MarkItDown OCR, tested: scanned PDFs need the plugin and a model
1,952
of 1,955 words, plugin and glm-ocr
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
| 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
| 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
| 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
| 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.
Two ways to skip the work
Run it yourself. Our Apify Actor turns scanned PDFs into Markdown, tables included.
Or send us the scan. Tack, our AI, does the job for $29, up to 50 pages. First 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.