A PDF engine written from scratch in Rust.
Parse, extract text, rasterize to PNG. One core, a CLI, and pythonic bindings. A clean-room reader built from the ISO 32000 spec. Safe Rust, no C dependencies, no bindings to another engine.
Prebuilt abi3 wheels for CPython 3.12+, no toolchain required.
The toolkit
Point it at a path or a URL.
The CLI ships info, text, md, render, images and tui, creation via create blank|text|images, and explorer subcommands json, hex, q (jq-style queries) and obj. Each takes a local path or an http(s) URL, fetched in byte ranges rather than downloaded whole.
$ pdfboss info quarterly.pdf $ pdfboss md quarterly.pdf $ pdfboss render quarterly.pdf $ pdfboss images quarterly.pdf # explore a remote file without downloading it $ pdfboss json https://example.com/report.pdf $ pdfboss q quarterly.pdf '.header.version' $ pdfboss create text notes.txt -o out.pdf $ pdfboss tui quarterly.pdf
import pdfboss doc = pdfboss.Document("report.pdf") text = doc.extract_text() md = doc.extract_markdown() png = doc[0].render(scale=2.0) # PNG bytes images = doc[0].extract_images() # async, straight off the wire doc = await pdfboss.AsyncDocument.open_url( "https://example.com/report.pdf" )
Benchmarks
Measured on real PDFs.
Apple M3 Pro, 40 real-world PDFs, pdfboss 0.22.0. The fastest library measured on text extraction, open + parse, and rendering, including against the C-backed PyMuPDF.
Text extraction: ~15× PyMuPDF, ~23× pdf_oxide.
Open + parse: ~2.1× pdf_oxide.
Rendering the mixed corpus: ~19% ahead of pdfium itself.
On a 544-page JBIG2 scanned book, fastest of the four measured.
Text extraction
Apple M3 Pro · 40 real-world PDFs · pages per second, higher is better
~15× PyMuPDF, ~23× pdf_oxide. Open + parse tells the same story: 405,000 pages/s to pdf_oxide’s 190,000.
Rendering
38 certified files · 888 pages · pages per second
Fastest on the mixed corpus, ~19% ahead of pdfium itself, with no C in it. pdfplumber renders via pdfium.
Scanned documents
544-page JBIG2 book · pages per second
~14% ahead of the C-backed renderers, and the only one of the four with no C in it.
Every file in the rendering benchmark is certified before timing: pages reporting dropped or approximated content exclude their file, and an ink-coverage gate catches silently skipped work.
| Engine | Reading-order NID ↑ | Total time |
|---|---|---|
| pdf-inspector | 0.915 | 0.44 s |
| liteparse | 0.913 | 0.75 s |
| opendataloader | 0.902 | 2.57 s |
| pymupdf4llm | 0.886 | 17.12 s |
| pdfboss md | 0.882 | 0.15 s |
| markitdown | 0.844 | 16.17 s |
pdfboss md scores mid-field on quality and reads the whole corpus in about a seventh of a second, ~3× faster than the fastest competing Markdown engine.
Under the hood
Ten crates, one implementation.
No borrowed decoders. pdfboss ships its own JPEG 2000 (ITU-T T.800), JBIG2, CCITT and ICC codecs, an anti-aliased vector rasterizer, layout analysis to plain text and Markdown, async range-fetching I/O, a CLI and TUI, and PyO3 bindings.
pdfboss-core
The clean-room reader, built from ISO 32000.
pdfboss-text
Text extraction and layout analysis.
pdfboss-output
Plain text and Markdown.
pdfboss-render
The anti-aliased vector rasterizer.
pdfboss-jpx
JPEG 2000 decoding, ITU-T T.800.
pdfboss-icc
ICC color profiles.
pdfboss-aio
Async range-fetching I/O.
pdfboss-cli
The command line.
pdfboss-tui
The terminal UI.
pdfboss-py
PyO3 bindings for Python.
Reporting
“Rendering is lenient and it says so.”
Broken files still open
Real-world PDFs are messy, so the reader is lenient by design: it reconstructs broken cross-reference tables, tolerates wrong stream lengths, and skips garbage operators instead of refusing the file.
Nothing is dropped silently
Content the renderer cannot read is skipped so the rest of the page still rasterizes, and every dropped or approximated item lands in a report: render warnings on stderr, render_reporting in Rust, Page.render_reporting() in Python.