Skip to main content

distillPDF

Turn any PDF into clean, LLM-ready HTML or Markdown — structure-aware, pure-Rust, MIT-licensed.

PyPI Python versions Docs License: MIT CI Built with Rust

distillpdf does structure-aware PDF extraction: it reconstructs a document's structure — reading order, headings, paragraphs, lists, tables, and figures — then emits compact, semantic HTML or Markdown (or plain text) ready to feed to an LLM or a RAG pipeline. No styling noise, no layout junk. It's pure Rust on lopdf, shipped to Python via PyO3 + maturin as a small, self-contained wheel — a lightweight, permissively licensed alternative to AGPL/heavyweight extractors (PyMuPDF, pdfminer, Unstructured), with no system dependencies and no Python runtime deps.

OCR for scanned PDFs: detect image-only pages and turn them into clean HTML or a compact searchable PDF, with a bundled offline engine or an optional accurate VLM — OCR guide » · example notebook »

Install

pip install distillpdf

Prebuilt wheels — no compiler or system libraries required. Installing also puts a distillpdf command on your PATH.

Quickstart

import distillpdf

doc = distillpdf.open("paper.pdf")        # or distillpdf.from_bytes(data)

doc.to_html()                             # writes paper.html (one self-contained file)
doc.to_markdown()                         # writes paper.md + an img/ folder of figures

html     = doc.to_html(return_string=True)   # ...or get the rendered string back instead
text     = doc.extract_text()                # plain text, in reading order
abstract = doc.section("abstract")           # one section's HTML (or None if no match)

By default these methods write a file and return 1; pass return_string=True for the string. PDF to HTML/Markdown — full guide »

distillpdf paper.pdf                  # HTML to stdout
distillpdf paper.pdf -o paper.html    # ...or to a file (.md infers Markdown)
distillpdf paper.pdf --markdown       # Markdown to stdout
distillpdf *.pdf -o out/              # batch: out/<name>.html per input
distillpdf scan.pdf --ocr             # OCR a scan → scan.searchable.pdf (bundled, no extra)

Command-line guide »

What's in the box

  • Rendering modes & image handling — section-first or page-first HTML/Markdown, an optional table of contents, and embed / external (an img/ folder) / drop image modes. Rendering »
  • Raw extractionextract_tables(), rich analyze_tables(), extract_images(), extract_links(), extract_fonts() give you the structured pieces, not rendered output. Extraction »
  • The .dpdf document modeldistill() once to a durable file, then re-render and query it forever with no source PDF and no re-analysis. .dpdf »
  • Honest search — coverage-reporting lexical find() (never a silent miss) and opt-in semantic search() over BAAI/bge-m3 vectors stored inside the .dpdf. Search »
  • OCR, two tiers — a bundled fast Tesseract engine (~0.8 s/page, offline, no download) and an optional accurate granite-docling VLM (structure + tables), folded into the same HTML / Markdown / searchable-PDF outputs. OCR » · setup »
  • An agent shell over .dpdf — any shell with distillpdf installed can drive info / toc / read / find / search against a distilled model, no SDK or server. CLI »

Lazy engine (experimental)

Opt in with engine="lazy" to read the PDF container through an on-demand index instead of parsing it whole, keeping peak memory far below the file size on large documents:

doc = distillpdf.open("10000-pages.pdf", engine="lazy")
doc.engine          # "lazy"

The output is identical to the default engine="eager" — it is a memory strategy, not a fidelity choice, and it is regression-tested against the eager route as the oracle. Damaged cross-reference data is rebuilt in place by a bounded forward scan, so a broken file stays lazy; only the rare shapes the index refuses — an oversized object, an unusually deep page tree, an unusual encryption — fall back to the eager engine, so engine="lazy" never turns a readable PDF into an error. The fallback is never silent: doc.engine then reports "lazy (eager fallback)". Experimental in that the default engine may change in a future release — the keyword and its two values are stable. Lazy engine »

Comparison

distillPDF PyMuPDF pdfminer.six Unstructured
License MIT AGPL / commercial MIT Apache (heavy deps)
Structure-aware HTML partial
System deps none none none many
Implementation Rust C Python Python

Documentation

Full documentation — guides, the Python API reference, and the .dpdf format spec — lives at distillpdf.readthedocs.io. New here? Start with Getting started, then the Python API reference and the .dpdf format reference.

Early release — testers wanted

This is a young project and the API is small and may still change. If you have PDFs that come out wrong, please open an issue with the file (or a description) — real-world documents are exactly what this needs to get better. The .dpdf document model is also experimental (schema_version 0) and not yet a stable contract.

Contributing

Feedback is the fastest way to improve this. Try it on your PDFs and tell me where the output is wrong, star the repo if it's useful, and PRs are welcome. See Contributing and development to build from source or run the tests.

License

MIT — see LICENSE. Use it anywhere, including commercial and closed-source projects.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

distillpdf-0.1.1-cp38-abi3-win_amd64.whl (10.1 MB view details)

Uploaded CPython 3.8+Windows x86-64

distillpdf-0.1.1-cp38-abi3-manylinux_2_39_x86_64.whl (9.4 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.39+ x86-64

distillpdf-0.1.1-cp38-abi3-macosx_11_0_arm64.whl (8.8 MB view details)

Uploaded CPython 3.8+macOS 11.0+ ARM64

File details

Details for the file distillpdf-0.1.1-cp38-abi3-win_amd64.whl.

File metadata

  • Download URL: distillpdf-0.1.1-cp38-abi3-win_amd64.whl
  • Upload date:
  • Size: 10.1 MB
  • Tags: CPython 3.8+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for distillpdf-0.1.1-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 975ceed89c9f263d1c50afff23bf74c362d4dad68b026b00da5cb7233f900d04
MD5 131c8dff116b5e9f5e4591b8f078435c
BLAKE2b-256 e67dd0dc63544a24d29a35554f4519f236187e2cc85d1d7be1fbb71308bfce71

See more details on using hashes here.

Provenance

The following attestation bundles were made for distillpdf-0.1.1-cp38-abi3-win_amd64.whl:

Publisher: publish.yml on kkollsga/distillpdf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file distillpdf-0.1.1-cp38-abi3-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for distillpdf-0.1.1-cp38-abi3-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 bf12af431f172d726c65d7c880c6b6c967c8627729ae24da31bbff149b71c08a
MD5 41d00ca9444b9e2ef25d7f3b21be4a2c
BLAKE2b-256 7dd3a29462b50eea08862d7f3cbfd1372ccf405bc94693503254f3dc85b2c04f

See more details on using hashes here.

Provenance

The following attestation bundles were made for distillpdf-0.1.1-cp38-abi3-manylinux_2_39_x86_64.whl:

Publisher: publish.yml on kkollsga/distillpdf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file distillpdf-0.1.1-cp38-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for distillpdf-0.1.1-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3a4df4dc78df93420d2f1eb47bbeac7bad50054a2fa71358a7d2b7df4c6f411b
MD5 718be0c2b6737397e28f23afbeaa3779
BLAKE2b-256 54abd6369fe9922184c08f91558bffc01cee2b0d4b7edff4a1034fa6a96ccbdc

See more details on using hashes here.

Provenance

The following attestation bundles were made for distillpdf-0.1.1-cp38-abi3-macosx_11_0_arm64.whl:

Publisher: publish.yml on kkollsga/distillpdf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page