Kraken OCR, tested on a real scanned PDF
1,875
of 1,955 scan words, read in order
Ten scanned pages in 380 seconds
380 s for 10 pages, Mac GPU
23 MB model download
- Run
pip install kraken. It installs torch. -
Run
kraken get 10.5281/zenodo.10592716. It downloads CATMuS-Print Large, the default model in the README. -
Save kraken.sh below next to book.pdf, then run
sh kraken.sh. It writes book.txt.
kraken.sh
# Kraken OCR on a PDF: book.txt plus page-NN.txt (brasspage.com/kraken-ocr/, Nov 12, 2026)
# Extra kraken options go first, for example: sh kraken.sh -d cpu --threads 2
set -e
pdftoppm -r 300 -png book.pdf page
kraken "$@" -I 'page-*.png' -o .txt segment -bl ocr -m catmus-print-fondue-large.mlmodel
# Join the pages, and the words the model split with a ¬ at the line end
for f in page-*.txt; do cat "$f"; echo; done | perl -CSD -0pe 's/\x{AC}\n//g' > book.txt
It needs Python 3.10 to 3.13, and pdftoppm from poppler. Kraken reads no PDF without its pdf extra, so the script turns each page into a picture first.
It marks split words with ¬
The default model writes ¬ where a word breaks at the line end:
different from those used by oystermen. Draw¬
Most of the neighboring fishermen had gath¬
fellow sat mending a net by the waterside, stop¬
1,864 words in order, raw pages
1,875 after kraken.sh joins them
It also puts a space before ? and :, the way French books do. That happened 11 times. The true text has none.
42 of the 64 missed places have a double quote mark. It also kept the running headers and page numbers.
Vision models read more, and faster
The same 10 scanned pages, scorer and Mac:
| Model | Words | Time |
|---|---|---|
| glm-ocr, Ollama | 1,953 | 104 s |
| Qwen3-VL 8B | 1,951 | 139 s |
| GOT-OCR 2.0 | 1,936 | 134 s |
| Kraken | 1,875 | 380 s |
| docTR | 1,869 | 13 s |
Kraken is built for old prints and non-Latin scripts, and you can train it on your own pages. On a modern English scan, it was the slowest here.
German: umlauts come out as two characters
137 of 206 umlauts right
1,776 of 1,887 words right
The model writes ü as u plus a separate dot mark. It looks right, but a search for "über" in book.txt found 0 matches.
This line makes each umlaut one character again. Then "über" found 12:
perl -CSD -MUnicode::Normalize -pe '$_ = NFC($_)' book.txt > book-nfc.txt
Some marks are still wrong: "spât" for "spät" and "Silbermïnze" for "Silbermünze".
No GPU: 321 seconds for 10 pages
On the CPU only, with 2 threads, the same script took 321 s, faster than the Mac GPU. The text was the same, byte for byte:
sh kraken.sh -d cpu --threads 2
Kraken reads every page as a picture. On a typed cover page, it read 11 of 13 words: "chopter" for "chapter" and "Noy" for "Nov".
Kraken and our Actor: 1 win, 5 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 | Kraken | Actor |
|---|---|---|
| Scan words in order | 1,875 | 1,874 |
| Typed cover words | 11 | 13 |
| Umlauts | 137 | 192 |
| Two columns, in order | 906 | 954 |
| Time, 11 pages | 385 s | 133 s |
| Time, 3 German pages | 207 s | 59 s |
The scan row is one word apart.
The Actor needs no GPU and no model download. It costs $0.006 a page.
Apache 2.0 code, CC BY 4.0 model
The Kraken license file is Apache 2.0, and PyPI says the same. I read it in full before the install.
The CATMuS-Print Large record on Zenodo says CC BY 4.0. Business use is fine if you credit its authors, Simon Gabay and Thibault Clérice.
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. One page has two columns, 972 words.
- Score: true words found in order in book.txt, with the scorer of the tessdata test. German: the scorer of Tesseract German.
- kraken 7.1.1 and torch 2.14.0, Python 3.12, on an Apple Silicon Mac, at the lowest priority. The default device picks the Mac GPU.
- Times count the whole script, with the page pictures and the model load. The model was already downloaded. One run of each setup.
- The glm-ocr, Qwen3-VL, GOT and docTR rows: the same files and scorer, on the same Mac, on November 12. They have their own pages.
- The Actor: two real runs earlier the same day, build 0.1.65, on the same files.
What I did not test
- Other models from the Zenodo list, and training your own.
- ALTO, hOCR and PageXML output.
- Right to left scripts, handwriting and manuscripts.
- eScriptorium, the web app built on Kraken.
- Windows, Linux and NVIDIA GPUs.
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
Does Kraken need a GPU?
No. On the CPU only, with 2 threads, it read 10 scanned pages in 321 s, faster than on the Mac GPU, with the same text.
Why does Kraken write ¬ at the end of a line?
The default model marks a word that breaks at the line end with ¬. Join the two lines and drop the sign, as kraken.sh does.
Is Kraken free for business use?
Yes. The code is Apache 2.0. The default model is CC BY 4.0, so you may use it if you credit its authors.
Related guides
- PaddleOCR on a Mac: CPU setup and results, tested
- docTR OCR on a scanned PDF: Mac setup and results, tested
- Fraktur OCR with Tesseract: 6 models tested on old German
- GOT-OCR 2.0 on a scanned PDF: Mac setup and results, tested
- EasyOCR vs Tesseract vs PaddleOCR vs RapidOCR, tested
- Ollama OCR on a scanned PDF: 2 models tested on a Mac