oxpdf
High-performance, streaming PDF engine for Python — powered by Rust 🦀
oxpdf provides blazing-fast, memory-bounded, layout-aware PDF processing for Python. Built from the ground up in Rust with zero heavy C/C++ dependencies, oxpdf delivers orders-of-magnitude faster parsing and Markdown conversion than legacy Python libraries (pypdf, pdfplumber, pdfminer.six).
Key Features
- ⚡ Blazing Fast: SIMD/SWAR-accelerated tokenization, streaming parser.
- 📐 Layout-Aware Markdown: Recursive XY-Cut algorithm for accurate multi-column reading order.
- 📊 Table Reconstruction: Geometric table recovery into clean GitHub-Flavored Markdown tables.
- 🖼️ Zero-Copy Image Extraction: Direct JPEG stream dumps from DCTDecode and PNG synthesis from Flate streams.
- 🛡️ Memory-Bounded & Safe: Protected against cyclic references, decompression bombs, and OOM.
- 🔒 PDF Security: Support for standard PDF encryption (RC4, AES-128, AES-256).
Installation
pip install oxpdf
Or build from source using maturin:
cd oxpdf-python
maturin develop --release
Quickstart
1. Document Loading & Inspection
import oxpdf
# Load from file
doc = oxpdf.Document.from_file("annual_report.pdf")
# Or load from bytes
with open("annual_report.pdf", "rb") as f:
doc = oxpdf.Document.from_bytes(f.read())
print(f"Total pages: {doc.page_count()}")
print(f"Total objects: {doc.object_count()}")
print(f"Page IDs: {doc.get_page_ids()}")
2. Layout-Aware Markdown Extraction
Convert complex documents into structured GitHub-Flavored Markdown with preserved headers and reconstructed tables:
import oxpdf
doc = oxpdf.Document.from_file("financial_statement.pdf")
# Extract entire document as Markdown
markdown = doc.to_markdown_all()
print(markdown)
# Or convert a specific page by ID
page_ids = doc.get_page_ids()
first_page_md = doc.to_markdown(page_ids[0])
print(first_page_md)
3. Extracting Plaintext
import oxpdf
doc = oxpdf.Document.from_file("document.pdf")
# Extract all pages
pages = doc.extract_text_all()
for idx, page_text in enumerate(pages, 1):
print(f"--- Page {idx} ---")
print(page_text)
# Or extract a specific page
page_ids = doc.get_page_ids()
text = doc.extract_text(page_ids[0])
4. Zero-Copy Image Extraction
Extract embedded images directly as JPEG or PNG without transcoding:
import oxpdf
doc = oxpdf.Document.from_file("presentation.pdf")
# Extract all images from the document
images = doc.extract_images_all()
print(f"Found {len(images)} images")
for img in images:
print(f"Name: {img.name}, Format: {img.format}, Size: {img.width}x{img.height}")
# Write image bytes directly to disk
with open(f"{img.name}.{img.format}", "wb") as f:
### 5. High-Fidelity Pure-Rust Rendering
Render pages directly to PNG image files or in-memory PNG bytes using the pure-Rust `#![forbid(unsafe_code)]` rasterization engine (zero C/C++ dependencies):
```python
import oxpdf
doc = oxpdf.Document.from_file("annual_report.pdf")
# Render page 1 directly to a PNG file at 150 DPI
doc.render_page_to_png(1, "page_1.png", dpi=150.0)
# Or render to in-memory PNG bytes (e.g. for GUI display or web APIs)
png_bytes = doc.render_page_to_bytes(1, dpi=300.0)
print(f"Rendered PNG size: {len(png_bytes)} bytes")
6. In-Memory Text Replacement & Document Mutation
import oxpdf
doc = oxpdf.Document.from_file("contract.pdf")
# Replace text on page 1
doc.replace_text(1, "Draft Agreement", "Executed Agreement")
# Save updated document
doc.save("contract_executed.pdf")
API Reference
oxpdf.Document
Document(data: bytes): Constructor from byte buffer.Document.from_bytes(data: bytes) -> Document: Load from bytes.Document.from_file(path: str) -> Document: Load from a file path.page_count() -> int: Returns the total number of pages.get_page_ids() -> list[int]: Returns indirect object IDs of all pages.extract_text(page_id: int) -> str: Extracts plaintext from a page.extract_text_all() -> list[str]: Extracts plaintext from all pages.to_markdown(page_id: int) -> str: Converts a page to layout-aware Markdown.to_markdown_all() -> str: Converts all pages to unified Markdown.extract_images(page_id: int) -> list[PyExtractedImage]: Extracts images from a page.extract_images_all() -> list[PyExtractedImage]: Extracts all images.render_page_to_png(page_index_or_id: int, path: str, dpi: float = 150.0): Renders a page directly to a PNG file.render_page_to_bytes(page_index_or_id: int, dpi: float = 150.0) -> bytes: Renders a page and returns PNG bytes.replace_text(page_index_or_id: int, target: str, replacement: str): Replaces text strings in page content streams.save(path: str) -> int: Saves the modified document to a filesystem path.save_bytes() -> bytes: Returns serialized PDF document bytes.object_count() -> int: Returns the total object count in the xref table.
oxpdf.PyExtractedImage
name: str: Image resource identifier (e.g./Im1).format: str: Image format (jpeg,png,rgb,gray).width: int: Image pixel width.height: int: Image pixel height.data: list[int]: Raw byte data.to_bytes() -> bytes: Direct Pythonbytesrepresentation.
License
Dual-licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
Metadata
Release files for oxpdf-python 1.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| oxpdf_python-1.5.0-cp38-abi3-win_amd64.whl | CPython 3.8 | abi3 | Windows x86-64 | Details for oxpdf_python-1.5.0-cp38-abi3-win_amd64.whl |
Release files / oxpdf_python-1.5.0-cp38-abi3-win_amd64.whl
| Download URL | oxpdf_python-1.5.0-cp38-abi3-win_amd64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.8 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
b613f5e06411bce8e711a6f7877190ac9861c01df7ff8e4f9675ac2cbc228921
|
|
BLAKE2b-256 checksum How to use checksums |
16ece673a50b51856d2d2636ab41b2bd8bca654b54ab1ae9921aa890ce7f4416
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Security for oxpdf-python 1.5.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.