LibPDF

Annotations

Add highlights, links, sticky notes, shapes, stamps, and freehand drawings to PDF pages.

Annotations

Beta Feature

The annotations API is still in beta. While the core functionality is stable, the API may change in future releases.

PDF annotations add interactive and visual elements to pages - highlights, sticky notes, links, shapes, stamps, and freehand drawings.

import { PDF, rgb } from "@libpdf/core";

const pdf = PDF.create();
const page = pdf.addPage();

// Add a yellow highlight
page.addHighlightAnnotation({
  rect: { x: 100, y: 700, width: 200, height: 14 },
  color: rgb(1, 1, 0),
  contents: "Important text",
});

// Add a link
page.addLinkAnnotation({
  rect: { x: 100, y: 650, width: 150, height: 14 },
  uri: "https://example.com",
});

const bytes = await pdf.save();

Reading Annotations

const pdf = await PDF.load(existingBytes);
const page = pdf.getPage(0);

// Get all annotations
const annotations = page.getAnnotations();

for (const annot of annotations) {
  console.log(annot.type, annot.contents);
}

// Get specific types
const highlights = page.getHighlightAnnotations();
const links = page.getLinkAnnotations();

Text Markup Annotations

Mark up text with highlights, underlines, strikeouts, or squiggly lines.

addHighlightAnnotation(options)

ParamTypeDefaultDescription
rectRectSingle rectangle
rectsRect[]Multiple rectangles (multi-line)
quadPointsnumber[][]Raw quad points (rotated text)
colorColoryellowHighlight color
opacitynumber1Opacity (0-1)
contentsstringComment text
titlestringAuthor name

Returns: PDFHighlightAnnotation

// Simple highlight
page.addHighlightAnnotation({
  rect: { x: 100, y: 700, width: 200, height: 14 },
  color: rgb(1, 1, 0),
});

// Multi-line selection
page.addHighlightAnnotation({
  rects: [
    { x: 100, y: 700, width: 400, height: 14 },
    { x: 100, y: 680, width: 250, height: 14 },
  ],
  color: rgb(0.5, 1, 0.5),
});

addUnderlineAnnotation(options)

Same options as addHighlightAnnotation.

Returns: PDFUnderlineAnnotation

page.addUnderlineAnnotation({
  rect: { x: 100, y: 700, width: 200, height: 14 },
  color: rgb(0, 0, 1),
});

addStrikeOutAnnotation(options)

Same options as addHighlightAnnotation.

Returns: PDFStrikeOutAnnotation

page.addStrikeOutAnnotation({
  rect: { x: 100, y: 700, width: 200, height: 14 },
  color: rgb(1, 0, 0),
});

addSquigglyAnnotation(options)

Same options as addHighlightAnnotation. Draws a wavy underline.

Returns: PDFSquigglyAnnotation

page.addSquigglyAnnotation({
  rect: { x: 100, y: 700, width: 200, height: 14 },
  color: rgb(1, 0, 0),
});

addLinkAnnotation(options)

ParamTypeDefaultDescription
rectRectrequiredLink area
uristringExternal URL
destinationInternalLinkDestinationInternal page link
borderWidthnumber0Border width
borderColorColorBorder color

Returns: PDFLinkAnnotation

// External link
page.addLinkAnnotation({
  rect: { x: 100, y: 600, width: 200, height: 20 },
  uri: "https://example.com",
});

// Internal link to another page
const page2 = pdf.addPage();
page.addLinkAnnotation({
  rect: { x: 100, y: 550, width: 200, height: 20 },
  destination: { page: page2, type: "Fit" },
});

// With specific position
page.addLinkAnnotation({
  rect: { x: 100, y: 500, width: 200, height: 20 },
  destination: {
    page: page2,
    type: "XYZ",
    left: 72,
    top: 720,
    zoom: 1.5,
  },
});

Destination Types:

TypeDescriptionParameters
FitFit entire pagenone
FitHFit page widthtop
FitVFit page heightleft
XYZExplicit position and zoomleft, top, zoom
FitRFit rectanglerect: [l, b, r, t]

Text Annotations (Sticky Notes)

addTextAnnotation(options)

ParamTypeDefaultDescription
rectRectrequiredIcon position
contentsstringNote text
titlestringAuthor name
colorColoryellowBackground color
iconTextAnnotationIcon"Note"Icon type
openbooleanfalseShow popup immediately

Returns: PDFTextAnnotation

page.addTextAnnotation({
  rect: { x: 500, y: 700, width: 24, height: 24 },
  contents: "This is a comment",
  title: "Reviewer",
  color: rgb(1, 1, 0.7),
  icon: "Comment",
  open: true,
});

Icon Options: Note, Comment, Key, Help, NewParagraph, Paragraph, Insert


Shape Annotations

addLineAnnotation(options)

ParamTypeDefaultDescription
startPointrequiredStart point
endPointrequiredEnd point
colorColorblackLine color
widthnumber1Line width
startStyleLineEndingStyle"None"Start ending
endStyleLineEndingStyle"None"End ending
interiorColorColorFill for closed arrows
contentsstringComment

Returns: PDFLineAnnotation

// Simple line
page.addLineAnnotation({
  start: { x: 100, y: 500 },
  end: { x: 300, y: 500 },
  color: rgb(0, 0, 0),
  width: 2,
});

// With arrow
page.addLineAnnotation({
  start: { x: 100, y: 450 },
  end: { x: 300, y: 450 },
  color: rgb(1, 0, 0),
  endStyle: "ClosedArrow",
  interiorColor: rgb(1, 0, 0),
});

Line Ending Styles: None, Square, Circle, Diamond, OpenArrow, ClosedArrow, Butt, ROpenArrow, RClosedArrow, Slash


addSquareAnnotation(options)

ParamTypeDefaultDescription
rectRectrequiredRectangle bounds
colorColorblackStroke color
fillColorColorFill color
borderWidthnumber1Border width
contentsstringComment

Returns: PDFSquareAnnotation

page.addSquareAnnotation({
  rect: { x: 100, y: 400, width: 150, height: 100 },
  color: rgb(0, 0, 1),
  fillColor: rgb(0.9, 0.9, 1),
  borderWidth: 2,
});

addCircleAnnotation(options)

Same options as addSquareAnnotation. Draws an ellipse within the bounding rect.

Returns: PDFCircleAnnotation

page.addCircleAnnotation({
  rect: { x: 300, y: 400, width: 100, height: 100 },
  color: rgb(1, 0, 0),
  fillColor: rgb(1, 0.9, 0.9),
  borderWidth: 2,
});

Stamp Annotations

addStampAnnotation(options)

ParamTypeDefaultDescription
rectRectrequiredStamp bounds
nameStampName | string"Draft"Stamp type
contentsstringComment

Returns: PDFStampAnnotation

page.addStampAnnotation({
  rect: { x: 400, y: 500, width: 120, height: 40 },
  name: "Approved",
});

Standard Stamps: Approved, NotApproved, Draft, Final, Confidential, Experimental, Expired, NotForPublicRelease, ForPublicRelease, ForComment, TopSecret, Departmental, AsIs, Sold


Ink Annotations (Freehand)

addInkAnnotation(options)

ParamTypeDefaultDescription
pathsPoint[][]requiredArray of stroke paths
colorColorblackStroke color
widthnumber1Stroke width
contentsstringComment

Returns: PDFInkAnnotation

page.addInkAnnotation({
  paths: [
    [
      { x: 100, y: 300 },
      { x: 150, y: 350 },
      { x: 200, y: 300 },
    ],
  ],
  color: rgb(0, 0, 1),
  width: 2,
});

Modifying Annotations

const highlights = page.getHighlightAnnotations();
const highlight = highlights[0];

// Update properties
highlight.setContents("Updated comment");
highlight.setColor(rgb(0, 1, 0));
highlight.setHidden(false);
highlight.setPrintable(true);

Removing Annotations

removeAnnotation(annotation)

Remove a specific annotation.

const highlights = page.getHighlightAnnotations();
page.removeAnnotation(highlights[0]);

removeAnnotations(options?)

Remove annotations, optionally filtered by type.

ParamTypeDescription
[options.type]AnnotationSubtypeFilter by type
// Remove all highlights
page.removeAnnotations({ type: "Highlight" });

// Remove all annotations
page.removeAnnotations();

Common Properties

All annotations have these properties:

PropertyTypeDescription
typeAnnotationSubtypeAnnotation type
rectRectBounding rectangle
contentsstring | nullText content
colorColor | nullAnnotation color
isHiddenbooleanHidden state
isPrintablebooleanPrintable state
isModifiedbooleanModified state

Types

Rect

interface Rect {
  x: number; // Left edge
  y: number; // Bottom edge
  width: number;
  height: number;
}

Point

interface Point {
  x: number;
  y: number;
}

AnnotationFlags

import { AnnotationFlags } from "@libpdf/core";

// Check flags
if (annotation.hasFlag(AnnotationFlags.Print)) {
  console.log("Will print");
}

// Set flags
annotation.setFlag(AnnotationFlags.ReadOnly, true);
FlagDescription
InvisibleDon't display unknown types
HiddenDon't display or print
PrintPrint when page is printed
NoZoomDon't scale with zoom
NoRotateDon't rotate with page
NoViewDon't display on screen
ReadOnlyDon't allow interaction
LockedDon't allow deletion
LockedContentsDon't allow content changes

On this page