> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/web/annotation/xfdf.md).

# Import and Export Annotations to PDF Viewer as XFDF

We show you how to use XFDF to format to import & export annotation data from a PDF document.

According to the XFDF specification:

> XFDF (XML Forms Data Format) is a format for representing forms data and annotations in a PDF document. XFDF is the XML version of Forms Data Format (FDF), a simplified version of PDF for representing forms data and annotations.

## Examples

{% tabs %}
{% tab title="XML" %}
{% code lineNumbers="true" %}

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
  <fields>
    <field name="ACombo"><value>Red</value></field>
  </fields>
  <annots>
    <square subject="Rectangle" page="0" rect="306.01,744.85,408.98,775.94" flags="print" name="447c49b7-5e50-4b13-adc8-c291102466e6" title="Guest" date="D:20171226120150-08'00'" color="#000000" width="5" creationdate="D:20171226120147-08'00'">
      <popup flags="print,nozoom,norotate" page="0" rect="0,767,112.5,842" open="no"/>
    </square>
  </annots>
</xfdf>
```

{% endcode %}
{% endtab %}
{% endtabs %}

The `fields` section contains the names and values of any form fields in the document. In `annots` all of the annotation data is found.

## In WebViewer

WebViewer provides methods to import annotations into the viewer from their XFDF data as well as export all currently loaded annotations as XFDF using [AnnotationManager](https://sdk.apryse.com/api/web/Core.AnnotationManager.html).

{% tabs %}
{% tab title="JavaScript (SDK v8.0+)" %}
{% code lineNumbers="true" %}

```js
WebViewer(...)
  .then(instance => {
    const { annotationManager } = instance.Core; 
    // import asynchronously
    // you might call this after fetching the XFDF data as a string from your server
    annotationManager.importAnnotations(xfdfData);

    // get all annotation and form data
    // you might call this when you want to pass the XFDF data to your server to be saved
    // or you may want to pass an XFDF string to doc.getFileData to embed the annotations
    // in the downloaded PDF
    annotationManager.exportAnnotations().then(xfdfData => { });

    // if you're saving the XFDF to your server and calling importAnnotations when loading
    // you may not want to save the widgets and links if they won't be changing in the document
    // this is because widgets and links don't have unique ids so WebViewer isn't always able
    // to merge them together without duplicating them when calling importAnnotations
    // as long as you save the field values then changes made to the fields (e.g. checking a checkbox)
    // will be saved
    // if you don't need to save field values either you can use "fields: false"
    annotationManager.exportAnnotations({
      widgets: false,
      links: false
      //fields: false
    }).then(annotData => { })

    // only get XFDF data for specified annotations
    // this might be useful if you save the XFDF data separately per user on your server
    // and you want to get the XFDF data for a particular user's annotations
    // it can also be useful if you want to get the XFDF for a particular annotation
    // because you're saving each annotation in a separate database row on your server
    annotationManager.exportAnnotations({
      annotList: [annot1, annot2]
    }).then(annotData => { })
  })
```

{% endcode %}

[WebViewerInstance](https://sdk.apryse.com/api/web/WebViewerInstance.html) [Core](https://sdk.apryse.com/api/web/Core.html) [AnnotationManager.importAnnotations](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#importAnnotations__anchor) [AnnotationManager.exportAnnotations](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#exportAnnotations__anchor)
{% endtab %}

{% tab title="JavaScript (SDK v6.0+)" %}
{% code lineNumbers="true" %}

```js
WebViewer(...)
  .then(instance => {
    const { annotManager } = instance; 
    // import asynchronously
    // you might call this after fetching the XFDF data as a string from your server
    annotManager.importAnnotations(xfdfData);

    // get all annotation and form data
    // you might call this when you want to pass the XFDF data to your server to be saved
    // or you may want to pass an XFDF string to doc.getFileData to embed the annotations
    // in the downloaded PDF
    annotManager.exportAnnotations().then(xfdfData => { });

    // if you're saving the XFDF to your server and calling importAnnotations when loading
    // you may not want to save the widgets and links if they won't be changing in the document
    // this is because widgets and links don't have unique ids so WebViewer isn't always able
    // to merge them together without duplicating them when calling importAnnotations
    // as long as you save the field values then changes made to the fields (e.g. checking a checkbox)
    // will be saved
    // if you don't need to save field values either you can use "fields: false"
    annotManager.exportAnnotations({
      widgets: false,
      links: false
      //fields: false
    }).then(annotData => { })

    // only get XFDF data for specified annotations
    // this might be useful if you save the XFDF data separately per user on your server
    // and you want to get the XFDF data for a particular user's annotations
    // it can also be useful if you want to get the XFDF for a particular annotation
    // because you're saving each annotation in a separate database row on your server
    annotManager.exportAnnotations({
      annotList: [annot1, annot2]
    }).then(annotData => { })
  })
```

{% endcode %}

[WebViewerInstance](https://sdk.apryse.com/api/web/WebViewerInstance.html) [AnnotationManager.importAnnotations](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#importAnnotations__anchor) [AnnotationManager.exportAnnotations](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#exportAnnotations__anchor)
{% endtab %}
{% endtabs %}

WebViewer also provides a way to get the XFDF data for annotations that have changed recently in the viewer. [AnnotationManager.exportAnnotationCommand](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#exportAnnotationCommand__anchor) will get the XFDF data for annotations that have been added, modified or deleted since the last time `exportAnnotationCommand` was called.

A command looks something like this:

{% tabs %}
{% tab title="XML" %}
{% code lineNumbers="true" %}

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
<fields />
<add>
  <text subject="Comment" page="0" rect="262.13,465.90,285.38,489.15" flags="print,nozoom,norotate" name="651eab92-9258-f676-b5c0-9767cb1ab932" title="Guest" date="D:20171226125004-08'00'" color="#FFFF00" opacity="0.5" creationdate="D:20171226125004-08'00'" icon="Comment">
    <popup flags="print,nozoom,norotate" page="0" rect="0,573,112.5,648" open="no"/>
  </text>
</add>
<modify>
  <text subject="Comment" page="0" rect="110.47,367.84,133.72,391.09" flags="print,nozoom,norotate" name="e89d6405-fdcc-aa2b-9ebb-cc9d8a525ca2" title="Guest" date="D:20171226125247-08'00'" color="#FFFF00" opacity="0.5" creationdate="D:20171226125238-08'00'" icon="Comment">
    <popup flags="print,nozoom,norotate" page="0" rect="0,573,112.5,648" open="no"/>
  </text>
</modify>
<delete>
  <id page="0">e2976b7b-075b-cad9-0f9f-fe0de613a543</id>
</delete>
</xfdf>
```

{% endcode %}
{% endtab %}
{% endtabs %}

Commands can be imported using [AnnotationManager.importAnnotationCommand](https://sdk.apryse.com/api/web/Core.AnnotationManager.html#importAnnotationCommand__anchor). This is the technique that is used in the [realtime collaboration example](/web/collaboration/realtime-collaboration.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/web/annotation/xfdf.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
