Free & open source (MIT) for Python · C# · Go · PHP · Ruby · Node · Delphi · Swift

The PDF library
your whole stack can share.

Generate archival PDF/A, sign documents with PAdES, encrypt with AES-256, and produce accessible PDF/UA, natively in the language you already use. It runs entirely on your servers, so no data leaves your network — and it is MIT licensed with every feature free, no keys and no AGPL strings.

Validated by the independent reference validator you can run yourself: veraPDF → verify it yourself

Generate documents at the speed of your API

A memory-safe Rust core with no garbage collector and a lock-free, Send object model. No GC pauses, no spikes, predictable latency, and throughput that scales with every core you add.

10,000 full PDFs generated in ~3 seconds
2.4 ms to build a real, text-heavy page
~22 MB RAM generating thousands in parallel

Near-linear scaling across cores

documents / second · one independent document per task
1 core 413
2 cores 758
4 cores 1,411
8 cores 2,601
14 cores 3,415 · 8.3×

* Each document is a one-page report (header, title and 35 lines of shaped, subsetted Unicode text), benchmarked on an Apple M3 Max. Numbers are reproducible: cargo run --release -p pdf --example stress.

"Serious" PDF support is scarce and uneven

Almost every language can emit a simple PDF. Almost none have a modern, complete library for what regulated businesses need: legal archival (PDF/A), juridically-valid signatures (PAdES), AES-256 for LGPD/GDPR, and accessibility (PDF/UA).

So teams settle for old incomplete libs, fragile HTML→PDF via headless Chrome, or expensive per-document SaaS that ships your sensitive data off-site. Building it right takes years of ISO 32000 + validator work.

  • Runs on your servers: your documents never leave your network, and nothing phones home.
  • Auditable output: the same input always produces the same file, so you can diff and verify it.
  • Dependable: a memory-safe core that won't crash the service generating your documents.
  • Free and open source: MIT licensed, every feature included, never a meter that bills you per document.
  • No legal landmines: none of the AGPL or per-server licensing of iText / Aspose.

Free to build with. Free to ship.

Generate everyday PDFs and ship the regulated-grade features (archival, signatures, encryption, accessibility) too. Everything is free, in every language you use.

Community free

  • Pages & vector graphics
  • Embedded/subset fonts, Unicode shaping
  • Justified paragraphs & tables
  • Images (JPEG/PNG/alpha/16-bit)
  • Hyperlinks, bookmarks & watermarks
  • Form fill & flatten
  • Merge / split / rotate, text & image extraction

Full-featured

  • PDF/A: 1b / 2b / 2a / 3b / 3a / 4 / 4e / 4f, plus convert existing PDFs to basic profiles (1b/2b/3b)
  • Digital signatures: PKCS#7, visible & multiple
  • PAdES: B-B / B-LT / B-LTA + RFC 3161 timestamps
  • Signature validation: verify any signed PDF
  • ZUGFeRD / Factur-X: electronic invoices
  • Redaction: truly remove page content
  • Encryption: RC4 / AES-128 / AES-256 (R6)
  • Page rendering: render a page to a PNG image
  • Accessibility: Tagged PDF / PDF/UA-1
  • AcroForm: fields with generated appearances

One engine. Eight languages. Identical behavior.

Every binding calls the same Rust core, so a feature behaves the same in Python as in Go, with no per-language quirks to debug in production.

Author a tagged PDF/A in a few lines

# pip install rustpdf
import rustpdf

with rustpdf.Document() as doc:
    doc.pdfa(rustpdf.PdfaLevel.A2A).set_info(title="Report")
    f = doc.add_font_file("Roboto-Regular.ttf")
    doc.add_page()
    doc.show_text(f, 20, 72, 760, "Title", heading_level=1)
    data = doc.to_bytes()

with rustpdf.EditableDoc.load(data) as ed:
    ed.encrypt(owner="owner", method=rustpdf.Encryption.AES256)
    ed.save("secured.pdf")
// npm install rustpdf
const { Document, Encryption } = require("rustpdf");

const doc = new Document();
doc.pdfa();                       // PDF/A-2b
const f = doc.addFontFile("Roboto-Regular.ttf");
doc.addPage();
doc.showText(f, 20, 72, 760, "Invoice #1024");
const bytes = doc.toBytes();      // archival-grade PDF
// dotnet add package RustPdf
using RustPdf;

using var doc = new Document();
doc.Pdfa(PdfaLevel.A2a).Tagged().SetInfo(title: "Report");
int f = doc.AddFontFile("Roboto-Regular.ttf");
doc.AddPage();
doc.ShowText(f, 20, 72, 760, "Title", headingLevel: 1);
byte[] bytes = doc.ToBytes();      // archival-grade PDF
// go get github.com/rustpdf/rustpdf-go@latest
doc, _ := rustpdf.New()
defer doc.Close()
doc.PdfaLevel(rustpdf.A2a)
doc.Tagged()
doc.SetInfo(rustpdf.Info{Title: "Report"})
f, _ := doc.AddFontFile("Roboto-Regular.ttf")
doc.AddPage()
doc.ShowText(f, 20, 72, 760, "Title", 1) // heading level 1 = H1
data, _ := doc.ToBytes()
// composer require rust-pdf/rustpdf
use RustPdf\Document;
use RustPdf\PdfaLevel;

$doc = new Document();
$doc->pdfa(PdfaLevel::A2a)->setInfo(title: 'Report');
$f = $doc->addFontFile('Roboto-Regular.ttf');
$doc->addPage()->showText($f, 20, 72, 760, 'Title', 1);
$bytes = $doc->toBytes();          // archival-grade PDF
# gem install rustpdf
doc = RustPdf::Document.new
doc.pdfa(RustPdf::Pdfa::A2A).info(title: "Report")
f = doc.add_font_file("Roboto-Regular.ttf")
doc.add_page
   .show_text(f, 20, 72, 760, "Title", heading_level: 1)
data = doc.to_bytes               # archival-grade PDF
// add RustPdf.pas to your unit search path (rustpdf.dev/docs/delphi)
Doc := TPdfDocument.Create;
try
  Doc.Pdfa(palA2A).Tagged.SetInfo('Report', '', '', '', '');
  F := Doc.AddFontFile('Roboto-Regular.ttf');
  Doc.AddPage.ShowText(F, 20, 72, 760, 'Title', 1);   // heading level 1 = H1
  Bytes := Doc.ToBytes;            // archival-grade PDF
finally
  Doc.Free;
end;
// SwiftPM: download the rustpdf-swift package from rustpdf.dev/docs/swift
import RustPdf

let doc = try Document()
try doc.pdfa(.a2a).tagged().setInfo(DocumentInfo(title: "Report"))
let f = try doc.addFont(path: "Roboto-Regular.ttf")
try doc.addPage()
try doc.showText(font: f, size: 20, x: 72, y: 760, "Title", headingLevel: 1)
let bytes = try doc.toBytes()      // archival-grade PDF, links on macOS & iOS

Run the validators yourself.

Generate a document, then check it with the same independent validator we gate every release on. No account, no upload: it all runs on your machine, against the bytes rust-pdf produced. PDF/A and accessibility are free, like every other feature — no key, no card, no sign-up.

# 1 · author an archival, accessible PDF/A-2a (report.py)
#     pip install rustpdf
from rustpdf import Document, PdfaLevel, Align

with Document() as doc:
    doc.pdfa(PdfaLevel.A2A).tagged()   # PDF/A-2a + tagged (PDF/UA)
    doc.set_info(title="Quarterly Report", author="rust-pdf")
    font = doc.add_font_file("DejaVuSans.ttf")  # embedded + subset
    doc.add_page((595, 842))           # A4, points
    doc.show_text(font, 24, 72, 760, "Quarterly Report", heading_level=1)
    doc.paragraph(font, 11, 72, 700, 451,
                  "Deterministic bytes, no timestamps, "
                  "fully tagged for accessibility.", Align.JUSTIFY)
    doc.save("out.pdf")

# 2 · or PDF/A-4f (PDF 2.0) with an embedded file (af.py)
with Document() as doc:
    doc.pdfa(PdfaLevel.A4F)   # PDF/A-4f (PDF 2.0)
    doc.set_info(title="Invoice 2026-001")
    font = doc.add_font_file("DejaVuSans.ttf")
    doc.add_page((595, 842))
    doc.show_text(font, 14, 72, 760, "Invoice 2026-001")
    doc.attach_file("invoice.xml", "application/xml",
                    open("invoice.xml", "rb").read())  # payload
    doc.save("af.pdf")

# 3 · validate with veraPDF, the reference validator (offline):
verapdf out.pdf          → auto-detects flavour, isCompliant=true
verapdf -f 2a out.pdf    → PDF/A-2a (archival) PASS
verapdf -f ua1 out.pdf   → PDF/UA-1 (accessibility) PASS
verapdf -f 4f af.pdf     → PDF/A-4f (embedded files) PASS

# 4 · machine-readable report + your own rules, for CI
verapdf --format xml -f 2a out.pdf > report.xml
verapdf --policyfile policy.sch out.pdf  → add your own rules

Every release is gated on this passing for PDF/A 1b–3a and A-4 and PDF/UA-1. More in the validation FAQ or your language's reference docs.

Everything is free.

rust-pdf is MIT licensed and every feature is included — no keys, no per-document metering, no per-server fees and no AGPL strings. Use it in commercial and closed-source products.

  • ✓ PDF/A (1b / 2b / 2a / 3b / 3a / 4 / 4e / 4f) + convert existing PDFs
  • ✓ ZUGFeRD / Factur-X electronic invoices
  • ✓ Encryption (RC4 / AES-128 / AES-256)
  • ✓ Digital signatures & PAdES (B-B / B-LT / B-LTA) + validation
  • ✓ RFC 3161 timestamps + LTV (DSS)
  • ✓ True redaction (remove page content)
  • ✓ Accessibility (Tagged PDF / PDF/UA-1)
  • ✓ Page rendering (PDF page to PNG image)
  • ✓ All ten language bindings

Get started View source

FAQ

Is it really free?

Yes. rust-pdf is MIT licensed and every feature is included: PDF/A, ZUGFeRD/Factur-X, encryption (RC4/AES-128/AES-256), digital signatures and PAdES (B-B/B-LT/B-LTA), RFC 3161 timestamps with LTV, signature validation, true redaction, PDF/UA accessibility and page rendering. Use it commercially and in closed-source products.

Is anything sent off my servers?

No. Everything runs locally and there are no network calls of any kind — ideal for government, banking and healthcare.

Do I need to publish my own source?

No. MIT is permissive: you can embed rust-pdf in commercial and closed-source products. There are no copyleft or AGPL strings.

How is this validated?

veraPDF, the independent reference validator, checks every release (PDF/A 1b–3a and A-4 + PDF/UA-1). You can run the same checks yourself.