EmbedPDF

Annotations

The PDFViewer includes a powerful annotation system that supports highlights, ink drawings, shapes, and more. While the built-in toolbar provides a UI for these tools, you can also control them programmatically.

Configuration

You can configure annotation defaults like the author name using the annotation config object.

<PDFViewer config={{ annotation: { annotationAuthor: 'John Doe', } }} />

Programmatic Control

You can control the active tool and manage annotations programmatically.

Setting the Active Tool

Use setActiveTool to switch between tools. Pass null to switch back to the default selection cursor.

<script lang="ts"> import { PDFViewer, type PluginRegistry, type AnnotationPlugin } from '@embedpdf/svelte-pdf-viewer'; let registry = $state<PluginRegistry | null>(null); const handleReady = (r: PluginRegistry) => { registry = r; }; const activateHighlighter = () => { const annotationPlugin = registry?.getPlugin<AnnotationPlugin>('annotation')?.provides(); annotationPlugin?.setActiveTool('highlight'); }; const activatePen = () => { const annotationPlugin = registry?.getPlugin<AnnotationPlugin>('annotation')?.provides(); annotationPlugin?.setActiveTool('ink'); }; const deactivateTool = () => { const annotationPlugin = registry?.getPlugin<AnnotationPlugin>('annotation')?.provides(); annotationPlugin?.setActiveTool(null); }; </script> <PDFViewer onready={handleReady} config={{ src: '/doc.pdf' }} />

Common Tool IDs

ToolIDDescription
Highlight'highlight'Text highlighter
Underline'underline'Text underline
Ink (Pen)'ink'Freehand drawing
Rectangle'square'Square/Rectangle shape
Circle'circle'Circle/Ellipse shape
Text'freeText'Free text box
Note'text'Sticky note

Listening for Changes

You can listen for annotation events (creation, deletion, updates) to sync with a backend or update your UI.

<script lang="ts"> import { PDFViewer, type PluginRegistry } from '@embedpdf/svelte-pdf-viewer'; const handleReady = (registry: PluginRegistry) => { const annotationPlugin = registry.getPlugin('annotation')?.provides(); // Listen for creation, updates, and deletion annotationPlugin?.onAnnotationEvent((event) => { const { type, annotation, pageIndex } = event; if (type === 'create') { console.log('Created annotation:', annotation.id); // e.g. save to backend } else if (type === 'delete') { console.log('Deleted annotation:', annotation.id); } }); // Listen for tool changes annotationPlugin?.onActiveToolChange(({ tool }) => { console.log('Active tool:', tool ? tool.name : 'Selection'); }); }; </script> <PDFViewer onready={handleReady} config={{ src: '/doc.pdf' }} />

Importing and Exporting Annotations

You can export all annotations from a document and re-import them later. This is useful for saving annotation state to a backend or transferring annotations between sessions.

Exporting Annotations

exportAnnotations() returns a Task that resolves to an array of AnnotationTransferItem objects. Each item contains the annotation object and, for stamps, a ctx with the appearance data as an ArrayBuffer.

<script lang="ts"> import { PDFViewer, type PluginRegistry, type AnnotationPlugin, type AnnotationTransferItem, } from '@embedpdf/svelte-pdf-viewer'; let exported = $state<AnnotationTransferItem[] | null>(null); const handleReady = (registry: PluginRegistry) => { const api = registry.getPlugin<AnnotationPlugin>('annotation')?.provides(); api?.exportAnnotations().wait( (items) => { exported = items; console.log(`Exported ${items.length} annotations`); }, (error) => console.error('Export failed', error), ); }; </script> <PDFViewer onready={handleReady} config={{ src: '/doc.pdf' }} />

Importing Annotations

importAnnotations() accepts the same AnnotationTransferItem[] format returned by exportAnnotations(), making the round-trip seamless.

<script lang="ts"> api?.importAnnotations(exported); </script>

For stamps, the ctx.data field accepts a raw ArrayBuffer containing PNG, JPEG, or PDF data — the engine detects the format automatically via magic bytes.

Adding Custom Stamp Tools

You can register custom stamp tools that place images with a single click. Access the annotation API in the onready handler:

<script lang="ts"> import { PDFViewer, type PluginRegistry, type AnnotationPlugin, type AnnotationTool, PdfAnnotationSubtype, type PdfStampAnnoObject, } from '@embedpdf/svelte-pdf-viewer'; const handleReady = (registry: PluginRegistry) => { const api = registry.getPlugin<AnnotationPlugin>('annotation')?.provides(); api?.addTool<AnnotationTool<PdfStampAnnoObject>>({ id: 'stampCheckmark', name: 'Checkmark', interaction: { exclusive: true, cursor: 'crosshair' }, matchScore: () => 0, defaults: { type: PdfAnnotationSubtype.STAMP, imageSrc: '/circle-checkmark.png', imageSize: { width: 30, height: 30 }, }, behavior: { showGhost: true, deactivateToolAfterCreate: true, selectAfterCreate: true, }, }); }; </script> <PDFViewer onready={handleReady} config={{ src: '/doc.pdf' }} />
Last updated on March 31, 2026

Need Help?

Join our community for support, discussions, and to contribute to EmbedPDF's development.