Annotations

Annotations

This page covers creating, reading, searching, and flattening PDF annotations. Page exposes one Add*() method per annotation subtype, each returning a live Annotation handle; the Annotation base class and its subtypes (TextAnnotation, StampAnnotation, MarkupAnnotation, and others) expose the annotation’s properties for reading and editing.


Creating Markup, Note, and Link Annotations

The four text-markup methods — Page.AddHighlight(), Page.AddUnderline(), Page.AddSquiggly(), and Page.AddStrikeOut() — take a quads array (/QuadPoints) and return a MarkupAnnotation. Page.AddLink() creates a clickable region with a URI or internal action, and Page.AddTextNote() adds a sticky-note icon that opens a popup with contents text, returning a TextAnnotation.

page.AddHighlight({ quads, color: [1, 1, 0], contents: 'Yellow highlight' });
page.AddUnderline({ quads, color: [0, 0, 1] });
page.AddStrikeOut({ quads, color: [1, 0, 0] });

page.AddLink({
  rect: [100, 700, 220, 716],
  action: { type: 'uri', uri: 'https://example.com' },
  border: 0,
});

page.AddTextNote({
  rect: [x, y, x + 20, y + 20], icon: 'Note', author: 'Reviewer',
  contents: 'This is a sticky-note annotation.',
});

Page also exposes shape and freehand methods — AddSquare(), AddCircle(), AddLine(), AddPolygon(), AddPolyline(), AddInk(), AddFreeText(), AddCaret(), and AddStamp() — each returning the corresponding annotation handle for that subtype, generating its /AP appearance automatically.


Reading and Listing Annotations

page.Annotations is an array of every Annotation on the page. Every annotation, regardless of subtype, exposes Subtype, Rect, Color, Contents, Name, Layer, ModDate, Flags, Print, Hidden, and Opacity; subtypes add their own fields, such as StampAnnotation.StampName or MarkupAnnotation.QuadPoints.

const freeText = page.Annotations.find((a) => a.Subtype === 'FreeText');
if (freeText) {
  freeText.Contents = 'Updated note text';
}

Searching Annotation Text

Page.SearchAnnotationText() and Page.SearchAnnotations() are deliberately disjoint. SearchAnnotationText() finds matches in the text an annotation carries rather than draws — a note’s /Contents, its author (/T), or its subject (/Subj) — and returns AnnotationTextMatch[] ({ annot, key, value, text }). SearchAnnotations() finds matches in the text an annotation draws, such as a FreeText’s visible words, and returns AnnotationMatch[] ({ annot, text, quads }).

// A sticky note's /Contents text — found by SearchAnnotationText, not SearchAnnotations.
const textHits = page.SearchAnnotationText('body secret');
console.log(textHits[0].key, textHits[0].value); // 'Contents' 'body secret'

// A FreeText's rendered words — found by SearchAnnotations, not SearchAnnotationText.
const drawnHits = page.SearchAnnotations('bravo');

Flattening Annotations

Annotation.Flatten() bakes an annotation’s /AP appearance directly into the page’s content stream at its /Rect, then drops it from /Annots. The result is permanent, static content — no longer a distinct annotation a viewer can click, edit, or hide.

const note = page.AddTextNote({
  rect: [72, 660, 92, 680], icon: 'Comment', contents: 'Reviewed and approved.',
});
note.Flatten();

Tips and Best Practices

  • Call Flatten() on the object returned directly by the Add*() call — an annotation obtained by re-reading page.Annotations afterward is a different object reference.
  • SearchAnnotationText() and SearchAnnotations() cover different text: run both if you need to find a phrase regardless of whether it was typed into a note or drawn on the page.
  • The four markup methods (AddHighlight, AddUnderline, AddSquiggly, AddStrikeOut) generate their /AP appearance automatically — no manual content-stream drawing is required.
  • Encryption survives a round trip: annotations added before Document.Save() with an encrypt option remain valid after the document is reopened and decrypted.

Common Issues

IssueCauseFix
page.Annotations.find() returns undefined for an annotation you just addedSearching a stale array captured before the annotation was addedRe-read page.Annotations after the Add*() call, or use the handle the call returned directly
SearchAnnotationText() finds nothing for text visible on the pageThe text is drawn by the annotation (e.g. a FreeText’s body), not carried in /ContentsUse SearchAnnotations() instead — it matches drawn text
Annotation still appears editable after Flatten()Flatten() was called on a copy rather than the handle Add*() returnedCall Flatten() on the object returned directly by the creating method

FAQ

What is the difference between SearchAnnotationText and SearchAnnotations?

SearchAnnotationText() matches text an annotation carries/Contents, /T (author), or /Subj — such as a sticky note’s body. SearchAnnotations() matches text an annotation draws on the page, such as a FreeText’s visible words. The two are disjoint: a match in one will not appear in the other.

How do I make an annotation permanent and non-interactive?

Call Flatten() on the Annotation handle returned by the Add*() method that created it. This bakes its appearance into the page’s content stream and removes it from /Annots.

Which annotation subtypes are supported?

Page exposes creation methods for text markup (AddHighlight, AddUnderline, AddSquiggly, AddStrikeOut), notes and callouts (AddTextNote, AddFreeText, AddCaret), links (AddLink), shapes (AddSquare, AddCircle, AddLine, AddPolygon, AddPolyline), freehand ink (AddInk), stamps (AddStamp), and file attachments (AddFileAttachment).

How do I list every annotation already on a page?

Read page.Annotations, an array of Annotation handles. Each exposes Subtype, Rect, Color, Contents, and the other shared properties, so you can filter or inspect them with standard array methods.


API Reference Summary

Class/MethodDescription
AnnotationBase handle over any annotation; exposes Subtype, Rect, Color, Contents, Name, Flags, Print, Hidden, Opacity
Annotation.Flatten()Bake the annotation’s appearance into static page content
TextAnnotationA /Text sticky-note handle; adds Icon, Open, Author
StampAnnotationA /Stamp rubber-stamp handle; adds StampName
MarkupAnnotationA text-markup handle (Highlight/Underline/StrikeOut/Squiggly); adds MarkupType, QuadPoints
Page.AddHighlight() / Page.AddUnderline() / Page.AddStrikeOut() / Page.AddSquiggly()Create a text-markup annotation over /QuadPoints
Page.AddTextNote()Create a sticky-note annotation
Page.AddLink()Create a clickable link with a URI or internal action
Page.AnnotationsEvery Annotation on the page, as an array
Page.SearchAnnotationText()Find text an annotation carries (/Contents, /T, /Subj)
Page.SearchAnnotations()Find text an annotation draws on the page

See Also