Adding free text annotations to a PDF document
Adding free text annotations to PDFs programmatically enables teams to automate document labeling, build watermarking systems, and implement visible commenting workflows. Whether you’re adding approval stamps, creating document headers, building caption systems, or implementing visible review notes, the free text annotation API provides complete control over text positioning, styling, and background colors. Unlike sticky note annotations that display as icons, free text annotations render text content directly on the page for immediate visibility.
How Nutrient helps you achieve this
Nutrient Python SDK handles PDF free text annotation structures and appearance generation. With the SDK, you don’t need to worry about:
- Parsing annotation dictionaries and text appearance streams
- Managing font embedding and character encoding
- Handling text layout and line breaking
- Complex coordinate transformations and rotation matrices
Instead, Nutrient provides an API that handles all the complexity behind the scenes, letting you focus on your business logic.
Complete implementation
Below is a complete working example that demonstrates adding free text annotations with various styles to a PDF. The following lines set up the Python application. The import statements bring in all the necessary classes from the Nutrient SDK:
from nutrient_sdk import Documentfrom nutrient_sdk import PdfEditorfrom nutrient_sdk import Colorfrom nutrient_sdk import NutrientExceptionThe main() function defines the entry point that will contain the free text annotation creation logic. The Document.open() call opens the PDF document. The context manager(opens in a new tab) syntax ensures the document is automatically closed when you’re done, preventing resource leaks. The following code creates a PDF editor, accesses the page collection, ensures at least one page exists by adding a letter-size page (612×792 points) if the document is empty, and retrieves 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()The following code adds a basic free text annotation at coordinates (50, 650) with dimensions 250×50 points. The add_free_text() method takes position coordinates (x, y), dimensions (width, height), author name, text content, font family (“Arial”), font size (12 points), and text color. The black text color is created using ARGB values (255, 0, 0, 0). The background defaults to transparent when the color property isn’t set:
black_color = Color.from_argb(255, 0, 0, 0) text_box = annotations.add_free_text( 50.0, 650.0, 250.0, 50.0, # x, y, width, height "Author", "This is a free text annotation that displays directly on the page.", "Arial", 12.0, black_color )The following code adds a warning annotation with a red text color (255, 0, 0) and a light yellow background (255, 255, 200). The color property sets the annotation’s background color, creating a highlighted appearance. This pattern is useful for warnings, alerts, or emphasizing critical information:
red_color = Color.from_argb(255, 255, 0, 0) warning_text = annotations.add_free_text( 50.0, 580.0, 250.0, 40.0, # x, y, width, height "Reviewer", "WARNING: This section requires review before publication.", "Arial", 14.0, red_color ) # Optionally set a background color warning_text.color = Color.from_argb(255, 255, 255, 200)The following code adds a note-style annotation with dark blue text (0, 0, 128) and a light blue background (200, 220, 255). The annotation uses Times New Roman font at 11 points and has a larger height (70 points) to accommodate multiple lines of text. Note-style annotations are commonly used for editorial comments or contextual explanations:
dark_blue = Color.from_argb(255, 0, 0, 128) note_text = annotations.add_free_text( 50.0, 480.0, 250.0, 70.0, # x, y, width, height "Editor", "Note: Consider adding more context to this paragraph. The reader may not be familiar with the terminology used here.", "Times New Roman", 11.0, dark_blue ) # Optionally set a background color note_text.color = Color.from_argb(255, 200, 220, 255)The following code demonstrates adding multiple styled annotations for document markup workflows. The first annotation creates an APPROVED stamp with dark green text (0, 100, 0), a light green background (200, 255, 200), and larger font size (18 points) for prominence. The second annotation creates a footer-style note using Courier New font at 9 points with gray text (100, 100, 100) and a light gray background (240, 240, 240). The footer spans 500 points wide to accommodate metadata text:
dark_green = Color.from_argb(255, 0, 100, 0)
approved_note = annotations.add_free_text( 350.0, 670.0, 200.0, 30.0, # x, y, width, height "Approver", "APPROVED", "Arial", 18.0, dark_green ) # Optionally set a background color approved_note.color = Color.from_argb(255, 200, 255, 200)
gray_text = Color.from_argb(255, 100, 100, 100)
footnote = annotations.add_free_text( 50.0, 50.0, 500.0, 50.0, # x, y, width, height "System", "Document last modified: 2024-01-15 | Review cycle: Annual", "Courier New", 9.0, gray_text ) # Optionally set a background color footnote.color = Color.from_argb(255, 240, 240, 240)The final code block saves the document with all free text annotations and closes the editor. The try-except block handles potential errors using NutrientException:
editor.save_as("output.pdf") editor.close() except NutrientException as e: print(f"Error: {e}")
if __name__ == "__main__": main()Conclusion
The free text annotation workflow consists of several key operations:
- Open the document and create an editor.
- Access the page collection and ensure at least one page exists.
- Retrieve the annotation collection for the target page.
- Add basic free text annotations with font, size, and text color specifications.
- Add colored annotations with background colors for emphasis using the
colorproperty. - Add note-style annotations with custom fonts and multiline text support.
- Add multiple styled annotations for comprehensive document markup (approvals, footers).
- Save and close the editor.
Nutrient handles free text annotation appearance streams and font embedding so you don’t need to understand PDF text rendering or manage character encoding manually.