Tools,

MarkItDown OCR, tested: scanned PDFs need the plugin and a model

1,952

of 1,955 words, plugin and glm-ocr

Get the script

OCR in MarkItDown, in 4 lines

68 s for 10 pages, Mac GPU

2.7 GB model, one download

Install Ollama first. Then, in the folder with scan.pdf:

pip install "markitdown[pdf]==0.1.9" "markitdown-ocr[llm]==0.1.2"
ollama pull glm-ocr
python md.py scan.pdf glm-ocr > scan.md
grep -c "\[Image OCR\]" scan.md

md.py is the setup from the plugin's README, pointed at Ollama:

# md.py: MarkItDown with its OCR plugin and a local Ollama model.
# python md.py scan.pdf glm-ocr > scan.md
import os
import sys

from markitdown import MarkItDown
from openai import OpenAI

url = os.environ.get("OLLAMA_URL", "http://localhost:11434/v1")
client = OpenAI(base_url=url, api_key="ollama")
md = MarkItDown(enable_plugins=True, llm_client=client, llm_model=sys.argv[2])
print(md.convert(sys.argv[1]).markdown)

The grep counts OCR blocks. 10 pages should give 10.

"Dependencies for .pdf files have not been installed"

MarkItDown says this for any import error. On my Mac, uv picked an Intel Python, and the cryptography package failed to load. Check that this prints arm64:

python -c "import platform;print(platform.machine())"

The command line gives 0 words

10 scanned pages, 1,955 words
Command Words Exit code
markitdown scan.pdf 0 0
markitdown --use-plugins scan.pdf 0 0
The README command, with --llm-model Error 2

markitdown 0.1.9 has no option to name a model. The README command stops with "unrecognized arguments". With --use-plugins alone, I got 10 page headings and no text.

A typo also gives 0 words

md.py on the same scan
Mistake Words Exit code
Model name typo 0 0
Ollama not running 0 0

The plugin catches the error on each page and moves on. Nothing shows on screen. Run the grep after each file.

The errors it hid
Error code: 404 - model 'glm-ocr:latest-typo' not found
Connection error.

glm-ocr beat a general model

Same 10 pages, of 1,955 words
Model Words Time
glm-ocr, 2.7 GB 1,952 68 s
qwen3-vl 4B, 3.3 GB 1,917 109 s

Each page went to the model as one PNG, 1,920 pixels wide. A typed cover page kept all 13 of its words, with no model call.

Old OCR text comes out twice

4,107 words out, for 1,955

1,651 in order in the old copy

The plugin reads every picture, even on a page that has text. On the OCRmyPDF copy of the scan, each page came out twice: the model text, then the old text.

If a PDF already has text, leave the plugin off.

No model? Run OCRmyPDF first

Same 10 pages, of 1,955 words
Then Words Tables
markitdown 1,872 8 fake
markitdown --use-plugins 1,877 0
ocrmypdf -j 2 scan.pdf scan-ocr.pdf
markitdown --use-plugins scan-ocr.pdf > scan.md

On page 7, plain MarkItDown turned lines of text into tables full of | signs. --use-plugins swaps in the plugin's PDF reader, which keeps plain lines.

OCRmyPDF took 27 s with 2 jobs, then MarkItDown 2 s.

Need Markdown with no setup?

Our Actor takes PDF, JPG and PNG files and returns Markdown, with no install and no model. On the same 10 pages, inside a PDF, it found 1,874 words:

curl -s -X POST "https://api.apify.com/v2/acts/brasspage~pdf-ocr-to-markdown/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"documentUrls": ["https://api.apify.com/v2/key-value-stores/sTnmNrGoSsi7tLQvs/records/anythingllm-mixed-11-pages.pdf"]}' \
  | jq -r '.[].markdown' > book.md

It costs $0.006 a page.

How I tested it
  • Pages: the 10 scans of OCR in n8n, proofread Wikisource book pages, 1,955 true words. Each page is one 300 ppi JPEG.
  • markitdown 0.1.9 and markitdown-ocr 0.1.2, with uv pip in a fresh venv, Python 3.12 for Apple Silicon.
  • Ollama 0.40.16 from GitHub, SHA-256 checked, one request at a time, at lowest priority. One run each.
  • Score: true words found in order in the Markdown, with the scorer of the tessdata test.
  • Old OCR text: OCRmyPDF 17.13.0 with 2 jobs. The cover test used the same scan with a typed cover page.
  • The Actor: one real run, build 0.1.65, on November 12. Its file holds the same 10 pages plus a typed cover page.
What I did not test
  • Paid models such as GPT-4o, and Word, PowerPoint or Excel files.
  • Windows and Linux, and a Mac with no GPU.
  • Phone photos, handwriting, and languages other than English.
Sources

Two ways to skip the work

Run it yourself. Our Apify Actor turns scanned PDFs into Markdown, tables included.

Try the Actor

Or send us the scan. Tack, our AI, does the job for $29, up to 50 pages. First page free.

Get one page free

Questions people ask

Does MarkItDown do OCR?

Not by itself. On 10 scanned pages it returned 0 words. The markitdown-ocr plugin sends each page picture to a vision model. With glm-ocr in Ollama it found 1,952 of 1,955 words.

How do I use markitdown-ocr with Ollama?

Install markitdown[pdf] and markitdown-ocr[llm], and pull a vision model. In Python, give MarkItDown enable_plugins=True, an OpenAI client with base_url http://localhost:11434/v1, and llm_model.

Why does markitdown-ocr return no text?

In markitdown 0.1.9 the command line cannot name a model, so --use-plugins alone gives no text. In Python, a wrong model name or a stopped Ollama also gave 0 words, with exit code 0.