pymupdf4llm
PyMuPDF4LLM turns PDFs and other MuPDF-readable documents into Markdown, plain text, or layout-rich JSON for search and retrieval pipelines. Version 1.28.2 automatically activates the separately packaged PyMuPDF Layout model to infer reading order, headings, lists, tables, pictures, and page regions, then selectively calls an installed OCR engine for pages or spans with unusable text. It can also return per-page chunks, save or embed images, extract PDF form values, and feed LlamaIndex.
PyMuPDF4LLM is a capable local extractor, but it is neither lightweight nor license-neutral after the automatic Layout dependency. Install it when its document quality wins on your own corpus and both licensing layers are acceptable; otherwise start with pypdf or compare Docling and Unstructured.
Use it if
- You need local PDF-to-Markdown extraction with multi-column reading order, headings, tables, images, and optional OCR
- Your retrieval pipeline benefits from per-page text plus source metadata and layout box character ranges
- You want JSON coordinates and layout classes for a custom document-processing pipeline
- You can accept the AGPL terms or purchase an Artifex commercial license and can also accept the separate PyMuPDF Layout licensing
- Your application is proprietary and you have not cleared licensing: PyMuPDF4LLM and PyMuPDF are offered under AGPL v3 or a commercial Artifex license
- You require an entirely open-source dependency chain: the changelog states PyMuPDF Layout is not open source and has its own license, and current PyPI metadata installs it automatically
- You already depend on a different PyMuPDF or pymupdf-layout version: 1.28.2 pins both packages to exactly 1.28.2 and its import code raises ImportError when the PyMuPDF version differs
- You need reliable semantic chunks rather than pages: page_chunks=True returns one record per page with layout metadata, not topic-aware or token-budgeted chunks
- You need deterministic OCR and table reconstruction without document-specific evaluation: OCR is selected by heuristics and the changelog records repeated fixes for missing, duplicated, misordered, and malformed content across unusual PDFs
Setup reality
pip install pymupdf4llm on Python 3.10 or newer now installs exact versions of pymupdf and pymupdf_layout plus tabulate and psutil. This is not a small pure-Python helper in practical terms: PyMuPDF wraps the native MuPDF engine, Layout uses its own model and dependencies, and the project changelog calls out packages such as onnxruntime, numpy, and sympy in that path. Check the separate Layout license as well as PyMuPDF4LLM's AGPL-or-commercial terms before deployment. Importing pymupdf4llm activates Layout globally and verifies that PyMuPDF's version exactly matches; pymupdf4llm.use_layout(False) switches process-global behavior to the legacy extractor, where to_json and to_text are unavailable and custom IdentifyHeaders becomes available. OCR does not become self-contained just because the Python package installed. Automatic selection can use Tesseract language data or rapidocr_onnxruntime when present; without a usable engine, normal extraction disables OCR with a warning, while forced OCR raises. Install and test the right language packs, and budget CPU and memory for image rendering and inference. The README's OCR default examples and current source defaults do not fully agree, so pass ocr_dpi explicitly when it matters. Page indexes are zero-based. to_json returns a JSON string, not a decoded dict. write_images needs a writable directory and cannot be combined with embed_images. Office files require the separate PyMuPDF Pro package and a commercial key for full functionality. Finally, extraction quality is heuristic: keep a representative fixture set with scanned, multi-column, table-heavy, rotated, and malformed files, then diff outputs during every version upgrade.
Patterns
Convert a document to Markdownconvert-to-markdown
from pathlib import Path
import pymupdf4llm
markdown = pymupdf4llm.to_markdown('report.pdf')
Path('report.md').write_text(markdown, encoding='utf-8')Layout mode is activated automatically in 1.28.2. Treat generated Markdown as extracted data and inspect it before rendering it as trusted HTML.
Extract only selected pagesextract-selected-pages
import pymupdf4llm
markdown = pymupdf4llm.to_markdown(
'report.pdf',
pages=[0, 1, 5],
)Page indexes are zero-based. Invalid or reordered page lists should be covered by your own tests when source-page mapping matters.
Return one metadata record per pagecreate-page-chunks
chunks = pymupdf4llm.to_markdown(
'report.pdf',
page_chunks=True,
)
for chunk in chunks:
page = chunk['metadata']['page_number']
text = chunk['text']
boxes = chunk['page_boxes']
index_page(page, text, boxes)These are physical page chunks, not semantic chunks. Each page_boxes item includes a class, bounding box, and character slice into the chunk text.
Decode layout-rich JSON outputextract-layout-json
import json
import pymupdf4llm
json_text = pymupdf4llm.to_json('report.pdf', pages=[0, 1])
data = json.loads(json_text)to_json returns a JSON string and is available only in Layout mode. Calling pymupdf4llm.use_layout(False) makes this API raise NotImplementedError.
Produce plain text with bounded tablesextract-plain-text
text = pymupdf4llm.to_text(
'report.pdf',
table_format='grid',
table_max_width=100,
table_min_col_width=10,
)to_text is Layout-only. Table formatting uses tabulate conventions and does not guarantee the original document's visual alignment.
Write document images beside Markdownsave-extracted-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 process needs write permission and extracted files need lifecycle management. Do not combine write_images=True with embed_images=True.
Embed images as data in Markdownembed-images
markdown = pymupdf4llm.to_markdown(
'report.pdf',
embed_images=True,
dpi=120,
)Embedding avoids sidecar files but can make Markdown very large. It is mutually exclusive with write_images in the current layout path.
Configure language-aware automatic OCRconfigure-selective-ocr
markdown = pymupdf4llm.to_markdown(
'mixed-scan.pdf',
use_ocr=True,
force_ocr=False,
ocr_language='eng+fra',
ocr_dpi=200,
)A compatible OCR engine and language data must already be installed. Pass ocr_dpi explicitly because current source and README defaults are not fully aligned.
Keep extraction native and predictabledisable-ocr
markdown = pymupdf4llm.to_markdown(
'digital.pdf',
use_ocr=False,
)Image-only pages can return no text when OCR is disabled. This is useful when OCR latency or recognition errors are unacceptable.
Emit reconstructed HTML tablesrender-html-tables
markdown = pymupdf4llm.to_markdown(
'tables.pdf',
table_output='html',
edge_threshold=0.75,
)Only table output changes to HTML. Sanitize the result before inserting it into a web page if the source document is untrusted.
Read form field names and valuesextract-pdf-form-values
import pymupdf4llm
fields = pymupdf4llm.get_key_values('application.pdf', xrefs=True)
for name, value in fields.items():
print(name, value)Non-form PDFs return an empty dict. xrefs are low-level PDF object references useful for loading widgets through PyMuPDF.
Batch-convert a directory from the CLIconvert-directory-cli
pymupdf4llm documents/ --out extracted/ --backend md --pattern '*.pdf' --workers 2 --ocr-lang engThe CLI writes per-document output directories and logs. Choose workers from measured memory use because Layout and OCR state can make each worker expensive.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| docling | PyPI | Use it for a broader document-conversion pipeline with structured document models and multiple parsing backends |
| unstructured | PyPI | Use it when partitioning many file types and attaching normalized element metadata matters more than a compact PDF-focused API |
| pypdf | PyPI | Use it for lightweight PDF text and metadata access when you do not need layout inference, table reconstruction, or OCR orchestration |