A PDF form filling library using Poppler + Cairo compiled to WebAssembly. Works in Node.js and the browser.
- Fill PDF form fields (text, checkbox, radio buttons, dropdowns)
- Read form field values and metadata
- Render PDF pages to PNG images
- Works entirely client-side - no server required
- TypeScript support with full type definitions
npm install pdf-filler-wasmimport { PdfForm } from 'pdf-filler-wasm';
import fs from 'fs';
// Load a PDF
const data = fs.readFileSync('form.pdf');
const form = await PdfForm.fromUint8Array(data);
// List all form fields
const fields = form.getFields();
console.log(`Found ${fields.length} fields`);
// Fill text fields
form.setField('name', 'John Doe');
form.setField('email', '[email protected]');
// Set checkboxes
form.setCheckbox('agree_terms', true);
// Save the filled PDF
const output = form.saveAsUint8Array();
fs.writeFileSync('filled-form.pdf', output);<script type="module">
import { PdfForm, initPdfFiller } from 'pdf-filler-wasm';
// Initialize the WASM module
await initPdfFiller();
// Load PDF from file input
const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', async (e) => {
const file = e.target.files[0];
const buffer = await file.arrayBuffer();
const form = await PdfForm.fromArrayBuffer(buffer);
// Fill fields
form.setField('name', 'Jane Doe');
// Download filled PDF
const data = form.saveAsUint8Array();
const blob = new Blob([data], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'filled.pdf';
a.click();
});
</script>Initialize the WASM module. Called automatically when using PdfForm.fromArrayBuffer(), but can be called explicitly to preload the module.
PdfForm.fromArrayBuffer(data: ArrayBuffer, password?: string): Promise<PdfForm>- Load a PDF from an ArrayBufferPdfForm.fromUint8Array(data: Uint8Array, password?: string): Promise<PdfForm>- Load a PDF from a Uint8Array
pageCount: number- Number of pages in the documenttitle: string- Document titleauthor: string- Document authorhasForm: boolean- Whether the document has fillable form fields
getFields(): FormField[]- Get all form fieldsgetField(name: string): FormField | null- Get a field by namesetField(name: string, value: string): void- Set a text field valuesetCheckbox(name: string, checked: boolean): void- Set a checkbox valuesetFields(values: Record<string, string>): void- Set multiple field valuesflatten(): void- Flatten the form (make fields non-editable)save(): ArrayBuffer- Save the PDF to an ArrayBuffersaveAsUint8Array(): Uint8Array- Save the PDF to a Uint8ArrayrenderPage(pageIndex: number, dpi?: number): Uint8Array- Render a page to PNG
interface FormField {
name: string; // Field name
fullName: string; // Fully qualified name (for nested fields)
type: FieldType; // 'text' | 'checkbox' | 'radio' | 'button' | 'choice' | 'signature'
value: string; // Current value
defaultValue: string; // Default value
isReadOnly: boolean;
isRequired: boolean;
isChecked: boolean; // For checkbox/radio fields
options: string[]; // For choice fields (dropdowns)
pageIndex: number; // Page the field appears on
}- Node.js 18+
- Docker (for building the WASM module)
- pnpm (recommended) or npm
# Clone the repository
git clone https://github.com/youmustfight/pdf-filler-js.git
cd pdf-filler-js
# Install dependencies
pnpm install
# Build the Docker image (first time only)
pnpm build:docker
# Build native dependencies (first time only)
pnpm build:deps
# Build the WASM module and TypeScript
pnpm build
# Run tests
pnpm test
# Run the browser example
pnpm exampleThis library compiles Poppler (a PDF rendering library) and Cairo (a 2D graphics library) to WebAssembly using Emscripten. The native C++ code handles PDF parsing, form field manipulation, and rendering, while the TypeScript wrapper provides a clean JavaScript API.
The WASM build includes:
- Poppler (PDF parsing and form handling)
- Cairo (2D rendering)
- FreeType (font rendering)
- libpng, libjpeg, libtiff, OpenJPEG (image codecs)
- zlib (compression)
- Pixman (pixel manipulation)
- Password-protected PDFs with encrypted form fields may not be fully supported
- Some advanced form features (JavaScript actions, XFA forms) are not supported
- The WASM bundle is approximately 3MB (can be gzipped to ~1MB)
GPL-3.0 - This project uses Poppler which is licensed under GPL-2.0-or-later. See LICENSE for details.
Contributions are welcome! Please open an issue or submit a pull request.
- Poppler - The PDF rendering library
- Cairo - 2D graphics library
- Emscripten - The compiler toolchain for WebAssembly