Ollama OCR, tested on a real scanned PDF
1,953
of 1,955 scan words, read in order
Pull glm-ocr, then run it
The Ollama library has two OCR models: glm-ocr and deepseek-ocr. glm-ocr read the most words on our scan.
1,953 of 1,955 words, in order
104 s for 10 pages, Mac GPU
Install Ollama, and Poppler for pdftoppm. Run
ollama pull glm-ocr, a 2.7 GB download.
Then run sh glm.sh next to the PDF. You get one Markdown
file, book.md.
The full glm.sh script
pdftoppm -r 200 -png book.pdf page
for p in page-*.png; do
ollama run glm-ocr "Text Recognition: ./$p" > "${p%.png}.md" || exit 1
done
cat page-*.md > book.md
Each model needs its own prompt
glm-ocr takes the prompt on its library page:
Text Recognition: and then the image path.
deepseek-ocr wants the image path first, a line break, and then
Free OCR. The script puts a real line break there.
The full deepseek.sh script
pdftoppm -r 200 -png book.pdf page
for p in page-*.png; do
ollama run deepseek-ocr "./$p
Free OCR." > "${p%.png}.md" || exit 1
done
cat page-*.md > book.md
GLM-OCR did better in Ollama
The same 10 scanned pages, scorer and Mac GPU:
| Model | Words | Time |
|---|---|---|
| glm-ocr, Ollama | 1,953 | 104 s |
| deepseek-ocr, Ollama | 1,952 | 101 s |
| GLM-OCR, llama.cpp | 1,950 | 118 s |
| DeepSeek OCR 2, llama.cpp | 1,948 | 83 s |
Ollama's glm-ocr is the BF16 file. Our llama.cpp test of the same model used a smaller Q8_0 copy.
Ollama's deepseek-ocr is the first DeepSeek-OCR. Ollama has no version 2.
The misses: 2 words and 3 words
glm-ocr wrote "tommyrot" as "tomyrot" and dropped one closing quote. It kept no running page header.
deepseek-ocr fixed two dialect words: "belongin's" became "belonging's", and "photograft" became "photograph".
It also added a quote, and it kept 1 running page header.
Typed pages: 11 of 13 cover words
Both models read every page as a picture, typed pages too. glm-ocr skipped the title line, COVER SHEET, and read the other 11 words.
In the 11-page file, the scan words stayed at 1,953, in 114 s.
German: deepseek-ocr read more umlauts
Neither script has a language option. I gave both 3 German pages. One is a magazine page with two columns.
| Model | Umlauts | Two columns |
|---|---|---|
| deepseek-ocr | 201 | 951 |
| glm-ocr | 193 | 955 |
deepseek-ocr took 42 s for the 3 pages. glm-ocr took 61 s.
dots.ocr is still the best here, with 204 umlauts.
Ollama and our Actor: 4 wins, 2 losses
Our Actor, from a file URL, with no install:
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' > mixed.md
| Test | glm-ocr | Actor |
|---|---|---|
| Scan words in order | 1,953 | 1,874 |
| Typed cover words | 11 | 13 |
| Umlauts | 193 | 192 |
| Two columns, in order | 955 | 954 |
| Time, 11 pages | 114 s | 133 s |
| Time, 3 German pages | 61 s | 59 s |
glm-ocr read more scan words. The Actor read all 13 cover words.
The Actor needs no GPU and no 2.7 GB download. It costs $0.006 a page.
The license allows business use
Ollama is MIT. The deepseek-ocr download holds the plain MIT license.
The glm-ocr download has no license file, but the GLM-OCR model card says MIT. I read all three before the download.
How I tested it
- Scan: the 10 pages of OCR in n8n, proofread Wikisource book scans, 1,955 true words. The 11-page file adds the 13-word typed cover page of AnythingLLM OCR.
- German: the 3 pages of Paperless-ngx OCR, 1,887 words, 206 umlauts.
- Score: true words found in order in book.md, with the scorer of the tessdata test. German: the scorer of Tesseract German.
- Ollama 0.40.16 for macOS on an Apple Silicon Mac GPU, at the lowest priority. glm-ocr:latest and deepseek-ocr:latest, with the library settings (temperature 0).
- Times count the script only, one model start included. The Ollama server ran before each script.
- One run each. The 11-page file holds the same 10 scan pages, and their text was the same in both runs, page for page.
- The llama.cpp rows: the same files and scorer, on the same Mac, on November 12. Each has its own page.
- The scripts above are the files that ran. The Actor: two real runs earlier the same day, build 0.1.65, on the same files.
What I did not test
- glm-ocr:q8_0, and the table and figure prompts.
- deepseek-ocr grounding mode and its Markdown prompt.
- Library vision models that are not OCR models.
- The Ollama app, Windows, Linux and NVIDIA GPUs.
- Handwriting, tables, charts, math and forms.
Sources
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
Can Ollama do OCR?
Yes. Its library has two OCR models, glm-ocr and deepseek-ocr. On a Mac GPU, glm-ocr read 10 scanned pages in 104 s.
Which Ollama model is best for OCR?
On our English scan, glm-ocr, by 1 word, and it is 4 GB smaller. On German pages, deepseek-ocr read 8 more umlauts.
Can a business use Ollama OCR?
Yes. Ollama is MIT, and both models say MIT, with no added terms. Keep the license notice if you share them.
Related guides
- docTR OCR on a scanned PDF: Mac setup and results, tested
- Qwen3-VL OCR on a scanned PDF: tested in Ollama on a Mac
- GOT-OCR 2.0 on a scanned PDF: Mac setup and results, tested
- GLM-OCR on a scanned PDF: Mac setup and results, tested
- DeepSeek OCR on a scanned PDF: Mac setup and results, tested
- LightOnOCR-3 4B on a scanned PDF: Mac setup and results
- Open WebUI OCR for scanned PDFs, tested on 0.13.3
- AnythingLLM OCR for scanned PDFs, tested on 1.19.0
- PDF to Markdown in Python: 5 libraries tested (2026)
- MarkItDown OCR: scanned PDFs, the plugin and Ollama, tested