A pure-Rust PDF SDK: render, extract, edit, sign, redact, and validate PDF/A — from Rust, Python, Node.js, .NET, Java, C, or the browser.
Share on X · Share on LinkedIn
Not a mock-up: cargo run --example readme_hero rebuilds this image from
docs/hero/, and both panels — and the picture itself — come out
of PDFluent's own rasterizer. The generator refuses to write it if the redacted
text is still extractable or validate_pdfa() disagrees.
cargo add pdfluent # Rust
pip install pdfluent # Python
npm install @pdfluent/node # Node.js
npm install @pdfluent/sdk-wasm # Browser (WebAssembly)
dotnet add package PDFluent # .NET<!-- Java (Maven) -->
<dependency>
<groupId>com.pdfluent</groupId>
<artifactId>pdfluent</artifactId>
</dependency>C and C++ link against pdf-capi; SETUP.md has the header and the
build flags.
use pdfluent::prelude::*;
fn main() -> Result<()> {
let doc = PdfDocument::open("input.pdf")?;
for page in doc.pages() {
println!("{}", page.text()?);
}
let report = doc.validate_pdfa(PdfAProfile::A2b)?;
if report.is_compliant() {
println!("PDF/A-2B ✓");
}
Ok(())
}QUICKSTART.md is the same five minutes in each language, and
https://pdfluent.com/cookbook/ has ten recipes with the explanation around
them. Every block on that page is a // site:<name> marker in
crates/pdfluent/examples/site_snippets.rs,
which CI compiles — an example that stops building breaks the build rather than
a reader's first attempt.
The axes, the readers and their versions, the machine class, and what counts as a failure are written up at https://pdfluent.com/benchmarks/how-we-measure. Every figure PDFluent publishes carries a claim ID and points back to that method. That page deliberately carries no figure of its own, and neither does this README.
The engine, the language bindings and the guards that gate them are in this one repository.
Rendering. A pure-Rust rasterizer (vello_cpu) to PNG, JPEG or a rasterized PDF, with SSIM comparison against a reference renderer.
Text and data. Extraction with position information, find-and-replace in content streams, OCR over scanned pages.
Forms. AcroForm fill, flatten and read-back across every binding. XFA is
experimental and feature-gated behind xfa-flatten: dynamic layout, a FormCalc
interpreter with the standard built-in functions, and SOM path resolution
(xfa.form.subform[3].field[*]). It is not production-supported.
Documents. Merge, split, insert, delete and rearrange pages; AES-256 (PDF 2.0) encryption; watermarks; redaction that removes the content rather than covering it.
PDF/A. Validation and conversion for A-1, A-2 and A-3, including ZUGFeRD and Factur-X invoices, with font embedding and subsetting, OutputIntent injection and XMP metadata repair.
Signatures. PAdES signing and verification.
Extraction runs in one of two tiers:
fast(default): the engine alone — pure Rust, no models, everywhere including WASM.balanced(preview): the layout model regions each page — headings, lists, tables, page furniture — and the table-structure model structures tables, all run locally through ONNX Runtime 1.23.2. Needs the model files (pdfluent models install layout tables) and does more work per page thanfast. Native only, never WASM. Balanced/tables: glibc Linux, macOS, Windows; not on musl Linux (loading returns a typed ModelError).
On the FinTabNet and PubTables-1M benchmarks, the balanced tier's table structure (TEDS) scores higher than Docling and pymupdf4llm (claim A35, claim A36, both measured 2026-10-08; see benchmarks/BENCHMARK_CLAIMS.md).
| Tier | Needs | Runs | Status |
|---|---|---|---|
fast |
Nothing | Everywhere, including WASM | Shipping |
balanced |
The ort-layout build (ort-tables for table structure) plus installed models |
Native only | Preview |
pdfluent models install layout tables # explicit, once; SHA-256 verified, never automatic
pdfluent models statusQuality tiers has the whole story: enabling, per-language options, errors and licences.
Rust 1.94.0, pinned in rust-toolchain.toml so rustup
installs it on the first cargo call. The default feature set needs no system
library beyond a C toolchain.
cargo build -p pdfluent # the SDK crate
cargo test -p pdfluent
cargo fmt --all --check
cargo clippy --workspace -- -D warnings
cargo build --workspace builds the bindings and the tools around the SDK as
well, which is what CI does and what takes the time.
Default features: signing, pdfa, redaction, font-subset.
Ask questions in GitHub Discussions, in the Q&A category. Report bugs in this repository's issue tracker. Report security problems by email to security@pdfluent.com, never in a public issue.
Issues labelled good first issue
and help wanted
are the ones we would most like a hand with.
Sign off every commit — git commit -s — and read
CONTRIBUTING.md before the first one: it says what the
sign-off certifies, what it does not, and which contributions need a CLA that
does not exist yet. A pull request here runs two checks and both must pass: no
commit publishes a personal address, and every commit written since the DCO
landed carries a matching Signed-off-by.
Security reports do not go in a public issue. SECURITY.md says where they go.
SETUP.md is the contributor onboarding, CHANGELOG.md
is what changed and when, and https://pdfluent.com is the product around it.
Runnable examples in Rust and a browser/WASM demo live in
pdfluent/examples. This engine also
ships inside pdfluent/pdfluent, the
free desktop editor.
External assets in this README. The badges come from img.shields.io, a
third-party host serving an image into this page. It is not code, it runs
nothing in your clone, and it can be removed without touching the build. It is
listed here so nobody has to wonder later where an image in our README comes
from.
The two images that are not external — docs/readme-hero.png and
docs/social-preview.png — are ours outright. The hero is generated by
cargo run --example readme_hero from the HTML in docs/hero/; the document on
it is invented, and no customer document or test corpus appears in either.
AGPL-3.0 or a commercial licence, at your option:
| file | what it is |
|---|---|
| LICENSE | the GNU Affero General Public License, version 3 — the FSF's text, verbatim |
| LICENSE-COMMERCIAL | the PDFluent Commercial Licence |
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-PDFluent-Commercial
Choose either. You do not need permission to choose the first.
LICENSE holds nothing but the AGPL itself, and that is deliberate: a licence
file with our explanation wrapped around it is not the AGPL, and neither a
reader nor a licence scanner can tell how much of what they are reading is the
FSF's. The explanation is here instead, where prose belongs, and
scripts/ci/license_boundary.py fails the build if LICENSE moves by one byte
from the text pinned at
docs/licensing/agpl-text-provenance.md.
The AGPL is the default. No key is required to receive it, nothing expires, and the rights it grants are not conditional on anything we do.
It asks something in return: if you convey the software, or let users interact with a modified version over a network, you must offer those users the corresponding source under the same licence.
If that is impossible for you — a closed surrounding product, a customer contract, a legal department that will not accept copyleft in a shipped binary — the commercial licence is the alternative. Under it you are not buying features. You are buying the right not to publish your own source. It is what pdfluent.com/sdk/pricing sells, yearly and self-service, in four options: Commercial (per organisation), OEM Startup and OEM (per product), and Priority support (an add-on). Enquiries go to sales@pdfluent.com.
There is nothing to activate. Since 6 September 2026 the compiled SDK carries no tier check and reads no key: every capability is present in every build, and nothing in the output marks whether a licence was bought. Earlier builds still contained checks left over from the proprietary model while the licence file of that time said there were none; this paragraph replaced the sentence that was wrong, and it will be updated again the day it stops being true.
Several crates in this repository are forks of third-party open-source projects and remain under their own permissive licences. They are not PDFluent's to relicense and need no licence from PDFluent.
| file | what it holds |
|---|---|
| NOTICE | which crates, and under what |
docs/licensing/boundary.toml |
the same thing, machine-readable |
| THIRD_PARTY_LICENSES.txt | attribution for everything we ship |
scripts/ci/license_boundary.py fails the build if a crate stops agreeing with
the side of that boundary it is recorded on.
The rendering path is built on hayro,
Laurenz Stampfl's pure-Rust PDF interpreter — mirrored under the PDFluent
org, unmodified license terms as recorded in NOTICE above.
Is the SDK covered by the free PDFluent editor licence? No. The PDFluent desktop editor is free to use, including at work, but that licence covers the application itself. Embedding, linking, or calling this SDK (or any of its crates or language bindings) from your own software is covered by the two licences above.
Until 1 September 2026 LICENSE held the PDFluent Commercial License v1.0 of
2 May 2026, and that was the only licence offered. It described licence keys,
tiers and an expiring evaluation, none of which exist. It is kept, unaltered, at
docs/licensing/archive/LICENSE-COMMERCIAL-v1.0-2026-05-02.txt,
because versions published under it are still out there and a licensee is
entitled to read the terms they agreed to.
From 1 September 2026 LICENSE carried the two-licence explanation above and
the AGPL text sat beside it in LICENSE-AGPL. Since 7 September 2026 there is
one AGPL text, in LICENSE, and this section is the explanation.
