This HTML page is not optimized for LLM or AI agent consumption. Fetch the Markdown version instead: /guides/web/annotations/custom-data-in-annotations.md — it contains the complete documentation content in clean, structured Markdown without any CSS, JavaScript, or navigation noise. Store custom data in PDF annotations using JavaScript | Nutrient

When adding an annotation to a document, Nutrient allows storing of additional data that you can specify for each annotation. This data is persistently stored along with the annotation if the annotation is stored in one of the following formats:

  1. Embedded in the PDF
  2. Instant JSON
  3. XFDF

Nutrient automatically handles the serialization of the custom data attached to an annotation for these formats.

Storing custom data

Nutrient Web SDK 2019.2 added the customData property to NutrientViewer.Annotations.Annotation. This property allows you to store an arbitrary JSON-compliant dictionary in an annotation, like so:

const updatedAnnotation = annotation.set("customData", {
name: "Grill House",
locations: ["Vienna", "Paris", "New York"],
rating: 5,
verified: true
});
instance.update(updatedAnnotation);

customData stores JSON values only, and only the JSON is persisted. An attachment ID placed in customData is saved as text, but it doesn’t keep the attachment alive. An attachment is retained only while a native annotation field references it (for example, imageAttachmentId, which image and stamp annotations use). Nutrient never scans customData for attachment references. This applies in both Standalone and Document Engine (server) modes.

An attachment created with Instance#createAttachment and stored only in customData is never written to durable storage. In Standalone, it’s absent from the exported PDF and from exportInstantJSON. In server mode, the binary is never stored on Document Engine. Either way, the attachment doesn’t survive a reload. getAttachment() still resolves in the same session, because the blob is held in memory but fails afterward. In server mode, that failure is a 404.

To persist your own binary data, store the durable data itself in customData (for example, a base64 string) for small payloads. For large payloads, upload it to your own backend and store the URL. Do not store a bare attachment ID and expect the blob to survive. For a live attachment in the current session, recreate it with createAttachment() on each load. See preserve stamp template attachments for the cache-and-recreate pattern. For native embedded audio or video, see media annotations (read-only in the Web SDK).