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 theAdd*()call — an annotation obtained by re-readingpage.Annotationsafterward is a different object reference. SearchAnnotationText()andSearchAnnotations()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/APappearance automatically — no manual content-stream drawing is required. - Encryption survives a round trip: annotations added before
Document.Save()with anencryptoption remain valid after the document is reopened and decrypted.
Common Issues
| Issue | Cause | Fix |
|---|---|---|
page.Annotations.find() returns undefined for an annotation you just added | Searching a stale array captured before the annotation was added | Re-read page.Annotations after the Add*() call, or use the handle the call returned directly |
SearchAnnotationText() finds nothing for text visible on the page | The text is drawn by the annotation (e.g. a FreeText’s body), not carried in /Contents | Use SearchAnnotations() instead — it matches drawn text |
Annotation still appears editable after Flatten() | Flatten() was called on a copy rather than the handle Add*() returned | Call 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/Method | Description |
|---|---|
Annotation | Base 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 |
TextAnnotation | A /Text sticky-note handle; adds Icon, Open, Author |
StampAnnotation | A /Stamp rubber-stamp handle; adds StampName |
MarkupAnnotation | A 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.Annotations | Every 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 |