mrkeyoor.com_
Wed 23 Sept 00:37 UTC
PyPIDataupdated 22 Sept 2026

pymupdf4llm review

pymupdf4llm 1.28.2 converts PDFs and other MuPDF-readable files into Markdown, plain text, or layout JSON for retrieval and document-processing systems. Its default Layout path reconstructs reading order, headings, tables, page regions, and pictures, then invokes an available OCR engine when page analysis calls for it. The current package pins PyMuPDF and pymupdf-layout to 1.28.2; the matching PyMuPDF release fixes a layout table case where a zero-cell table raised `ValueError`. It can return physical page chunks with metadata, but it does not decide semantic chunk boundaries for an embedding model.

Verdict

pymupdf4llm 1.28.2 installed in 1.7 seconds with 0 audit findings, yet its 12-package environment occupied 243 MB and imported in 1.84 seconds on our box. Install it when its page layout and selective OCR beat simpler extraction on your own corpus, after clearing the AGPL or commercial license and exact-version constraints.

We installed it

Lab card: what happened when we installed pymupdf4llmScreenshot of pymupdf4llm documentation
Install✓ · 1.7s12 packages on disk · 243 MB
Importimport pymupdf4llm in 1.84s · pure Python · requires Python >=3.10
Known vulns0(pip-audit)

Answers from our run

Does pymupdf4llm install cleanly?

Yes. In a fresh container with an empty cache, pip install pymupdf4llm finished in 2 seconds, leaving 12 packages and 243 MB on disk. pip-audit reported no known vulnerabilities.

What does pymupdf4llm need to run?

Python >=3.10, and nothing compiled: it is pure Python. In our run import pymupdf4llm succeeded in 1.84s.

pymupdf4llm or pypdf: which should you use?

pypdf: Use it for PDF text, metadata, forms, merging, and page manipulation when layout inference and OCR orchestration are unnecessary. pymupdf4llm 1.28.2 installed in 1.7 seconds with 0 audit findings, yet its 12-package environment occupied 243 MB and imported in 1.84 seconds on our box.

When should you not use pymupdf4llm?

Your proprietary service has no approved AGPL compliance plan or Artifex commercial license. PyPI labels pymupdf4llm, PyMuPDF, and pymupdf-layout with the dual AGPL 3.0 or commercial terms.

API stability3/5`to_markdown()` remains the main call, but the surrounding contract has moved quickly. The package now activates Layout on import, requires exact PyMuPDF and pymupdf-layout versions, exposes different behavior after a process-wide `use_layout(False)`, and has revised OCR selection and page-chunk records. The changelog also records new output methods and repeated changes to image, table, header, and OCR parameters. Pin all three Artifex packages together and compare saved outputs before accepting an upgrade.
Docs4/5The current README shows Markdown, JSON, plain text, page chunks, selected pages, image writing, HTML tables, OCR controls, layout switching, the batch CLI, and framework integrations. The API reference lists parameter availability and marks options that require legacy mode. Some details still conflict: README OCR prose says a 300 dpi default while the 1.28.2 Layout wrapper source uses 150, and a README page-chunk example places `page_boxes` under metadata even though the change record documents it as a chunk-level key.
Maintenance5/5PyPI published 1.28.2 on 2026-08-06, the unarchived repository was pushed on 2026-08-25, and GitHub reports 2120 stars plus 42 open issues and pull requests. Current tests cover OCR, malicious Markdown links, HTML table output, tabulation failures, LlamaIndex, and named regressions. The matching PyMuPDF 1.28.2 changelog includes a fix for layout table detection returning a zero-cell object, showing that the coordinated version pins carry real parser fixes as well as release churn.
Ecosystem4/5The package receives roughly 2.04 million weekly downloads and sits on PyMuPDF's MuPDF bindings plus the pymupdf-layout model. Its README covers LlamaIndex and LangChain paths, while the converter accepts PDF, XPS, EPUB-family documents, and images; paid PyMuPDF Pro extends the path to Office files. Adoption has real boundaries: Python must be at least 3.10, the core trio uses AGPL or commercial licensing, OCR engines are optional installations, and the exact-version pins can conflict with an existing PyMuPDF stack.

Use it if

  • Your PDF pipeline needs reading-order reconstruction, headings, tables, images, and optional OCR in local Python code.
  • Downstream indexing needs one record per source page with document metadata and character ranges for layout boxes.
  • You need bounding boxes and layout classes through JSON rather than only a flattened text string.
  • Your organization can meet the GNU AGPL 3.0 terms or has arranged an Artifex commercial license for the deployed stack.
Skip it if

Setup reality

We installed pymupdf4llm 1.28.2 in a fresh Python 3.12 Bookworm container. The install succeeded in 1.7 seconds, left 12 packages, and used 243 MB. It declares 4 direct dependencies and requires Python 3.10 or newer. import pymupdf4llm worked in 1.84 seconds, and pip-audit found 0 known vulnerabilities. The package is pure Python and has no py.typed marker. Its license is GNU AGPL 3.0 or an Artifex commercial license.

Version pairing is strict. PyPI requires exact 1.28.2 releases of both PyMuPDF and pymupdf-layout, and the import checks the PyMuPDF version before exposing the API. Importing also activates Layout for the process. Calling pymupdf4llm.use_layout(False) switches that global state to the legacy extractor, where custom IdentifyHeaders becomes available. Layout-only JSON and plain-text behavior should not be assumed after that switch.

OCR needs software beyond the 4 direct dependencies. The package can select Tesseract language data or RapidOCR when available. With no usable engine, automatic OCR is disabled with a warning; forcing OCR raises an exception. Set ocr_language for the installed language packs and pass ocr_dpi explicitly when output cost matters. Image-only pages can return empty text with use_ocr=False, which is useful when a caller would rather reject a scan than accept recognition errors.

Page numbers in pages are zero-based, and to_json() returns a JSON string that callers must decode. Writing images needs a writable directory; write_images=True and embed_images=True are mutually exclusive. The batch CLI can start multiple worker processes, so choose --workers after measuring the 243 MB baseline against representative documents. Word, Excel, PowerPoint, and HWP/HWPX handling requires the separate PyMuPDF Pro package, and full Office support requires a commercial key.

Patterns

Convert a document to Markdown convert-to-markdown

from pathlib import Path
import pymupdf4llm

markdown = pymupdf4llm.to_markdown("report.pdf")
Path("report.md").write_text(markdown, encoding="utf-8")

Version 1.28.2 activates Layout during import. Treat extracted Markdown as untrusted document data before rendering it as HTML.

Read a selected set of pages extract-selected-pages

import pymupdf4llm

markdown = pymupdf4llm.to_markdown(
    "report.pdf",
    pages=[0, 1, 5],
)

The `pages` list uses zero-based indexes. Keep the source page index with downstream chunks when citations must point back to the PDF.

Return one record for each page create-page-chunks

import pymupdf4llm

chunks = pymupdf4llm.to_markdown(
    "report.pdf",
    page_chunks=True,
)

for chunk in chunks:
    page_number = chunk["metadata"]["page_number"]
    index_page(page_number, chunk["text"], chunk["page_boxes"])

Page chunks follow physical pages rather than topics or token limits. Each `page_boxes` record maps a layout class and character slice back into that page's text.

Decode layout JSON extract-layout-json

import json
import pymupdf4llm

raw = pymupdf4llm.to_json("report.pdf", pages=[0, 1])
data = json.loads(raw)

`to_json()` returns a string in Layout mode. Decode it before indexing fields, and do not expect this output method after globally disabling Layout.

Format tables in plain-text output extract-plain-text

import pymupdf4llm

text = pymupdf4llm.to_text(
    "report.pdf",
    table_format="grid",
    table_max_width=100,
    table_min_col_width=10,
)

`to_text()` is part of the Layout path, and table formatting follows tabulate formats. Visual alignment still depends on the inferred table cells.

Write extracted pictures beside the text save-images

from pathlib import Path
import pymupdf4llm

image_dir = Path("report-images")
image_dir.mkdir(parents=True, exist_ok=True)
markdown = pymupdf4llm.to_markdown(
    "report.pdf",
    write_images=True,
    image_path=str(image_dir),
    image_format="png",
    dpi=150,
)

The destination must be writable, and generated files need their own retention policy. `write_images=True` cannot be combined with `embed_images=True`.

Place image data inside Markdown embed-images

import pymupdf4llm

markdown = pymupdf4llm.to_markdown(
    "report.pdf",
    embed_images=True,
    dpi=120,
)

Embedded pictures avoid sidecar files but enlarge the returned Markdown with base64 data. The Layout wrapper rejects simultaneous image writing and embedding.

Set language and resolution for selective OCR configure-selective-ocr

import pymupdf4llm

markdown = pymupdf4llm.to_markdown(
    "mixed-scan.pdf",
    use_ocr=True,
    force_ocr=False,
    ocr_language="eng+fra",
    ocr_dpi=200,
)

Tesseract language data or a supported RapidOCR installation must already exist. Passing `ocr_dpi` avoids relying on the README and Layout source defaults, which disagree.

Reject OCR work for digital-only input disable-ocr

import pymupdf4llm

markdown = pymupdf4llm.to_markdown(
    "digital.pdf",
    use_ocr=False,
)

Image-only pages can yield empty text with OCR disabled. Use this setting when recognition latency or uncertain text is worse than rejecting a scan.

Emit reconstructed tables as HTML render-html-tables

import pymupdf4llm

markdown = pymupdf4llm.to_markdown(
    "tables.pdf",
    table_output="html",
    edge_threshold=0.75,
)

Only table regions change to HTML; Layout still controls surrounding reading order and OCR. Sanitize generated HTML before placing it in a web page.

Read names and values from a PDF form extract-form-values

import pymupdf4llm

fields = pymupdf4llm.get_key_values("application.pdf", xrefs=True)
for name, value in fields.items():
    print(name, value)

A PDF without form fields returns an empty dictionary. With `xrefs=True`, values include PDF object references that PyMuPDF can use to load widgets.

Convert a directory with bounded workers batch-convert-directory

pymupdf4llm documents/ --out extracted/ --backend md --pattern '*.pdf' --workers 2 --ocr-lang eng

The CLI starts worker processes and writes outputs under the requested directory. Pick the worker count from measured memory use on your documents rather than CPU count alone.

Alternatives

PackageRegistryPick it when
pypdfPyPIUse it for PDF text, metadata, forms, merging, and page manipulation when layout inference and OCR orchestration are unnecessary.
doclingPyPIUse it when several document formats and a structured document model matter more than a compact PDF-first API.
unstructuredPyPIUse it for file-type partitioning into normalized elements and integrations across a wider ingestion system.
marker-pdfPyPICompare it on equation-heavy or layout-heavy PDFs when a larger model-based conversion stack is acceptable.

More data guides

numpy · fsspec · pandas · sqlalchemy · pyarrow · lxml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.