PDF editing and rendering for Python, powered by Rust (lopdf + hayro). MIT, zero dependencies, lightweight wheels.
Project description
pylopdf
PDF editing and rendering for Python, powered by Rust — lopdf for editing and hayro (the pure-Rust PDF renderer adopted by typst) for rendering.
MIT licensed, zero runtime dependencies, lightweight wheels. Covers the common pymupdf use cases without the AGPL.
Why pylopdf?
| pylopdf | pymupdf | pypdf | pypdfium2 | |
|---|---|---|---|---|
| License | MIT | AGPL / commercial | BSD | Apache/BSD |
| Wheel size | ~3.5 MB | ~40 MB+ | small (pure Python) | ~8 MB |
| Editing (merge / split / metadata) | ✅ | ✅ | ✅ | limited |
| Rendering (PNG / SVG) | ✅ | ✅ | ❌ | ✅ (PNG) |
| Text extraction | ✅ (basic) | ✅ (advanced) | ✅ | ✅ |
| Implementation | pure Rust | C | Python | C++ (PDFium) |
- Fits size-constrained environments such as AWS Lambda
- Safe for commercial projects that need to avoid the AGPL
- abi3: one wheel covers Python 3.10–3.14
- API modeled after pymupdf
Limitations: no precise layout analysis, no annotation/form editing. Use pymupdf if you need those.
Install
pip install pylopdf
To render Japanese PDFs without embedded fonts, install the optional CJK fonts (Noto Sans/Serif JP, auto-detected at render time):
pip install pylopdf[cjk]
Building from source (requires a Rust toolchain):
uv sync
Usage
import pylopdf
# Open from a path or bytes
doc = pylopdf.open("input.pdf")
doc = pylopdf.open(stream=pdf_bytes)
# Page count
print(doc.page_count) # same as len(doc)
# Metadata
print(doc.metadata["title"])
doc.set_metadata({"title": "Monthly Report", "author": "Alice"})
# Text extraction (0-based page numbers)
text = doc.get_page_text(0)
# Rendering
png: bytes = doc.render_page(0) # 72 dpi
png2x: bytes = doc.render_page(0, scale=2) # 144 dpi
svg: str = doc.render_page_svg(0)
# Delete pages (split)
doc.delete_page(0)
doc.delete_pages([1, 2])
# Keep/reorder pages
doc.select([2, 0])
# Merge
merged = pylopdf.Document()
merged.insert_pdf(pylopdf.open("a.pdf"))
merged.insert_pdf(pylopdf.open("b.pdf"))
# Save
merged.save("merged.pdf")
data: bytes = merged.tobytes()
# Context manager
with pylopdf.open("input.pdf") as doc:
print(doc.metadata)
# Encrypted PDFs (RC4-40/128, AES-128, AES-256; empty user passwords open transparently)
doc = pylopdf.open("locked.pdf", password="secret")
doc = pylopdf.open("locked.pdf")
if doc.needs_pass:
doc.authenticate("secret") # 0=failed, 2=user, 4=owner, 6=both
# CJK fallback font for PDFs without embedded fonts
# (automatic with pylopdf[cjk]; or bring your own font)
doc.set_fallback_font("NotoSansJP-Regular.otf")
doc.set_fallback_font(font_bytes, kind="serif")
API
pylopdf.Document (pylopdf.open() is an alias constructor):
| Method / property | Description |
|---|---|
Document(filename=None, stream=None, password=None) |
Open from a path or bytes; empty document if both are None |
needs_pass / is_encrypted |
Encryption status (pymupdf-compatible semantics) |
authenticate(password) |
Decrypt with a password (returns 0/1/2/4/6, pymupdf-compatible) |
page_count / len(doc) |
Number of pages |
metadata |
Metadata dict (title, author, subject, keywords, creator, producer, creationDate, modDate, format) |
set_metadata(dict) |
Set metadata (empty string deletes the entry) |
get_page_text(pno) |
Extract text from a page |
render_page(pno, scale=1.0) |
Render a page to PNG bytes |
render_page_svg(pno) |
Render a page to an SVG string |
set_fallback_font(font, kind="sans", index=0) |
Set a fallback font (path/bytes) for non-embedded CJK fonts; None disables auto-detection |
select(page_numbers) |
Keep only the given pages, in the given order |
delete_page(pno) / delete_pages(iterable) |
Delete pages |
insert_pdf(other) |
Append all pages of another document |
save(filename) / tobytes() |
Save |
close() |
Close (supports with) |
For low-level access, use pylopdf.pylopdf_core._Document (a thin lopdf wrapper) directly.
Architecture
Follows the division of labor in the 2026 Rust PDF ecosystem:
pylopdf.Document (Python, pymupdf-style API)
└─ _Document (PyO3)
├─ lopdf 0.44 … editing: open → modify → save
└─ hayro 0.7 … rendering: PNG / SVG (standard fonts embedded)
rust/ # PyO3 bindings
src/pylopdf/ # Python high-level API
tests/ # pytest (Rust behavior is verified through Python tests)
uv sync # build + install dependencies
uv run pytest # tests
uv run ruff check . # lint
uv run mypy src tests # type check
uv build --wheel # build a wheel
uv sync detects Rust source changes and rebuilds automatically (via tool.uv.cache-keys).
License
MIT (lopdf is MIT; hayro is MIT/Apache-2.0)
Project details
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 pylopdf-0.5.0.tar.gz.
File metadata
- Download URL: pylopdf-0.5.0.tar.gz
- Upload date:
- Size: 27.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8ecb17bfc95a11e6bd6799b1f8bdd09cc29911aa4883ca42a7c61d65bd1efb16
|
|
| MD5 |
5fba8c38c7c335d31e67b5acefa5b103
|
|
| BLAKE2b-256 |
766ec0d542f6c3cf8eb804a3dbc3fe855efb4695692ca7989e8809199a74baf2
|
Provenance
The following attestation bundles were made for pylopdf-0.5.0.tar.gz:
Publisher:
release.yml on yhay81/pylopdf
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pylopdf-0.5.0.tar.gz -
Subject digest:
8ecb17bfc95a11e6bd6799b1f8bdd09cc29911aa4883ca42a7c61d65bd1efb16 - Sigstore transparency entry: 2217869353
- Sigstore integration time:
-
Permalink:
yhay81/pylopdf@d2ad0b277b48c2f1bd04e6d975eb1b9061a54eb6 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/yhay81
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d2ad0b277b48c2f1bd04e6d975eb1b9061a54eb6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pylopdf-0.5.0-cp310-abi3-win_amd64.whl.
File metadata
- Download URL: pylopdf-0.5.0-cp310-abi3-win_amd64.whl
- Upload date:
- Size: 3.8 MB
- Tags: CPython 3.10+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
13d5c29f6593ad60f198c4bfcb88427548427cfd20a6bd7aad03a577d432a073
|
|
| MD5 |
6ceca922cab3a2a57dfdf5048b11d333
|
|
| BLAKE2b-256 |
07d023fc50823d7e78f39ba6549a2499340d6f3bdad093a0c3a980ad842ed23c
|
Provenance
The following attestation bundles were made for pylopdf-0.5.0-cp310-abi3-win_amd64.whl:
Publisher:
release.yml on yhay81/pylopdf
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pylopdf-0.5.0-cp310-abi3-win_amd64.whl -
Subject digest:
13d5c29f6593ad60f198c4bfcb88427548427cfd20a6bd7aad03a577d432a073 - Sigstore transparency entry: 2217872420
- Sigstore integration time:
-
Permalink:
yhay81/pylopdf@d2ad0b277b48c2f1bd04e6d975eb1b9061a54eb6 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/yhay81
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d2ad0b277b48c2f1bd04e6d975eb1b9061a54eb6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pylopdf-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: pylopdf-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 4.3 MB
- Tags: CPython 3.10+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
304e3f568c09d410167c874452cfba0ce5c5f651b27c179a83c3117c5a3219e2
|
|
| MD5 |
1702b4a883230c0d4ebd05e9f810d43c
|
|
| BLAKE2b-256 |
71bf0353bcaee5b6e1d0db102e1a0bd365709212aa7cbaba108bcbfc59717ab4
|
Provenance
The following attestation bundles were made for pylopdf-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on yhay81/pylopdf
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pylopdf-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
304e3f568c09d410167c874452cfba0ce5c5f651b27c179a83c3117c5a3219e2 - Sigstore transparency entry: 2217873295
- Sigstore integration time:
-
Permalink:
yhay81/pylopdf@d2ad0b277b48c2f1bd04e6d975eb1b9061a54eb6 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/yhay81
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d2ad0b277b48c2f1bd04e6d975eb1b9061a54eb6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pylopdf-0.5.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: pylopdf-0.5.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 4.2 MB
- Tags: CPython 3.10+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8e098228c77c2de1c64d6fe97c7197d36f1d8f62dbdf48bdac9110ceea0f5dd1
|
|
| MD5 |
8a4ca5909d4be965ac7f3f4cfdcd1d15
|
|
| BLAKE2b-256 |
58be6e80bdf74673c68f7215752e64cbe2f0248f4952885b7a543237c53e57af
|
Provenance
The following attestation bundles were made for pylopdf-0.5.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
release.yml on yhay81/pylopdf
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pylopdf-0.5.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
8e098228c77c2de1c64d6fe97c7197d36f1d8f62dbdf48bdac9110ceea0f5dd1 - Sigstore transparency entry: 2217870761
- Sigstore integration time:
-
Permalink:
yhay81/pylopdf@d2ad0b277b48c2f1bd04e6d975eb1b9061a54eb6 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/yhay81
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d2ad0b277b48c2f1bd04e6d975eb1b9061a54eb6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pylopdf-0.5.0-cp310-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: pylopdf-0.5.0-cp310-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 3.7 MB
- Tags: CPython 3.10+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
490f0ae8ebea546a503915028149ad7d07de2791921c581c9ddfd35d2509c441
|
|
| MD5 |
472b2175f574d529e0744f2023f2cb94
|
|
| BLAKE2b-256 |
447b17022ab9c836224617449410c0c3f61b6c5053682ec5ad80cae6f4d16b8c
|
Provenance
The following attestation bundles were made for pylopdf-0.5.0-cp310-abi3-macosx_11_0_arm64.whl:
Publisher:
release.yml on yhay81/pylopdf
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pylopdf-0.5.0-cp310-abi3-macosx_11_0_arm64.whl -
Subject digest:
490f0ae8ebea546a503915028149ad7d07de2791921c581c9ddfd35d2509c441 - Sigstore transparency entry: 2217870000
- Sigstore integration time:
-
Permalink:
yhay81/pylopdf@d2ad0b277b48c2f1bd04e6d975eb1b9061a54eb6 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/yhay81
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d2ad0b277b48c2f1bd04e6d975eb1b9061a54eb6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pylopdf-0.5.0-cp310-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: pylopdf-0.5.0-cp310-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 4.1 MB
- Tags: CPython 3.10+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30ee1325dafd766184940a814c06043ede745377f37b08eb1931fe93f2f24b8e
|
|
| MD5 |
5be9ef6f7ae5752c796446f55f08ec22
|
|
| BLAKE2b-256 |
18691ec68d5e4237cb19385bca99b090cc28ebe1f25cb3c1e87a72569e5adbbb
|
Provenance
The following attestation bundles were made for pylopdf-0.5.0-cp310-abi3-macosx_10_12_x86_64.whl:
Publisher:
release.yml on yhay81/pylopdf
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pylopdf-0.5.0-cp310-abi3-macosx_10_12_x86_64.whl -
Subject digest:
30ee1325dafd766184940a814c06043ede745377f37b08eb1931fe93f2f24b8e - Sigstore transparency entry: 2217871563
- Sigstore integration time:
-
Permalink:
yhay81/pylopdf@d2ad0b277b48c2f1bd04e6d975eb1b9061a54eb6 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/yhay81
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d2ad0b277b48c2f1bd04e6d975eb1b9061a54eb6 -
Trigger Event:
push
-
Statement type: