---
title: "Creating and filling PDF forms programmatically in JavaScript"
canonical_url: "https://www.nutrient.io/blog/creating-and-filling-pdf-forms-programmatically-in-javascript/"
md_url: "https://www.nutrient.io/blog/creating-and-filling-pdf-forms-programmatically-in-javascript.md"
last_updated: "2026-08-25T10:48:10.057Z"
description: "Create PDF forms with text fields, checkboxes, radio buttons, and signatures in JavaScript. Fill forms from JSON, XFDF, or a database using Nutrient Web SDK."
---

**TL;DR**

Create PDF forms with text fields, checkboxes, radio buttons, and signatures using [Nutrient Web SDK](https://www.nutrient.io/sdk/web/). Fill forms programmatically from [Instant JSON](https://www.nutrient.io/guides/web/json.md), XFDF, or a database.

PDF forms automate data collection for applications, contracts, surveys, and onboarding workflows. This tutorial shows how to [create form fields](https://www.nutrient.io/sdk/form-creator/) programmatically and populate them with data.

**What you’ll build:**

- Text inputs, checkboxes, radio buttons, and a signature field

- Prefilled forms using JSON or XFDF

- Database-driven form population

## Display a PDF

1. Create a project directory:

   ```bash

   mkdir CreatingPdfForms
   cd CreatingPdfForms
   npm init -y
   ```

2. Install Nutrient and Vite:

   ```bash

   npm install @nutrient-sdk/viewer
   npm install -D vite
   ```

The `useCDN: true` option loads SDK assets from Nutrient's CDN, so no manual asset copying is required.

3. Add a PDF document named `document.pdf` to your project’s root directory.![image showing a screenshot of the pdf and its contents](@/assets/images/blog/2023/creating-and-filling-pdf-forms-programmatically-in-javascript/pdf-screenshot.png)

4. Create `index.html` and `index.js`:

   ```bash

   touch index.html index.js
   ```

5. Add this to `index.js`:

   ```js

   (async () => {
     const NutrientViewer = (await import("@nutrient-sdk/viewer")).default;
     const container = document.getElementById("pspdfkit");

     NutrientViewer.load({
       container,
       document: "document.pdf",
       useCDN: true,
     }).then((instance) => {
         console.log("Nutrient loaded", instance);
       }).catch((error) => {
         console.error(error.message);
       });
   })();
   ```

6. Add this to `index.html`:

   ```html

   <!DOCTYPE html>
   <html>
     <head>
       <title>PDF Forms</title>
       <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     </head>
     <body>
       <div id="pspdfkit" style="width: 100%; height: 100vh;"></div>
       <script type="module" src="index.js"></script>
     </body>
   </html>
   ```

7. Start the dev server:

   ```bash

   npx vite
   ```

## Add form fields

Each form field needs two parts: a widget annotation (position and size) and a form field (type and behavior).

The widget annotation defines where the field appears:

```js

const firstNameWidget = new NutrientViewer.Annotations.WidgetAnnotation({
  id: NutrientViewer.generateInstantId(),
  pageIndex: 0,
  formFieldName: "First Name",
  boundingBox: new NutrientViewer.Geometry.Rect({
    left: 115,
    top: 98,
    width: 200,
    height: 25,
  }),
});

```

The form field defines the field type and links to the widget:

```js

const firstNameFormField = new NutrientViewer.FormFields.TextFormField({
  name: "First Name",
  annotationIds: new NutrientViewer.Immutable.List([firstNameWidget.id]),
});

```

Create both together:

```js

await instance.create([firstNameWidget, firstNameFormField]);

```

This is the signature field:

```js

const signatureWidget = new NutrientViewer.Annotations.WidgetAnnotation({
  id: NutrientViewer.generateInstantId(),
  pageIndex: 0,
  boundingBox: new NutrientViewer.Geometry.Rect({
    left: 43,
    top: 325,
    width: 150,
    height: 75,
  }),
  formFieldName: "Signature",
});

const signatureFormField = new NutrientViewer.FormFields.SignatureFormField({
  name: "Signature",
  annotationIds: new NutrientViewer.Immutable.List([signatureWidget.id]),
});

await instance.create([signatureWidget, signatureFormField]);

```

Radio buttons and checkboxes use multiple widget annotations for different values:

```js

// Radio button widgets.
const yesRadioWidget = new NutrientViewer.Annotations.WidgetAnnotation({
  id: NutrientViewer.generateInstantId(),
  pageIndex: 0,
  formFieldName: "Human",
  boundingBox: new NutrientViewer.Geometry.Rect({
    left: 80, top: 188, width: 20, height: 20,
  }),
});

const noRadioWidget = new NutrientViewer.Annotations.WidgetAnnotation({
  id: NutrientViewer.generateInstantId(),
  pageIndex: 0,
  formFieldName: "Human",
  boundingBox: new NutrientViewer.Geometry.Rect({
    left: 80, top: 214, width: 20, height: 20,
  }),
});

const maybeRadioWidget = new NutrientViewer.Annotations.WidgetAnnotation({
  id: NutrientViewer.generateInstantId(),
  pageIndex: 0,
  formFieldName: "Human",
  boundingBox: new NutrientViewer.Geometry.Rect({
    left: 80, top: 240, width: 20, height: 20,
  }),
});

const radioFormField = new NutrientViewer.FormFields.RadioButtonFormField({
  name: "Human",
  annotationIds: new NutrientViewer.Immutable.List([
    yesRadioWidget.id,
    noRadioWidget.id,
    maybeRadioWidget.id,
  ]),
  options: new NutrientViewer.Immutable.List([
    new NutrientViewer.FormOption({ label: "Yes", value: "1" }),
    new NutrientViewer.FormOption({ label: "No", value: "2" }),
    new NutrientViewer.FormOption({ label: "Maybe", value: "3" }),
  ]),
  defaultValue: "Maybe",
});

// Checkbox
const checkBoxWidget = new NutrientViewer.Annotations.WidgetAnnotation({
  id: NutrientViewer.generateInstantId(),
  pageIndex: 0,
  formFieldName: "Fun",
  boundingBox: new NutrientViewer.Geometry.Rect({
    left: 128, top: 269.5, width: 20, height: 20,
  }),
});

const checkBoxFormField = new NutrientViewer.FormFields.CheckBoxFormField({
  name: "Fun",
  annotationIds: new NutrientViewer.Immutable.List([checkBoxWidget.id]),
  options: new NutrientViewer.Immutable.List([
    new NutrientViewer.FormOption({ label: "FunCheck", value: "1" }),
  ]),
});

await instance.create([
  yesRadioWidget, noRadioWidget, maybeRadioWidget, radioFormField,
  checkBoxWidget, checkBoxFormField,
]);

```

Here's a complete example for [creating all form fields](https://www.nutrient.io/sdk/form-creator/):

```js

(async () => {
  const NutrientViewer = (await import("@nutrient-sdk/viewer")).default;
  const container = document.getElementById("pspdfkit");

  NutrientViewer.load({
    container,
    document: "document.pdf",
    useCDN: true,
  }).then(async (instance) => {
      console.log("Nutrient loaded", instance);

		// Creating the first name text form field.
		const firstNameWidget = new NutrientViewer.Annotations.WidgetAnnotation(
			{
				id: NutrientViewer.generateInstantId(),
				pageIndex: 0,
				formFieldName: 'First Name',
				boundingBox: new NutrientViewer.Geometry.Rect({
					left: 115,
					top: 98,
					width: 200,
					height: 25,
				}),
			},
		);

		const firstNameFormField = new NutrientViewer.FormFields.TextFormField({
			name: 'First Name',
			annotationIds: new NutrientViewer.Immutable.List([
				firstNameWidget.id,
			]),
		});

		// Creating the last name text form field.
		const lastNameWidget = new NutrientViewer.Annotations.WidgetAnnotation({
			id: NutrientViewer.generateInstantId(),
			pageIndex: 0,
			formFieldName: 'Last Name',
			boundingBox: new NutrientViewer.Geometry.Rect({
				left: 115,
				top: 128,
				width: 200,
				height: 25,
			}),
		});

		const lastNameFormField = new NutrientViewer.FormFields.TextFormField({
			name: 'Last Name',
			annotationIds: new NutrientViewer.Immutable.List([
				lastNameWidget.id,
			]),
		});

		// Creating a new radio button form field.
		const yesRadioWidget = new NutrientViewer.Annotations.WidgetAnnotation({
			id: NutrientViewer.generateInstantId(),
			pageIndex: 0,
			formFieldName: 'Human',
			boundingBox: new NutrientViewer.Geometry.Rect({
				left: 80,
				top: 188,
				width: 20,
				height: 20,
			}),
		});

		const noRadioWidget = new NutrientViewer.Annotations.WidgetAnnotation({
			id: NutrientViewer.generateInstantId(),
			pageIndex: 0,
			formFieldName: 'Human',
			boundingBox: new NutrientViewer.Geometry.Rect({
				left: 80,
				top: 214,
				width: 20,
				height: 20,
			}),
		});

		const maybeRadioWidget = new NutrientViewer.Annotations.WidgetAnnotation(
			{
				id: NutrientViewer.generateInstantId(),
				pageIndex: 0,
				formFieldName: 'Human',
				boundingBox: new NutrientViewer.Geometry.Rect({
					left: 80,
					top: 240,
					width: 20,
					height: 20,
				}),
			},
		);

		const radioFormField = new NutrientViewer.FormFields.RadioButtonFormField(
			{
				name: 'Human',
				annotationIds: new NutrientViewer.Immutable.List([
					yesRadioWidget.id,
					noRadioWidget.id,
					maybeRadioWidget.id,
				]),
				options: new NutrientViewer.Immutable.List([
					new NutrientViewer.FormOption({
						label: 'Yes',
						value: '1',
					}),
					new NutrientViewer.FormOption({
						label: 'No',
						value: '2',
					}),
					new NutrientViewer.FormOption({
						label: 'Maybe',
						value: '3',
					}),
				]),
				defaultValue: 'Maybe',
			},
		);

		// Creating a new checkbox form field.
		const checkBoxWidget = new NutrientViewer.Annotations.WidgetAnnotation({
			id: NutrientViewer.generateInstantId(),
			pageIndex: 0,
			formFieldName: 'Fun',
			boundingBox: new NutrientViewer.Geometry.Rect({
				left: 128,
				top: 269.5,
				width: 20,
				height: 20,
			}),
		});

		const checkBoxFormField = new NutrientViewer.FormFields.CheckBoxFormField(
			{
				name: 'Fun',
				annotationIds: new NutrientViewer.Immutable.List([
					checkBoxWidget.id,
				]),
				options: new NutrientViewer.Immutable.List([
					new NutrientViewer.FormOption({
						label: 'FunCheck',
						value: '1',
					}),
				]),
			},
		);

		// Creating a new signature form field.
		const signatureWidget = new NutrientViewer.Annotations.WidgetAnnotation(
			{
				id: NutrientViewer.generateInstantId(),
				pageIndex: 0,
				boundingBox: new NutrientViewer.Geometry.Rect({
					left: 43,
					top: 325,
					width: 150,
					height: 75,
				}),
				formFieldName: 'Signature',
			},
		);

		const signatureFormField = new NutrientViewer.FormFields.SignatureFormField(
			{
				name: 'Signature',
				annotationIds: new NutrientViewer.Immutable.List([
					signatureWidget.id,
				]),
			},
		);

		await instance.create([
			firstNameWidget,
			firstNameFormField,
			lastNameWidget,
			lastNameFormField,
			yesRadioWidget,
			noRadioWidget,
			maybeRadioWidget,
			radioFormField,
			checkBoxWidget,
			checkBoxFormField,
			signatureWidget,
			signatureFormField,
		]);
    }).catch((error) => {
      console.error(error.message);
    });
})();

```![Form field creation result](@/assets/images/blog/2023/creating-and-filling-pdf-forms-programmatically-in-javascript/form-field-creation.gif)

Now, export the resulting document and use it in the next section to fill out the form fields. To do that, add the following after `instance.create();`:

```js

instance.exportPDF().then((buffer) => {
  const blob = new Blob([buffer], { type: "application/pdf" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = "document.pdf";
  a.click();
  URL.revokeObjectURL(url);
});

```

Refresh your app in the browser to get a copy of the document with the form fields.![gif showing the result of 'instance.exportPDF()'](@/assets/images/blog/2023/creating-and-filling-pdf-forms-programmatically-in-javascript/export-pdf.gif)

<!---

> Interact with the sandbox by clicking the left rectangle icon and selecting Editor > Show Default Layout. To edit, sign in with GitHub — click the rectangle icon again and choose Sign in. To preview the result, click the rectangle icon once more and choose Editor > Embed Preview. For the full example, click the Open Editor button. Enjoy experimenting with the project!

--->

## Fill forms with Instant JSON

Now that you have a form with fields, let's explore how to populate them programmatically with data.

Use the exported PDF from the previous section. First, check what fields exist:

```js

const formFieldValues = instance.getFormFieldValues();
console.log(formFieldValues);

```![image showing the result of 'console.log(formFieldValues);'](@/assets/images/blog/2023/creating-and-filling-pdf-forms-programmatically-in-javascript/form-fields-data-log.png)

Keys are field names, and values are `null`, `string`, or `Array<string>`.

Pass form values in the `instantJSON` option:

```js

instantJSON: {
  format: "https://pspdfkit.com/instant-json/v1",
  formFieldValues: [
    {
      name: "First Name",
      value: "John",
      type: "pspdfkit/form-field-value",
      v: 1,
    },
    {
      name: "Last Name",
      value: "Appleseed",
      type: "pspdfkit/form-field-value",
      v: 1,
    },
    {
      name: "Human",
      value: "3",
      type: "pspdfkit/form-field-value",
      v: 1,
    },
    {
      name: "Fun",
      value: "1",
      type: "pspdfkit/form-field-value",
      v: 1,
    },
  ],
}

```

Signature fields require an ink annotation instead of a value. The code below draws a simple “X” signature by creating two diagonal lines within the signature field's boundaries:

```js

// The name of the signature field you want.
//
const formFieldName = 'Signature';

// First, get all `FormFields` in the `Document`.
//
const formFields = await instance.getFormFields();

// Get a signature form with the specific name you want.
//
const field = formFields.find(
	(formField) =>
		formField.name === formFieldName &&
		formField instanceof NutrientViewer.FormFields.SignatureFormField,
);

// In this example, assume the widget you need is on the first page.
//
const annotations = await instance.getAnnotations(0);

// Find that widget.
//
const widget = annotations.find(
	(annotation) =>
		annotation instanceof NutrientViewer.Annotations.WidgetAnnotation &&
		annotation.formFieldName === field.name,
);

// Make a new ink annotation.
//
const annotation = new NutrientViewer.Annotations.InkAnnotation({
	pageIndex: 0,
	lines: NutrientViewer.Immutable.List([
		NutrientViewer.Immutable.List([
			new NutrientViewer.Geometry.DrawingPoint({
				x: widget.boundingBox.left + 10,
				y: widget.boundingBox.top + 10,
			}),
			new NutrientViewer.Geometry.DrawingPoint({
				x: widget.boundingBox.left + widget.boundingBox.width - 10,
				y: widget.boundingBox.top + widget.boundingBox.height - 10,
			}),
		]),
		NutrientViewer.Immutable.List([
			new NutrientViewer.Geometry.DrawingPoint({
				x: widget.boundingBox.left + widget.boundingBox.width - 10,
				y: widget.boundingBox.top + 10,
			}),
			new NutrientViewer.Geometry.DrawingPoint({
				x: widget.boundingBox.left + 10,
				y: widget.boundingBox.top + widget.boundingBox.height - 10,
			}),
		]),
	]),
	boundingBox: widget.boundingBox,
	isSignature: true,
});

instance.create(annotation);

```

Here’s a complete example for filling form fields and adding a signature:

```js

(async () => {
  const NutrientViewer = (await import("@nutrient-sdk/viewer")).default;
  const container = document.getElementById("pspdfkit");

  NutrientViewer.load({
    container,
    document: "document.pdf",
    useCDN: true,
    instantJSON: {
      format: "https://pspdfkit.com/instant-json/v1",
      formFieldValues: [
        { name: "First Name", value: "John", type: "pspdfkit/form-field-value", v: 1 },
        { name: "Last Name", value: "Appleseed", type: "pspdfkit/form-field-value", v: 1 },
        { name: "Human", value: "3", type: "pspdfkit/form-field-value", v: 1 },
        { name: "Fun", value: "1", type: "pspdfkit/form-field-value", v: 1 },
      ],
    },
  }).then(async (instance) => {
      console.log("Nutrient loaded", instance);

      // Get the signature field.
      const formFields = await instance.getFormFields();
      const field = formFields.find(
        (f) => f.name === "Signature" && f instanceof NutrientViewer.FormFields.SignatureFormField
      );
      if (!field) return;

      // Get the widget annotation.
      const annotations = await instance.getAnnotations(0);
      const widget = annotations.find(
        (a) => a instanceof NutrientViewer.Annotations.WidgetAnnotation && a.formFieldName === field.name
      );
      if (!widget) return;

      // Create an ink annotation as the signature.
      const annotation = new NutrientViewer.Annotations.InkAnnotation({
        pageIndex: 0,
        lines: NutrientViewer.Immutable.List([
          NutrientViewer.Immutable.List([
            new NutrientViewer.Geometry.DrawingPoint({ x: widget.boundingBox.left + 10, y: widget.boundingBox.top + 10 }),
            new NutrientViewer.Geometry.DrawingPoint({ x: widget.boundingBox.left + widget.boundingBox.width - 10, y: widget.boundingBox.top + widget.boundingBox.height - 10 }),
          ]),
          NutrientViewer.Immutable.List([
            new NutrientViewer.Geometry.DrawingPoint({ x: widget.boundingBox.left + widget.boundingBox.width - 10, y: widget.boundingBox.top + 10 }),
            new NutrientViewer.Geometry.DrawingPoint({ x: widget.boundingBox.left + 10, y: widget.boundingBox.top + widget.boundingBox.height - 10 }),
          ]),
        ]),
        boundingBox: widget.boundingBox,
        isSignature: true,
      });

      instance.create(annotation);
    }).catch((error) => {
      console.error(error.message);
    });
})();

```![Form fields filled with Instant JSON](@/assets/images/blog/2023/creating-and-filling-pdf-forms-programmatically-in-javascript/filling-form-fields-instance-json.gif)

## Fill forms with XFDF

XFDF is an XML format for form data:

```js

(async () => {
  const NutrientViewer = (await import("@nutrient-sdk/viewer")).default;
  const container = document.getElementById("pspdfkit");

  const XFDF = `<?xml version="1.0" encoding="UTF-8"?>
<xfdf xml:space="preserve" xmlns="http://ns.adobe.com/xfdf/">
  <annots></annots>
  <fields>
    <field name="First Name"><value>John</value></field>
    <field name="Last Name"><value>Appleseed</value></field>
    <field name="Human"><value>3</value></field>
    <field name="Fun"><value>1</value></field>
  </fields>
</xfdf>`;

  NutrientViewer.load({
    container,
    document: "document.pdf",
    useCDN: true,
    XFDF,
  });
})();

```![Form fields filled with XFDF](@/assets/images/blog/2023/creating-and-filling-pdf-forms-programmatically-in-javascript/filling-form-fields-XFDF.gif)

## Fill forms from a database

Fetch user data from your API and convert it to Instant JSON:

```json

// Example response from `/user` endpoint.
{ "firstName": "John", "lastName": "Appleseed", "human": "3", "fun": "1" }

```

```js

(async () => {
  const NutrientViewer = (await import("@nutrient-sdk/viewer")).default;
  const container = document.getElementById("pspdfkit");

  // Fetch user data from your server.
  const response = await fetch("https://[YOUR-SERVER]/user");
  const { firstName, lastName, human, fun } = await response.json();

  // Convert to Instant JSON format.
  const instantJSON = {
    format: "https://pspdfkit.com/instant-json/v1",
    formFieldValues: [
      { v: 1, type: "pspdfkit/form-field-value", name: "First Name", value: firstName },
      { v: 1, type: "pspdfkit/form-field-value", name: "Last Name", value: lastName },
      { v: 1, type: "pspdfkit/form-field-value", name: "Human", value: human },
      { v: 1, type: "pspdfkit/form-field-value", name: "Fun", value: fun },
    ],
  };

  NutrientViewer.load({
    container,
    document: "document.pdf",
    useCDN: true,
    instantJSON,
  });
})();

```![Form fields filled from database](@/assets/images/blog/2023/creating-and-filling-pdf-forms-programmatically-in-javascript/filling-form-fields-database.gif)

## FAQ

#### What form field types does Nutrient support?

Nutrient supports text fields, checkboxes, radio buttons, signature fields, combo boxes (dropdowns), and list boxes. Each type has a corresponding class like `TextFormField`, `CheckBoxFormField`, and `SignatureFormField`.

#### How do I read form field values?

Use `instance.getFormFieldValues()` to get all values as an object where keys are field names and values are the current entries. For individual fields, use `instance.getFormFields()` to access field properties.

#### What’s the difference between Instant JSON and XFDF?

Instant JSON is Nutrient’s native format — it’s compact and supports all Nutrient features, including annotations. XFDF is an Adobe standard XML format with broader compatibility across PDF tools. Use Instant JSON for Nutrient-only workflows and XFDF when exchanging data with other PDF software.

#### Can I make form fields required?

Yes. Set the `required` property to `true` when creating a form field:

```js

const field = new NutrientViewer.FormFields.TextFormField({
  name: "Email",
  required: true,
  annotationIds: new NutrientViewer.Immutable.List([widget.id]),
});

```

#### How do I export a filled PDF form?

Use `instance.exportPDF()` to get the PDF as an `ArrayBuffer`. You can then create a download link or send it to your server:

```js

const buffer = await instance.exportPDF();
const blob = new Blob([buffer], { type: "application/pdf" });

```

## Conclusion

You now have a PDF form with text fields, checkboxes, radio buttons, and signatures that can be prefilled from JSON, XFDF, or your database. Use this to build document workflows, onboarding forms, or contract signing apps.

[Try the forms demo](https://www.nutrient.io/demo/forms) or explore the [forms documentation](https://www.nutrient.io/guides/web/forms.md).
---

## Related pages

- [The business case for accessibility: Five ways it drives enterprise value](/blog/5-ways-accessibility-drives-enterprise-value.md)
- [Accessibility Untangled Why It Matters Guide](/blog/accessibility-untangled-why-it-matters-guide.md)
- [Advanced Techniques For React Native Ui Components](/blog/advanced-techniques-for-react-native-ui-components.md)
- [`vector_store` holds your indexed documents (see the multimodal RAG post](/blog/agentic-rag.md)
- [Ai Document Automation Extraction To Action](/blog/ai-document-automation-extraction-to-action.md)
- [Ai Legal Assistant Document Authoring](/blog/ai-legal-assistant-document-authoring.md)
- [Amazon Textract Alternatives](/blog/amazon-textract-alternatives.md)
- [Start (clears any prior buffer), navigate the document, then stop into a file.](/blog/android-faster-pdf-rendering.md)
- [Android Pdf Out Of Memory Handling](/blog/android-pdf-out-of-memory-handling.md)
- [Angular File Viewer Pdf Image Office Files](/blog/angular-file-viewer-pdf-image-office-files.md)
- [Auto Tagging And Document Accessibility In Dotnet Sdk](/blog/auto-tagging-and-document-accessibility-in-dotnet-sdk.md)
- [Simple PII redaction.](/blog/automated-pii-removal.md)
- [Best Document Ai Platforms](/blog/best-document-ai-platforms.md)
- [Best Document Viewers](/blog/best-document-viewers.md)
- [Build Vs Buy Document Extraction](/blog/build-vs-buy-document-extraction.md)
- [The CEO’s AI playbook: Why decision architecture beats model selection](/blog/ceo-ai-playbook-decision-architecture.md)
- [1. Extract and chunk the PDF.](/blog/chat-with-pdf.md)
- [Complete Guide To Pdfjs](/blog/complete-guide-to-pdfjs.md)
- [Construction Document Data Extraction](/blog/construction-document-data-extraction.md)
- [Convert One Drive Files To Pdf In Sharepoint](/blog/convert-one-drive-files-to-pdf-in-sharepoint.md)
- [Create And Edit Pdfs In Flutter](/blog/create-and-edit-pdfs-in-flutter.md)
- [Create Pdfs With React](/blog/create-pdfs-with-react.md)
- [Creating A Document Scanner With Ocr In Python](/blog/creating-a-document-scanner-with-ocr-in-python.md)
- [The CTO’s AI playbook: Why accountability architecture beats orchestration](/blog/cto-ai-playbook-accountability-architecture.md)
- [Digital Signatures](/blog/digital-signatures.md)
- [Digital Workflow Automation](/blog/digital-workflow-automation.md)
- [Document Ai Vs Ocr](/blog/document-ai-vs-ocr.md)
- [Document Extraction Confidence Scores](/blog/document-extraction-confidence-scores.md)
- [Document Viewer](/blog/document-viewer.md)
- [Document Watermarking](/blog/document-watermarking.md)
- [Emerging threats: Your logging system may be an agentic threat vector](/blog/emerging-threats-your-logging-system.md)
- [Extract Patient Data On Premises](/blog/extract-patient-data-on-premises.md)
- [app.py](/blog/extract-text-from-pdf-using-python.md)
- [Fillable Pdf](/blog/fillable-pdf.md)
- [How To Add Digital Signature To Pdf Using React](/blog/how-to-add-digital-signature-to-pdf-using-react.md)
- [How To Build A Dotnet Maui Pdf Viewer](/blog/how-to-build-a-dotnet-maui-pdf-viewer.md)
- [How To Build A Flutter Pdf Viewer](/blog/how-to-build-a-flutter-pdf-viewer.md)
- [or](/blog/how-to-build-a-javascript-pdf-viewer-with-pdfjs.md)
- [How To Build A Javascript Pdf Viewer](/blog/how-to-build-a-javascript-pdf-viewer.md)
- [or](/blog/how-to-build-a-nextjs-pdf-viewer.md)
- [How To Build A Powerpoint Viewer Using Javascript](/blog/how-to-build-a-powerpoint-viewer-using-javascript.md)
- [Using Yarn](/blog/how-to-build-a-react-excel-viewer.md)
- [How To Build A React Native Pdf Viewer](/blog/how-to-build-a-react-native-pdf-viewer.md)
- [How To Build A React Powerpoint Viewer](/blog/how-to-build-a-react-powerpoint-viewer.md)
- [How To Build A Reactjs File Viewer](/blog/how-to-build-a-reactjs-file-viewer.md)
- [or](/blog/how-to-build-a-reactjs-pdf-viewer-with-react-pdf.md)
- [or](/blog/how-to-build-a-reactjs-pdf-viewer.md)
- [How To Build A Reactjs Viewer With Pdfjs](/blog/how-to-build-a-reactjs-viewer-with-pdfjs.md)
- [How To Build A Vuejs Pdf Viewer With Pdfjs](/blog/how-to-build-a-vuejs-pdf-viewer-with-pdfjs.md)
- [How To Build A Vuejs Pdf Viewer](/blog/how-to-build-a-vuejs-pdf-viewer.md)
- [How To Build An Android Pdf Viewer](/blog/how-to-build-an-android-pdf-viewer.md)
- [How To Build An Angular Pdf Viewer With Ng2 Pdf Viewer](/blog/how-to-build-an-angular-pdf-viewer-with-ng2-pdf-viewer.md)
- [How To Build An Angular Pdf Viewer With Pdfjs](/blog/how-to-build-an-angular-pdf-viewer-with-pdfjs.md)
- [How To Convert Docx To Pdf Using Javascript](/blog/how-to-convert-docx-to-pdf-using-javascript.md)
- [How To Convert Docx To Pdf Using Python](/blog/how-to-convert-docx-to-pdf-using-python.md)
- [How To Convert Html To Pdf Using Html2pdf](/blog/how-to-convert-html-to-pdf-using-html2pdf.md)
- [or](/blog/how-to-convert-html-to-pdf-using-react.md)
- [How To Convert Html To Pdf Using Wkhtmltopdf And Csharp](/blog/how-to-convert-html-to-pdf-using-wkhtmltopdf-and-csharp.md)
- [or](/blog/how-to-convert-html-to-pdf-using-wkhtmltopdf-and-python.md)
- [How To Convert Word To Pdf In Nodejs](/blog/how-to-convert-word-to-pdf-in-nodejs.md)
- [or](/blog/how-to-create-a-react-js-signature-pad.md)
- [How To Create Pdfs With React To Pdf](/blog/how-to-create-pdfs-with-react-to-pdf.md)
- [How To Edit Pdfs Using Ios Pdf Library](/blog/how-to-edit-pdfs-using-ios-pdf-library.md)
- [How To Embed A Pdf Viewer In Your Website](/blog/how-to-embed-a-pdf-viewer-in-your-website.md)
- [How To Extract Tables From Pdf And Images](/blog/how-to-extract-tables-from-pdf-and-images.md)
- [How To Generate Pdf From Html With Nodejs](/blog/how-to-generate-pdf-from-html-with-nodejs.md)
- [base_url tells WeasyPrint where to resolve relative asset paths](/blog/how-to-generate-pdf-reports-from-html-in-python.md)
- [How To Merge Pdfs Using Javascript](/blog/how-to-merge-pdfs-using-javascript.md)
- [How To Ocr Pdfs In Linux](/blog/how-to-ocr-pdfs-in-linux.md)
- [How To Print Pdf In Csharp](/blog/how-to-print-pdf-in-csharp.md)
- [Open an image.](/blog/how-to-use-tesseract-ocr-in-python.md)
- [From an HTML string.](/blog/html-in-pdf-format.md)
- [Html To Pdf In Javascript](/blog/html-to-pdf-in-javascript.md)
- [Javascript Pdf Editors](/blog/javascript-pdf-editors.md)
- [Javascript Pdf Libraries](/blog/javascript-pdf-libraries.md)
- [Langextract Vs Llamaindex Extraction Comparison](/blog/langextract-vs-llamaindex-extraction-comparison.md)
- [Linearized Pdf](/blog/linearized-pdf.md)
- [or](/blog/merge-pdfs.md)
- [Swift Package Manager](/blog/mobile-pdf-sdk.md)
- [`elements` come from your document parser — each has a type and content.](/blog/multimodal-rag.md)
- [Nutrient Flutter 6 Bindings Api](/blog/nutrient-flutter-6-bindings-api.md)
- [Nutrient Vs Conga Composer](/blog/nutrient-vs-conga-composer.md)
- [Online Document Viewer](/blog/online-document-viewer.md)
- [Open Pdf In Your Web App](/blog/open-pdf-in-your-web-app.md)
- [Building WCAG 2.2, Section 508, and PDF/UA-compliant PDFs with an SDK](/blog/pdf-accessibility.md)
- [Extract data from PDF files: A developer guide to structured data from PDFs and scans](/blog/pdf-data-extraction-developer-guide.md)
- [Pdf Extraction Benchmark Opendataloader Bench](/blog/pdf-extraction-benchmark-opendataloader-bench.md)
- [Pdf Extraction Document Case Studies](/blog/pdf-extraction-document-case-studies.md)
- [Pdf Page Labels](/blog/pdf-page-labels.md)
- [Pdf Sdk Compliance Security Checklist](/blog/pdf-sdk-compliance-security-checklist.md)
- [Pdf Sdk Performance Benchmark](/blog/pdf-sdk-performance-benchmark.md)
- [Pdf Ua Compliance Guide](/blog/pdf-ua-compliance-guide.md)
- [Pdfjs Accessibility Structtree Printing](/blog/pdfjs-accessibility-structtree-printing.md)
- [Pdfjs Advanced Loading Streaming Workers](/blog/pdfjs-advanced-loading-streaming-workers.md)
- [Pdfjs Annotation Editor Layer](/blog/pdfjs-annotation-editor-layer.md)
- [Pdfjs Area Annotations Canvas Capture](/blog/pdfjs-area-annotations-canvas-capture.md)
- [Pdfjs Coordinate Systems Pdf To Screen](/blog/pdfjs-coordinate-systems-pdf-to-screen.md)
- [Pdfjs Document Outline Bookmarks Metadata](/blog/pdfjs-document-outline-bookmarks-metadata.md)
- [Pdfjs Eventbus Guide](/blog/pdfjs-eventbus-guide.md)
- [macOS](/blog/pdfjs-file-format-conversion-to-pdf.md)
- [macOS](/blog/pdfjs-generating-pdf-thumbnails-pdf2pic.md)
- [Pdfjs Limitations Commercial Upgrade](/blog/pdfjs-limitations-commercial-upgrade.md)
- [Pdfjs Native Annotation Layer Forms](/blog/pdfjs-native-annotation-layer-forms.md)
- [Pdfjs Navigation Zoom Rotation](/blog/pdfjs-navigation-zoom-rotation.md)
- [Pdfjs Pdf Page Manipulation Pdf Lib](/blog/pdfjs-pdf-page-manipulation-pdf-lib.md)
- [Pdfjs React Viewer Setup](/blog/pdfjs-react-viewer-setup.md)
- [Pdfjs Rendering Overlays React Portals](/blog/pdfjs-rendering-overlays-react-portals.md)
- [Pdfjs Server Side Text Extraction](/blog/pdfjs-server-side-text-extraction.md)
- [Pdfjs Sticky Note Annotations](/blog/pdfjs-sticky-note-annotations.md)
- [Pdfjs Text Highlight Annotations](/blog/pdfjs-text-highlight-annotations.md)
- [Pdfjs Text Search Pdffindcontroller](/blog/pdfjs-text-search-pdffindcontroller.md)
- [Pdfjs Thumbnail Sidebar](/blog/pdfjs-thumbnail-sidebar.md)
- [Process Flows](/blog/process-flows.md)
- [React Native Pdf Annotation](/blog/react-native-pdf-annotation.md)
- [Using Yarn](/blog/react-pdf-editor.md)
- [React Pdf Loading States Errors Passwords](/blog/react-pdf-loading-states-errors-passwords.md)
- [React Pdf Setup Basic Rendering](/blog/react-pdf-setup-basic-rendering.md)
- [React Pdf Text Layer Custom Renderer](/blog/react-pdf-text-layer-custom-renderer.md)
- [labels.py](/blog/route-documents-automatically-classify-api.md)
- [or](/blog/sample-blog-updated.md)
- [Sdk Product Updates Q2 2026](/blog/sdk-product-updates-q2-2026.md)
- [Add DWS MCP Server to your Claude Code project.](/blog/teaching-llms-to-read-pdfs.md)
- [Open an image file.](/blog/tesseract-python-guide.md)
- [Define the HTML part of the document.](/blog/top-10-ways-to-generate-pdfs-in-python.md)
- [Top 5 Javascript Pdf Viewers](/blog/top-5-javascript-pdf-viewers.md)
- [or](/blog/top-js-pdf-libraries.md)
- [Convert an HTML file to PDF.](/blog/top-ten-ways-to-convert-html-to-pdf.md)
- [Vector Pdf](/blog/vector-pdf.md)
- [Wcag2 Accessibility Requirements Documents](/blog/wcag2-accessibility-requirements-documents.md)
- [Web Sdk Is Now Headless](/blog/web-sdk-is-now-headless.md)
- [What Are Annotations](/blog/what-are-annotations.md)
- [What Is A Vpat](/blog/what-is-a-vpat.md)
- [What Is Document Processing](/blog/what-is-document-processing.md)
- [What Is Intelligent Document Processing](/blog/what-is-intelligent-document-processing.md)
- [What Is Pdf Ua](/blog/what-is-pdf-ua.md)
- [Why Pdfium Is A Trusted Platform For Pdf Rendering](/blog/why-pdfium-is-a-trusted-platform-for-pdf-rendering.md)
- [Why Your Ai Agent Hallucinates Pdf Table Data](/blog/why-your-ai-agent-hallucinates-pdf-table-data.md)

