Skip to main content

Form Filling

Read, fill, and flatten PDF forms. Requires the full tier.

import { PDFDocument } from "pdfnova";

Read Form Fields

const doc = await PDFDocument.open(formPdf);
const fields = await doc.getFormFields();

for (const field of fields) {
console.log(`${field.name}: ${field.value} (${field.type})`);
}

FormFieldData

PropertyTypeDescription
namestringField name
typeFormFieldTypeField type
valuestringCurrent value
flagsnumberField flags (readonly, required, etc.)
isCheckedboolean?For checkboxes/radio buttons
pageIndexnumberPage containing the field
annotIndexnumberAnnotation index on the page

FormFieldType

enum FormFieldType {
Unknown = -1,
PushButton = 0,
CheckBox = 1,
RadioButton = 2,
ComboBox = 3,
ListBox = 4,
TextField = 5,
Signature = 6,
}

Fill Form Fields

await doc.setFormField("name", "John Doe");
await doc.setFormField("email", "john@example.com");
await doc.setFormField("date", "2025-01-15");

Flatten Forms

Flattening bakes form field values into the page content, making them non-interactive:

import { FLATTEN_USAGE } from "pdfnova";

// Flatten all fields
await doc.flattenForms();

// Flatten only fields visible when printing
await doc.flattenForms(FLATTEN_USAGE.PRINT);

Complete Example

import { PDFDocument } from "pdfnova";

const doc = await PDFDocument.open(formPdf);

// Read existing values
const fields = await doc.getFormFields();
console.log("Fields:", fields.map((f) => f.name));

// Fill in values
await doc.setFormField("first_name", "Jane");
await doc.setFormField("last_name", "Smith");
await doc.setFormField("company", "Acme Inc.");

// Flatten (optional — makes fields non-editable)
await doc.flattenForms();

// Save
const bytes = await doc.save();
doc.close();