Download pdf with annotations(fields data + signatures)

PDF.js Express Version

Detailed description of issue
Trying to download PDF document with added annotations by WebViewer UI using instance.downloadPdf, but instead get a file without annotations.

Expected behaviour
To download document with annotations added in Viewer.

Link to document

Code snippet

  .then(function(instance) {
    var docViewer = instance.docViewer;
    var annotManager = instance.annotManager;

    // you must have a document loaded when calling this api
    docViewer.on('documentLoaded', async function() {
      // download pdf without annotations added by WebViewer UI
        includeAnnotations: false,

      // download pdf with all annotations flattened
        includeAnnotations: true,
        flatten: true,

      // download pdf without links
      const xfdfString = await annotManager.exportAnnotations({ links: false });
        xfdfString: xfdfString,


PDF.js Express does not support flattening annotations on the client. To get this functionality, you can either use the merge rest API, or try out our sister product, PDFTron Webviewer (which has this functionality client side).


Thanks, @Logan

Could you please help with advice?
When I merged annotations with rest API, how is it possible to flatten it?
I want to get PDF document where all form fields and signature are read-only\static.

Hi there!

Before you export the annotations, you can loop over them and set them as readonly.

const { annotManager } = instance;
const list = annotManager.getAnnotationsList();

list.forEach(item => {
  item.ReadOnly = true

const xfdf = await annotManager.exportAnnotations();

Keep in mind that a lot of PDF viewers do not honour the ReadOnly flag, so the document may still be editable in some viewers.


Can I use the “merge rest API” without license key like as a trial?

	  const onSave = async () => {
	    const xfdf = await annotManager.exportAnnotations({ links: false, widgets: false });
	    const fileData = await docViewer.getDocument().getFileData({});

	    const data = new FormData();
	    data.append('xfdf', xfdf);
	    data.append('file', fileData);
	    data.append('license', 'my_license_key');

	    // Process the file
	    const response = await fetch('', {
	      method: 'post',
	      body: data
	    }).then(resp => resp.json());

	    const { url, key, id } = response;

	    // Download the file
	    const mergedFileBlob = await fetch(url, {
	      headers: {
	        Authorization: key
	    }).then(resp => resp.blob())

Yes! The API can be used without a license key, however please note that the output will be watermarked and/or mangled.