Frequently asked

Does it support fillable AcroForm fields and inserting signatures?

It's a fair question to ask of any PDF library. Here is what works today, the code for it, and what doesn't work yet.

Short answer: yes, to both. DartPDF fills existing AcroForm text, checkbox, radio, combo box, list box, and image-button fields, and redraws each field's appearance so the value shows up in other PDF viewers, not only this one. It can also add new fields and flatten a form into the page. For signatures, users can draw a handwritten signature and drop it on the page. Apps can also apply real certificate-backed digital signatures (PAdES B-B through B-LTA), shown in a visible signature box that can include the drawn signature. It's all pure Dart and runs the same on Android, iOS, desktop, web, and servers.

By Ben Milanko, maintainer of dart-pdf Published 23 September 2026 Applies to dart_pdf_editor / pdf_document 4.5.0

“Signature” means two different things

People asking about signatures usually mean one of two jobs, and a PDF stores them very differently. DartPDF does both, and can combine them.

Drawn signature

Your handwriting on the page. Good for everyday sign-and-return. It is ink on the page, so it doesn't prove who drew it.

Digital signature

A cryptographic signature from a certificate. It detects changes to the signed bytes. Establishing who signed also requires trusting the signer's certificate and its issuing authority.

Both at once

A visible signature box on the page, showing the drawn signature, backed by a real digital signature.

Fillable AcroForm fields

AcroForms are the standard interactive form fields defined by the PDF specification. They are what Acrobat, Word's PDF export, and most form designers produce. DartPDF finds every field in the document, including widgets a broken file left attached to a page but missing from the field tree, and handles each field type as follows:

Field type Read & fill Add new
Text (single-line & multiline) Yes: wrapping, auto-size, alignment, RTL text, custom font/size/colour Yes
Checkbox Yes Yes
Radio group Yes Not yet
Combo box / list box Yes: by export or display value; editable combos accept free text Not yet
Push button (image) Yes: fill with a PNG/JPEG, e.g. a photo or signature image Yes
Signature field Detected, signed, and validated (see below) Created when you sign

The important detail is appearance generation. In a PDF, a field's value and how it looks on the page are stored separately. A library that only sets the value leaves a form that looks empty in some viewers, or that Acrobat redraws with its own layout. DartPDF redraws every field it fills, including wrapping, auto-sizing, quadding (alignment), borders, backgrounds, and page rotation, and then clears /NeedAppearances. The saved file looks the same in every viewer, and it prints correctly.

In a Flutter app

Form filling is on by default. PdfEditorView (the full editor) and PdfReader (the read-only viewer) both let users tap into fields. Tapping a text field opens an inline editor, checkboxes and radios toggle, choice fields open a menu, and image buttons open the host's image picker. To add form filling to a custom viewer, pass it an editing controller:

final session = PdfEditingController(pdfBytes);

PdfViewer(
  formController: session, // tap-to-fill, no editing toolbar
  formImagePicker: (context, field) => pickImageBytes(context),
);

// Or fill from code, e.g. to prefill from your backend:
session.setFormFieldText('applicant.name', 'Ada Lovelace');
session.toggleFormCheckBox('terms');
session.setFormChoiceValue('country', 'Australia');

final Uint8List filled = session.bytes;

Every change is an incremental revision, so undo and redo work for form input too.

In pure Dart (server, CLI, tests)

The form engine is in pdf_document, which has no Flutter dependency. That makes it a good fit for batch-filling a template on a server:

import 'package:pdf_document/pdf_document.dart';

Uint8List fillApplication(Uint8List template) {
  final editor = PdfEditor(PdfDocument.open(template));
  final form = editor.acroForm!;

  for (final field in form.fields) {
    print('${field.name}: ${field.type} = ${field.value}');
  }

  editor.setTextValue(form.fieldNamed('name')!, 'John Doe');
  editor.setCheckBoxValue(form.fieldNamed('agree')!, true);
  editor.setRadioValue(form.fieldNamed('color')!, 'Blue');
  editor.setChoiceValue(form.fieldNamed('size')!, 'Large');

  // Optional: burn the values into the page so they can't be edited.
  editor.flattenForm();

  return editor.save();
}

To add fields, use addTextField, addCheckBoxField, and addPushButtonField. renameField, removeField, and changeFieldType handle field management. If the document has no AcroForm yet, the first new field creates one. The editor UI has matching tools, so users can draw fields onto a plain PDF and turn it into a fillable form.

Drawn (handwritten) signatures

The editor ships a signature pad with pressure-sensitive strokes, pen colour and width, and a saved signature library. Users draw once, then tap anywhere to place the signature. The library persists on the device through PdfEditingPreferences, and users can rename, redraw, or delete entries.

// Show the pad, keep the result in the library, and place it.
final ink = await showPdfSignatureDialog(context);
if (ink != null) {
  session.addSavedSignature(ink, name: 'Full signature');
  session.placeSignature(0, 300, 200); // page 0, centred on (300, 200) in PDF points
}

A placed signature is a vector ink annotation. It stays crisp at any zoom, can be moved and resized, and appears in any viewer. To stop it being moved or removed, flatten it into the page content, using the editor's Flatten action or flattenDocument(). If a form has an image button meant for a signature, filling that button with a picture of the signature also works.

Know what a drawn signature does and doesn't prove. It shows intent, and that is enough for most everyday paperwork. It doesn't say who drew it, and nothing detects a later change to the document. If you need either of those, use a digital signature.

Digital signatures (PAdES)

DartPDF writes standard adbe.pkcs7.detached / PAdES signatures, and it does the cryptography (CMS, X.509, RSA, ECDSA) in Dart. It has no OpenSSL dependency and no native plugin. The output is interoperable: pyHanko rates our PAdES B-LTA files valid and LTV-enabled with no network access.

Capability Support
Signing keys Your own RSA or ECDSA key and certificate chain; an external signer callback for HSMs and platform keystores
PAdES levels B-B, B-T (RFC 3161 timestamp), B-LT (embedded OCSP/CRL in a /DSS), B-LTA (plus a document timestamp)
Identities One-tap self-signed P-256 identities, your own organisation CA that issues member certificates, or keyless Sigstore certificates tied to an email sign-in
Appearance Invisible, or a visible box with the signer's name, date, reason, location, drawn signature, and logo backdrop. The box can be repeated on other pages.
Existing fields Signs into an empty signature field a form designer already placed
Certification Certify (DocMDP) signatures with P=1/2/3 change permissions; additional approval signatures are refused after P=1 certification. General editing APIs do not enforce DocMDP permissions.
Multiple signers Each signature is an incremental update, so countersigning leaves earlier signatures valid
Validation Checks the digest, the signature, and whether the whole document is covered; builds the chain against your trust store; reports PAdES level, timestamp, and embedded revocation data

Sign with a visible box

final identity = PdfSigningIdentity.generate(
  name: 'Ada Lovelace',
  email: 'ada@example.com',
);

final editor = PdfEditor(PdfDocument.open(filledPdf));
final signed = await editor.saveSelfSignedPades(
  identity: identity,
  level: PdfPadesLevel.bT,                  // trusted time from a TSA
  timestampClient: myTimestampClient,       // you supply the HTTP call
  reason: 'Approved',
  location: 'Melbourne',
  appearance: PdfSignatureAppearance(
    page: 0,
    rect: const PdfRect(72, 80, 320, 150),
    graphic: PdfEmbeddableImage.png(drawnSignaturePng),
  ),
);

To sign into a field the form already has, pass fieldName: 'ApproverSig'. The box then takes the field's existing position. For a company certificate, use saveSignedPades with your RsaPrivateKey and certificate chain. The library does no network I/O of its own: timestamp, OCSP, and CRL transports are callbacks you provide, so it runs on the web and never contacts a server you didn't choose.

In the Flutter editor

The editor's signature-box tool lets users drag out a rectangle on the page. Your onPlaceSignature callback receives the page and rectangle, and the controller does the signing:

final identity = PdfDigitalSignatureIdentity.fromFiles(
  privateKey: privateKeyBytes,
  certificates: certificateFileBytes,
);
await session.addDigitalSignature(
  identity,
  reason: 'Approved',
  appearance: PdfSignatureAppearance(page: pageIndex, rect: pageRect),
);

Before committing a signature, the controller re-opens and validates it. So it will never save a signature that doesn't verify. addSelfSignedSignature and addKeylessSignature cover the other identity types. The package also ships a “Create signing identity” dialog and secure key storage. The DartPDF app wires all of this into a single Digitally sign… dialog.

Verify signatures

for (final sig in PdfSignature.of(PdfDocument.open(bytes))) {
  final result = sig.validate(trustStore: PdfTrustStore.trusting([caDer]));
  print('${sig.signerName}: intact=${result.intact} '
      'trusted=${result.chainTrusted} level=${result.padesLevel}');
}

The editor's annotations panel shows the same result next to each signature.

What isn't supported (yet)

These are the gaps you're most likely to hit, so you know before you build on it:

  • XFA forms. XFA is the older XML-based Adobe forms format. Pure-XFA (“dynamic”) forms won't show their fields. Hybrid forms work through their AcroForm half.
  • Form JavaScript. There is deliberately no JS engine, so calculated totals, format/validation scripts, and scripted show/hide don't run. Scripts are exposed read-only so your app can inspect them.
  • Comb fields, /MaxLen, and password masking are not enforced when filling.
  • Tab to the next field isn't implemented yet. Users tap each field.
  • Multi-select list boxes take a single value.
  • Authoring covers text, checkbox, and image-button fields. You can't yet add radio groups, choice fields, or empty signature fields for someone else to sign later.
  • Signing encrypted (password-protected) PDFs is refused. Sign an unencrypted copy instead. Adding password encryption afterwards rewrites the signed bytes and invalidates the signature; an encrypted, signed output is not currently supported.
  • Trust roots. No certificate authorities are bundled. Validation tells you whether the chain reaches a root you supplied (for example, the AATL or your organisation's CA), and it doesn't query live revocation during validation. A self-signed signature validates as intact, but Acrobat shows its signer as unknown until the certificate is trusted.

If one of these blocks you, open an issue with a sample PDF. Real forms decide what we work on next.

Common questions

Will filled forms look right in Adobe Acrobat?

Yes. DartPDF writes each field's value and redraws its appearance stream, then turns off /NeedAppearances so Acrobat doesn't redraw the field with its own layout. The field stays editable in Acrobat unless you flatten the form.

Does filling a form break an existing signature?

Form fills are saved as incremental updates, so the signed bytes stay untouched and their cryptographic signature can remain intact. Validation reports that the signature no longer covers the whole document. A certification signature may still forbid the change: DocMDP P=1 forbids form filling, while P=2 and P=3 permit it. The editing APIs do not enforce those permissions, so check the document's certification policy before filling it.

Can I fill forms without Flutter?

Yes. pdf_document is pure Dart with no dart:io or Flutter imports, so the same filling, flattening, and signing code runs on a server, in a CLI, or on the web.

Is a drawn signature legally binding?

That depends on your jurisdiction and use case, not on the library. Many everyday agreements accept a drawn signature. Some regulated workflows need an advanced or qualified signature. For those, sign with a certificate from a provider your regulator recognises. DartPDF produces the PAdES formats those schemes build on.

See it on a real form

The web demo's showcase PDF includes fillable fields and a signature area. Fill it in, draw a signature, and save it to check the output in your own viewer.