Adding shape annotations to a PDF document
Use shape annotations to add structured visual markup to PDF files.
Common use cases include:
- Architectural markups
- Diagram and technical drawing tools
- Review workflows with callouts
- Region highlighting and boundary marking
In this guide, you’ll add:
- Lines with configurable ending styles
- Circles and ellipses
- Squares and rectangles
- Custom colors and line widths
How Nutrient helps
Nutrient Python SDK handles shape annotation structures and rendering.
The SDK handles:
- Parsing shape annotation dictionaries and path construction
- Managing stroke and fill operations with appearance streams
- Handling geometric calculations and coordinate transformations
- Complex line ending styles and cap rendering
Complete implementation
This example adds multiple shape annotations to a PDF file:
from nutrient_sdk import Documentfrom nutrient_sdk import PdfEditorfrom nutrient_sdk import Colorfrom nutrient_sdk import PdfLineEndingStylefrom nutrient_sdk import NutrientExceptionWorking with shape annotations
Open the document in a context manager(opens in a new tab) to ensure cleanup after processing.
Then:
- Create a PDF editor.
- Get the page collection.
- Add a letter-size page (
612 × 792) if the document is empty. - Get the annotation collection from the first page.
def main(): try: with Document.open("input.pdf") as document: editor = PdfEditor.edit(document) pages = editor.get_page_collection()
if pages.get_count() == 0: pages.add(612.0, 792.0)
page = pages.get_first() annotations = page.get_annotation_collection()Adding a line annotation
Create a line with add_line(start_x, start_y, end_x, end_y, author, content).
This example adds a horizontal line from (50, 700) to (200, 700):
By default, the SDK uses:
- Black stroke color (
ARGB 255, 0, 0, 0) 1.0point line width
line = annotations.add_line( 50.0, 700.0, 200.0, 700.0, # start_x, start_y, end_x, end_y "Author", "Simple horizontal line" )Adding a line with arrow endings
Create a second line and customize its style.
This example:
- Draws a diagonal line from
(50, 650)to(200, 600). - Sets
end_captoPdfLineEndingStyle.CLOSED_ARROW. - Sets the color to blue with
Color.from_argb(255, 0, 0, 255). - Sets the line width to
2.0.
Set ending styles on both start_cap and end_cap:
arrow = annotations.add_line( 50.0, 650.0, 200.0, 600.0, # start_x, start_y, end_x, end_y "Reviewer", "Arrow pointing to important area" ) # Optionally customize the line arrow.end_cap = PdfLineEndingStyle.CLOSED_ARROW arrow.color = Color.from_argb(255, 0, 0, 255) arrow.line_width = 2.0Available line ending styles from the PdfLineEndingStyle enumeration include:
NONE— No ending (default)SQUARE— Square ending for boundary indicatorsCIRCLE— Circular ending for connection pointsDIAMOND— Diamond shape for decision pointsOPEN_ARROW— Open arrowhead for directional indicatorsCLOSED_ARROW— Filled arrowhead for emphasisBUTT— Perpendicular line for measurement marksREVERSE_OPEN_ARROW— Reverse open arrow for backward directionREVERSE_CLOSED_ARROW— Reverse closed arrow for backward emphasisSLASH— Slash mark for termination indicators
Adding a circle annotation
Create a circle with add_circle(x, y, width, height, author, content).
In this sample:
- The bounds are
x=250,y=550,width=100, andheight=100. - Equal width and height produce a circle.
- Unequal values produce an ellipse.
- The style is updated to green and a
2.0point line width.
circle = annotations.add_circle( 250.0, 550.0, 100.0, 100.0, # x, y, width, height "Editor", "Area of interest" ) # Optionally customize the appearance circle.color = Color.from_argb(255, 0, 128, 0) circle.line_width = 2.0Adding a square annotation
Create a square or rectangle with add_square(x, y, width, height, author, content).
In this sample:
- The bounds are
x=400,y=550,width=150, andheight=100. - Equal width and height produce a square.
- Unequal values produce a rectangle.
- The style is updated to purple and a
2.0point line width.
square = annotations.add_square( 400.0, 550.0, 150.0, 100.0, # x, y, width, height "Reviewer", "Section to review" ) # Optionally customize the appearance square.color = Color.from_argb(255, 128, 0, 128) square.line_width = 2.0Combining multiple shapes
Use consistent styling across multiple shapes to build one markup set.
This sample creates:
- A callout line with an open arrow
- An ellipse highlight
- A rectangular selection box
All three use:
- An orange stroke (
ARGB 255, 255, 165, 0). 1.5point line width.
callout_line = annotations.add_line( 50.0, 500.0, 150.0, 450.0, # start_x, start_y, end_x, end_y "Author", "Callout line" ) callout_line.end_cap = PdfLineEndingStyle.OPEN_ARROW callout_line.color = Color.from_argb(255, 255, 165, 0) callout_line.line_width = 1.5
highlight_circle = annotations.add_circle( 150.0, 420.0, 100.0, 60.0, # x, y, width, height "Author", "Highlighted area" ) highlight_circle.color = Color.from_argb(255, 255, 165, 0) highlight_circle.line_width = 1.5
selection_box = annotations.add_square( 260.0, 420.0, 100.0, 60.0, # x, y, width, height "Author", "Selection box" ) selection_box.color = Color.from_argb(255, 255, 165, 0) selection_box.line_width = 1.5Saving the document
Save the output PDF and close the editor.
The except block catches NutrientException if processing fails:
editor.save_as("output.pdf") editor.close() except NutrientException as e: print(f"Error: {e}")
if __name__ == "__main__": main()Conclusion
Use this workflow to add shape annotations:
- Open the document using a context manager(opens in a new tab) for automatic resource cleanup.
- Create an editor and access the page collection.
- Ensure at least one page exists by adding a letter-size page if needed.
- Retrieve the annotation collection from the target page.
- Create line annotations with
add_line()specifying start and end coordinates. - Customize line endings using
start_capandend_capproperties withPdfLineEndingStylevalues. - Create circle annotations with
add_circle()for highlighting regions (equal dimensions create perfect circles). - Create square annotations with
add_square()for boundary marking (equal dimensions create perfect squares). - Combine multiple shapes with consistent styling for unified visual markup systems.
- Save and close the editor.
For related annotation workflows, refer to the Python SDK annotation guides.