← All articles

Convert PDF to Markdown in Python: 4 Libraries + API Compared

Published 2026-07-09

The short answer: for clean digital PDFs, pymupdf4llm gets you to Markdown in four lines of Python. For scanned pages, complex tables, or LaTeX math, local libraries plateau fast — that's where a VLM-based parsing API earns its keep. Here's working code for every option, with honest failure modes.

Option 1: pymupdf4llm (best local default)

bashClick to Copy
pip install pymupdf4llm
pythonClick to Copy
import pymupdf4llm

md = pymupdf4llm.to_markdown("paper.pdf")
with open("paper.md", "w", encoding="utf-8") as f:
    f.write(md)

Built on PyMuPDF, designed specifically for LLM ingestion: it detects headings by font size, renders tables as pipe tables, and can emit page chunks for RAG (page_chunks=True).

Where it breaks: scanned PDFs (no OCR), math (formulas come out as garbled Unicode), and merged-cell or cross-page tables.

Option 2: MarkItDown (Microsoft)

bashClick to Copy
pip install markitdown
pythonClick to Copy
from markitdown import MarkItDown

md = MarkItDown()
result = md.convert("paper.pdf")
print(result.text_content)

Microsoft's Swiss-army converter (PDF, Office, images → Markdown). Convenient when PDFs are one of many input formats in your pipeline.

Where it breaks: its PDF path is text-extraction based — same weaknesses as above, with less layout awareness than pymupdf4llm.

Option 3: Marker (best open-source quality)

bashClick to Copy
pip install marker-pdf
marker_single paper.pdf --output_dir out/

Marker runs a pipeline of ML models (layout detection, OCR via Surya, equation handling) and produces notably better structure than pure-text extractors, including decent math support.

Where it breaks: heavy dependencies and GPU appetite — practical for batch jobs on your own hardware, annoying inside a lightweight service. Tables with merged cells still fail regularly.

Option 4: pdfplumber (when you need coordinates, not Markdown)

pythonClick to Copy
import pdfplumber

with pdfplumber.open("report.pdf") as pdf:
    for page in pdf.pages:
        print(page.extract_text())
        for table in page.extract_tables():
            print(table)

Not a Markdown converter — a precision instrument for pulling specific tables and text regions when you know the document's geometry. Great for invoices with fixed layouts; wrong tool for general conversion.

Option 5: VLM parsing API (when quality is the requirement)

Everything above reads the PDF's text layer. A Visual Language Model reads the page image — which is why it survives scans, multi-column reading order, merged cells, and math. KolmoPDF's PDF parsing API wraps that in one call:

pythonClick to Copy
import requests

resp = requests.post(
    "https://www.kolmopdf.com/api/pdf-to-markdown-proxy/parse",
    headers={"Authorization": "Bearer sk-xxx"},  # get a key at /api-keys
    files={"file": open("paper.pdf", "rb")},
)
markdown = resp.json()

Output is GitHub-Flavored Markdown with LaTeX math in $/$$ delimiters, pipe tables, and fenced code blocks. Pricing is per page (2 credits/page) with free signup credits — try it in the browser first with the PDF to Markdown converter.

Head-to-head: what actually fails where

Inputpymupdf4llmMarkItDownMarkerVLM API
Clean single-column text
Two-column paper⚠️ order issues⚠️
Tables (simple)⚠️
Tables (merged cells / cross-page)⚠️
LaTeX math⚠️
Scanned PDF✅ (slow)
Runs fully offline

Recommendation by use case

  • RAG over clean digital PDFs: pymupdf4llm, no contest — free, fast, local.
  • Mixed-format ingestion (Office + PDF + images): MarkItDown for uniformity.
  • Batch conversion on your own GPU: Marker.
  • Papers, textbooks, scans, anything with math or serious tables: VLM API. The cost of bad parsing shows up later as bad retrieval — if the documents matter, parse them properly once.

A common production pattern: route by document type. Text-layer extraction for born-digital simple PDFs; VLM parsing for scans and technical documents. The four-line check: if pymupdf4llm's output looks scrambled, escalate that file to the API.

FAQ

What's the fastest way to convert PDF to Markdown in Python? pymupdf4llm.to_markdown("file.pdf") — one line after install. Speed isn't the bottleneck; quality on hard documents is.

How do I convert a scanned PDF to Markdown in Python? Local: Marker (bundles OCR). Hosted: a VLM API that treats every page as an image, so scans need no special handling.

Why does my extracted Markdown have formulas like "x2+y2=r2"? The PDF text layer stores rendered glyphs, not LaTeX source. Only vision-based parsing can reconstruct $x^2 + y^2 = r^2$.

Which output is best for LLM / RAG pipelines? Markdown with real heading hierarchy — headings become chunk boundaries. That's the argument for parsers that get structure right, whichever one you pick.