PDF parsing, text extraction and rendering in pure Rust with pythonic bindings
Project description
pdfboss
A PDF engine written from scratch in Rust — parse, extract text, rasterize to PNG. One core, a CLI, and pythonic bindings.
Motivation
Reading a PDF shouldn't mean linking a C library. pdfboss is a clean-room reader built straight from the ISO 32000 specification: no C dependencies, no bindings to anyone else's engine — just safe Rust with a small, obvious API. The same core powers a CLI and a native Python extension, so a script and a service share one implementation.
It is a lenient reader: real-world files are damaged, and pdfboss recovers rather than refuses — reconstructing broken cross-reference tables, tolerating wrong stream lengths, and skipping garbage operators instead of erroring out.
Install
Python
pip install pdfboss
Prebuilt abi3 wheels (CPython ≥ 3.12) for Linux and macOS; no toolchain required.
Rust
cargo add pdfboss-core pdfboss-text pdfboss-render # library crates
cargo install pdfboss-cli # the `pdfboss` binary
Usage
CLI
pdfboss info report.pdf # version, page count, sizes, metadata
pdfboss text report.pdf --page 2 # extract text (omit --page for all)
pdfboss render report.pdf --page 1 -o page.png --scale 2.0
pdfboss obj report.pdf 5 # pretty-print object 5
Python
import pdfboss
doc = pdfboss.Document("report.pdf") # or Document(data=raw_bytes)
print(doc.page_count, doc.version, doc.metadata)
page = doc[0]
print(page.width, page.height, page.rotation)
text = page.extract_text() # or doc.extract_text() for all pages
png = page.render(scale=2.0) # PNG bytes
Rust
use pdfboss_core::Document;
let doc = Document::open("report.pdf")?;
let page = doc.page(0)?;
let text = pdfboss_text::extract_text(&doc, &page)?;
let pixmap = pdfboss_render::render_page(&doc, &page, 2.0)?;
pixmap.save_png("page.png")?;
What's inside
| Crate | Responsibility |
|---|---|
pdfboss-core |
Tokenizer, object model, stream filters, cross-references, object streams, document & page tree, content-stream operators |
pdfboss-text |
Simple and CID/Type0 fonts, standard encodings, ToUnicode CMaps, positional text extraction |
pdfboss-render |
Anti-aliased vector rasterizer — paths, fills, strokes, clipping, color, images — to RGBA/PNG |
pdfboss-cli |
The pdfboss command-line tool |
pdfboss-py |
PyO3 extension module (pdfboss._pdfboss) built with maturin |
Supported: classic, stream, and hybrid cross-references with recovery scanning · object streams · FlateDecode, LZWDecode, ASCII85Decode, ASCIIHexDecode, RunLengthDecode + PNG/TIFF predictors · DCTDecode (JPEG) images · Standard-handler decryption — RC4 and AES-128/256 (empty user password) · page-tree attribute inheritance · text extraction with ToUnicode and WinAnsi/MacRoman/Standard encodings · rasterization of paths, fills (nonzero & even-odd), strokes, transforms, clipping, image/form XObjects, and embedded-TrueType glyph outlines.
Benchmarks
Against other Python PDF libraries over 40 real-world PDFs (best-of-3 per file, aggregated over the files every library handled; pages/sec, higher is faster):
pdfboss is the fastest library measured on both operations — including against the C-backed PyMuPDF. On text extraction it reaches 3,184 pages/s versus PyMuPDF's 460 (≈7×), and 30–170× the pure-Python readers. On open + parse it reaches 280,873 pages/s versus PyMuPDF's 102,576 (≈2.7×): lazy page-tree loading means opening a document reads only its declared page count instead of parsing every page dictionary up front. Rendering is not compared — pdfboss's rasterizer does not yet paint every glyph, so timing it against full renderers would be misleading.
Numbers are machine-dependent; reproduce with benchmarks/bench.py.
Limitations
Rendered pages paint the outlines of embedded TrueType glyphs (Type0/CIDFontType2 under Identity, and simple /TrueType fonts via their cmap). Text in other fonts (CFF/Type1 programs, the standard 14, subset fonts without a usable cmap) is still positioned but not drawn.
Not yet supported in v0.1 (they error or degrade gracefully, and are on the roadmap): password-protected documents (the empty user password is handled for both RC4 and AES) · non-TrueType glyph outlines (CFF/Type1) · shadings and tiling patterns · JPXDecode (JPEG 2000).
Development
cargo test --workspace # Rust test suite
cargo clippy --workspace --all-targets -- -D warnings
maturin develop # build the Python extension into your venv
pytest # Python integration tests
License
Dual-licensed under either of
- MIT license (LICENSE-MIT)
- Apache License, Version 2.0 (LICENSE-APACHE)
at your option. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be dual-licensed as above, without any additional terms or conditions.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pdfboss-0.1.0.tar.gz.
File metadata
- Download URL: pdfboss-0.1.0.tar.gz
- Upload date:
- Size: 165.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0d44c19d40ac87caee15bc282b6dcd6c7bc73e08f3dd1ed319488abc0e029b0c
|
|
| MD5 |
58d1eef89b226e024de922eba89625cd
|
|
| BLAKE2b-256 |
2a616dcba22a710719a8f59882cf6a5821cfc24e29ac77fdce609fa35b5f822f
|
Provenance
The following attestation bundles were made for pdfboss-0.1.0.tar.gz:
Publisher:
release-please.yaml on 4thel00z/pdfboss
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pdfboss-0.1.0.tar.gz -
Subject digest:
0d44c19d40ac87caee15bc282b6dcd6c7bc73e08f3dd1ed319488abc0e029b0c - Sigstore transparency entry: 2169737479
- Sigstore integration time:
-
Permalink:
4thel00z/pdfboss@59059533041077c98a78fd27d0808e4a6b9e3c94 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/4thel00z
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-please.yaml@59059533041077c98a78fd27d0808e4a6b9e3c94 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pdfboss-0.1.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: pdfboss-0.1.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 738.7 kB
- Tags: CPython 3.12+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
807bf0537b720be619015e001b640a20addaad20a1638a7f667aafbeca9c709d
|
|
| MD5 |
9572cb5837577896c7b7c9c25495f04c
|
|
| BLAKE2b-256 |
ac8c495789390fe17d44b8c3479f07b3184e4a2d73ffbb5fb3a11736941a614e
|
Provenance
The following attestation bundles were made for pdfboss-0.1.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release-please.yaml on 4thel00z/pdfboss
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pdfboss-0.1.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
807bf0537b720be619015e001b640a20addaad20a1638a7f667aafbeca9c709d - Sigstore transparency entry: 2169737494
- Sigstore integration time:
-
Permalink:
4thel00z/pdfboss@59059533041077c98a78fd27d0808e4a6b9e3c94 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/4thel00z
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-please.yaml@59059533041077c98a78fd27d0808e4a6b9e3c94 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pdfboss-0.1.0-cp312-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: pdfboss-0.1.0-cp312-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 642.3 kB
- Tags: CPython 3.12+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d0b8b13163e2f8bd1ea562232aa47c176053dab491b985b763e1c0b28caf781d
|
|
| MD5 |
a05e774a61b0abcb30e5f2ffc89adc2c
|
|
| BLAKE2b-256 |
e8104d0ce09ed47e71f13cb25b69851929c80a714a0fb80795db5fda249f849d
|
Provenance
The following attestation bundles were made for pdfboss-0.1.0-cp312-abi3-macosx_11_0_arm64.whl:
Publisher:
release-please.yaml on 4thel00z/pdfboss
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pdfboss-0.1.0-cp312-abi3-macosx_11_0_arm64.whl -
Subject digest:
d0b8b13163e2f8bd1ea562232aa47c176053dab491b985b763e1c0b28caf781d - Sigstore transparency entry: 2169737519
- Sigstore integration time:
-
Permalink:
4thel00z/pdfboss@59059533041077c98a78fd27d0808e4a6b9e3c94 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/4thel00z
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-please.yaml@59059533041077c98a78fd27d0808e4a6b9e3c94 -
Trigger Event:
push
-
Statement type: