MarkItDown vs Docling vs PyMuPDF4LLM: Which Is Best for PDF to Markdown?

The Short Answer
If you need a PDF parser for RAG today, start with PyMuPDF4LLM. It is the best default for most digital PDF-to-RAG workflows: lightweight, designed for fast PDF ingestion, and it emits LLM-shaped Markdown (plus JSON) with layout-aware reading order, table detection, and optional hybrid OCR. When document structure and complex layouts matter — multi-column pages, complex tables, formulas — Docling is the stronger choice, exporting structured JSON with coordinates and Markdown. When simplicity and mixed Office + PDF support matter, MarkItDown is the easiest universal converter. There is no universal winner, but there is a sensible default per document type.
Which One Should I Use?
| Your situation | Pick | Why |
|---|---|---|
| Normal digital PDFs, fast RAG ingestion | PyMuPDF4LLM | Lighter-weight, typically faster for native PDF extraction, no ML model downloads; page chunks with metadata suit RAG. |
| Complex tables, formulas, multi-column layouts, scanned PDFs | Docling | Document-understanding pipeline: layout analysis, reading order, table structure, coordinates, OCR with multiple backends. |
| Mixed Office (DOCX/XLSX/PPTX) + PDF, simplest universal converter | MarkItDown | One tool for many formats with plain LLM-friendly Markdown; optional LLM Vision OCR plugin for scanned content. |
| OCR-heavy or scanned PDFs | Docling OCR or PyMuPDF4LLM hybrid OCR | Compare both OCR paths on your files; MarkItDown’s optional OCR plugin is the fallback for mixed-format batches. |
The Problem
When I build RAG pipelines, knowledge bases, and agent workflows, the first step is almost always the same: turn PDFs into clean Markdown. But no single parser handles every document well. Marketing pages claim each tool is the best, and searching for “best PDF parser for RAG” or “PDF parser for LLM” returns conflicting advice.
The real question is not “which tool is best” but “which tool is best for this kind of document.” That is why I evaluated MarkItDown, Docling, and PyMuPDF4LLM across common document scenarios based on current capabilities, documentation, and hands-on observations — and why document parsing for RAG usually needs a routing strategy rather than a single tool.
The Three Tools
┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐│ MarkItDown │ │ Docling │ │ PyMuPDF4LLM ││ │ │ │ │ ││ Office + clean PDF │ │ Complex layout │ │ Fast PDF-to-LLM ││ → plain Markdown │ │ tables + OCR │ │ Markdown + images ││ │ │ → Markdown + JSON │ │ │└─────────────────────┘ └─────────────────────┘ └─────────────────────┘MarkItDown is Microsoft’s converter. It handles PDFs, Word, Excel, PowerPoint, HTML, images, and audio. The output is plain Markdown aimed directly at LLM prompts.
Docling is a document-understanding pipeline rather than a PDF-to-Markdown converter. It runs layout analysis, reading-order detection, table-structure recognition, and OCR, and it handles formulas, code, and images. The result is a structured document representation you can export as Markdown, JSON, or plain text — element types and coordinates included.
PyMuPDF4LLM is a PyMuPDF extension purpose-built for LLM ingestion. It turns a PDF into Markdown quickly, with optional image extraction and OCR, and no ML model downloads. Modern PyMuPDF4LLM is more than a lightweight text extractor — details in its section below.
Installation and Minimal Usage
Here are the install commands and the smallest working examples for each tool. I verified these against the official documentation; exact output still depends on your documents.
MarkItDown
pip install markitdown[all]Convert a file from the command line:
markitdown path-to-file.pdf -o document.mdOr use the Python API in a script:
from markitdown import MarkItDown
md = MarkItDown()result = md.convert("report.docx")print(result.text_content)Core MarkItDown converts native text and embedded text content — it does not OCR scanned pages. OCR ships in the optional markitdown-ocr plugin, which can use LLM Vision to read images inside PDFs as well as inside DOCX, PPTX, and XLSX files. So MarkItDown is weak by default on scanned PDFs, but the plugin turns it into a viable option for OCR-heavy, mixed-format batches.
Docling
pip install doclingThe full package pulls ML models for layout, table structure, and OCR on the first run. A slimmer install is available with pip install docling-slim[format-pdf,cli] if you only need PDF and the CLI.
Convert a file from the command line:
docling report.pdfThe Python API gives more control, including structured JSON export:
from docling.document_converter import DocumentConverter
converter = DocumentConverter()result = converter.convert("complex-table.pdf")print(result.document.export_to_markdown())
# Structured JSON with coordinates for downstream pipelinesdoc_dict = result.document.export_to_dict()Docling’s strongest differentiator is structure: it detects paragraphs, headings, tables, formulas, code blocks, and images on a page and reports their positions, and it supports multiple OCR backends (EasyOCR, Tesseract, and others) for scanned input. The visual below shows what that detection looks like on a real PDF page.

That coordinate data is what makes Docling a good fit for precise RAG chunking, because a chunk can carry its position and element type as metadata — especially when downstream RAG needs structural metadata rather than flat text. This is also where Docling stands out in the Docling vs PyMuPDF4LLM comparison: both produce Markdown, but Docling keeps the document model behind it.
PyMuPDF4LLM
pip install --upgrade pymupdf4llm[ocr,layout]Convert from the command line, with images written to disk:
pymupdf4llm document.pdf --out output/ --write-imagesOr use the Python API:
import pymupdf4llm
md = pymupdf4llm.to_markdown( "research-paper.pdf", write_images=True, image_path="./images")The returned string feeds directly into an LLM prompt, a chunker, or a vector store.
Modern PyMuPDF4LLM is more than a simple lightweight Markdown extractor:
- Layout-aware reading order and multi-column reconstruction via the layout extra.
- Table detection, so table cells survive as structure instead of raw text runs.
- Markdown, JSON, or plain-text output — in JSON mode you get page chunks with metadata, including bounding-box/layout information for downstream chunking.
- Hybrid/selective OCR for scanned or broken regions, rather than an all-or-nothing OCR pass over the whole page.
- Image extraction with
--write-images(CLI) orwrite_images=True(API).
Its core, open-source focus is PDF; Office support is available through PyMuPDF Pro rather than the free PyMuPDF4LLM path.
Comparing Them Across Common Document Scenarios
I evaluated the three tools across common document scenarios based on current capabilities, official documentation, and hands-on observations — not a formal benchmark. In the MarkItDown vs Docling vs PyMuPDF4LLM decision, real results differ by document, so treat these notes as a starting point for your own tests:

1. clean digital PDF2. multi-column layout3. simple table4. complex table5. equations/formulas6. embedded images and charts7. scanned PDF / OCR8. large PDFFor each tool I checked the same criteria: text extraction quality, reading order, heading preservation, tables, formulas, images, OCR, speed, setup complexity, output readability, RAG suitability, and agent workflow suitability.
The table below is a baseline from official docs and my hands-on notes, not a guarantee. Run the same files through your own pipeline and refine the notes with your numbers.
| Requirement | MarkItDown | Docling | PyMuPDF4LLM |
|---|---|---|---|
| Clean digital PDF | Straightforward, LLM-friendly text | Accurate text with layout-aware reading order | Strong default; LLM-shaped Markdown |
| Multi-column layout | Content order can drift | Layout analysis reconstructs reading order | Layout mode with reading-order detection |
| Complex tables | Basic, text-order dependent | Dedicated table-structure model | Table detection; structure from PDF internals |
| Equations/formulas | Limited | Formula support via layout + structure analysis | Limited to what the PDF exposes |
| Scanned PDF / OCR | Weak by default; optional LLM Vision OCR plugin (markitdown-ocr) | Multiple OCR backends | Hybrid/selective OCR for scanned or broken regions |
| Reading order | Depends on source order | Layout-model driven, multi-column aware | Layout-aware reading order, multi-column reconstruction |
| Image extraction | Basic handling | Detects images and exports with coordinates | --write-images / write_images=True |
| Structured JSON / bounding boxes | No | Yes — structured doc model with coordinates | Yes — JSON mode with page metadata and bounding boxes |
| Office documents | Native DOCX/XLSX/PPTX | DOCX/PPTX support | PDF only (Office via PyMuPDF Pro) |
| Speed | Lightweight, fast text conversion | Heavier; ML models add latency | Lightweight; typically fast for native PDF extraction |
| Dependencies/setup | pip install markitdown[all] | Heavier; downloads ML models on first run | pip install pymupdf4llm[ocr,layout]; no ML downloads |
| RAG chunking | Good text chunks, no structure metadata | Strong — element types + coordinates | Strong — page chunks with metadata for RAG |
| Best use case | Mixed Office + PDF, simplicity | Complex structure and OCR with metadata | Digital PDF → RAG ingestion default |
Choose MarkItDown if…
You need mixed Office + PDF ingestion and want the simplest universal converter. MarkItDown natively handles Word, Excel, and PowerPoint, has an easy setup, and emits plain Markdown shaped for LLM prompts. It is the right default when simplicity and one-tool coverage matter more than PDF-specific capabilities. For scanned files it is weak by default — the optional LLM Vision OCR plugin (markitdown-ocr) is the path to OCR, including OCR inside PDF, DOCX, PPTX, and XLSX.
Choose Docling if…
Complex document understanding is the job: multi-column layouts, complex tables, formulas, and scanned pages. Docling is a document-understanding pipeline, not just a converter — layout analysis, reading order, table structure, and coordinates are first-class, and OCR supports multiple backends. If downstream RAG needs structural metadata (element types, bounding boxes) rather than flat text, Docling’s structured JSON is a major reason to pick it.
Choose PyMuPDF4LLM if…
Your pipeline is PDF-only and you want the default parser for normal digital PDFs and fast RAG ingestion. It is lightweight, needs no ML model downloads, and is typically faster for native PDF extraction than ML-based pipelines. Modern PyMuPDF4LLM also handles layout-aware reading order, table detection, JSON output with bounding boxes, page chunks with metadata for RAG, and hybrid OCR for scanned or broken regions — so for OCR-heavy PDFs, compare its OCR path against Docling’s before routing elsewhere.
The Routing Strategy

For production ingestion, I do not pick one parser for everything. I route each document by type:
┌──────────────────────────────┐ │ Incoming document batch │ └──────────────┬───────────────┘ │ ┌──────────────▼───────────────┐ │ Office document? │ └──────────────┬───────────────┘ Yes │ No ┌──────────────▼───────────────┐ │ MarkItDown │ └──────────────────────────────┘ │ ┌──────────────▼───────────────┐ │ PDF: scanned or OCR-heavy? │ └──────────────┬───────────────┘ Yes │ No ┌──────────────▼───────────────┐ │ Docling OCR or │ │ PyMuPDF4LLM hybrid OCR │ └──────────────────────────────┘ │ ┌──────────────▼───────────────┐ │ Complex tables, formulas, │ │ or layout semantics? │ └──────────────┬───────────────┘ Yes │ No ┌──────────────▼───────────────┐ │ Docling │ └──────────────────────────────┘ │ ┌──────────────▼───────────────┐ │ Normal digital PDF → │ │ PyMuPDF4LLM │ └──────────────────────────────┘Keep MarkItDown as an alternative when simplicity and one-tool mixed-format ingestion matter more than PDF-specific capabilities — for a clean PDF it is a fine choice even though the flow above defaults to PyMuPDF4LLM.
The same idea as pseudo-code:
from pathlib import Path
def route_to_parser(file_path: Path, is_scanned: bool = False) -> str: ext = file_path.suffix.lower() if ext in {".docx", ".xlsx", ".pptx"}: return "markitdown" # Office documents -> MarkItDown if is_scanned: return "docling_ocr_or_pymupdf4llm_ocr" # scanned/OCR-heavy PDFs if needs_complex_structure(file_path): return "docling" # complex tables/formulas/layout -> Docling return "pymupdf4llm" # normal digital PDF -> PyMuPDF4LLMMy Recommended Document Parsing Stack
For RAG systems, knowledge bases, and agent workflows, this is the stack I would start with:
- Default parser for normal digital PDFs: PyMuPDF4LLM for fast RAG ingestion and LLM-shaped Markdown (or JSON metadata when you need page chunks with bounding boxes).
- Complex documents: Docling with table structure and OCR enabled, exporting both Markdown and structured JSON for chunking and metadata.
- Office files: MarkItDown, which natively handles Word, Excel, and PowerPoint.
- Scanned / OCR-heavy PDFs: compare Docling’s OCR (multiple backends) with PyMuPDF4LLM’s hybrid/selective OCR; for mixed-format OCR batches, MarkItDown’s optional LLM Vision OCR plugin is worth testing.
- Orchestration: a small router that classifies each file and dispatches to the right parser. Cache results and log per-document metrics (timing, token size, extraction quality) to catch regressions.
- RAG note: prefer structured exports (JSON with coordinates) over raw Markdown when chunking complex tables. Use Markdown for general text chunks. When the choice is PyMuPDF4LLM vs MarkItDown for clean PDFs, it comes down to whether Office support and one-tool simplicity beat PDF-specific output.
Summary
In this post, I evaluated MarkItDown, Docling, and PyMuPDF4LLM for PDF-to-Markdown work in LLM and RAG pipelines: PyMuPDF4LLM as the default for normal digital PDFs and fast RAG ingestion, Docling for complex structure and OCR with structural metadata, and MarkItDown for simplicity and mixed Office + PDF ingestion. No single parser wins every case — in production, route documents by type, cache results, and re-test on your own files before choosing a default parser.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 MarkItDown (Microsoft) on GitHub
- 👨💻 Docling on GitHub
- 👨💻 Docling Quickstart
- 👨💻 PyMuPDF4LLM on GitHub
- 👨💻 PyMuPDF4LLM Configuration Reference
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments