Set text field values, check checkboxes, select radio buttons, and choose dropdown options programmatically in any AcroForm PDF.
use pdfluent::prelude::*;
fn main() -> Result<()> {
let mut doc = PdfDocument::open("application.pdf")?;
{
let mut form = doc.form_mut();
form.set_text("first_name", "Jane")?
.set_text("last_name", "Smith")?
.set_checkbox("agree_terms", true)?
.set_dropdown("country", "Netherlands")?;
}
doc.save("application_filled.pdf")?;
Ok(())
}Open the PDF with a mutable binding. Use form_fields() to check whether the document has any form fields before trying to fill them.
use pdfluent::prelude::*;
let mut doc = PdfDocument::open("application.pdf")?;
if doc.form_fields()?.is_empty() {
eprintln!("This PDF has no form fields.");
return Ok(());
}Call form_mut() to get a PdfFormMut value that lets you write field values. The accessor is infallible — errors surface on the individual set_* calls when a field does not exist or has a different type.
let mut form = doc.form_mut();Use set_text() with the field name as it appears in the PDF. Field names are case-sensitive. The setters chain via Result<&mut Self>.
form.set_text("first_name", "Jane")?
.set_text("last_name", "Smith")?
.set_text("email", "jane@example.com")?;Pass true or false to set_checkbox(). For radio buttons, pass the export value of the option you want selected. PDFluent writes the field value (/V) correctly. Note: in 1.0 the widget appearance state (/AS) on kid annotations is not yet synced — viewers that honour /AS may show stale visual state until they rebuild appearance from /V.
form.set_checkbox("agree_terms", true)?
.set_checkbox("newsletter", false)?
// Radio button: pass the export value, not the display label
.set_radio("payment_method", "credit_card")?;Drop the form handle scope and call save() on the document. flatten_forms() is on the 1.0 surface but currently returns Error::MissingDependency — the flatten runtime is tracked for a 1.x MINOR.
doc.save("application_filled.pdf")?;No JVM, no runtime, no DLL dependencies. Ships as a single native binary or WASM module.
Rust's ownership model prevents buffer overflows and use-after-free. No segfaults in PDF parsing.
Same code runs server-side, in Docker, on AWS Lambda, on Cloudflare Workers, or in the browser via WASM.