Qwen3-VL OCR, tested on a real scanned PDF
1,951
of 1,955 scan words, read in order
Use the instruct tag and temperature 0
139 s for 10 pages, Mac GPU
6.2 GB download, 8B instruct
-
Install Ollama and Poppler. Run
ollama pull qwen3-vl:8b-instruct. -
Save the Modelfile below, then run
ollama create qwen3-vl-ocr -f Modelfile. -
Run
sh qwen.sh qwen3-vl-ocrnext to book.pdf. It writes book.md.
The Modelfile and qwen.sh
FROM qwen3-vl:8b-instruct
PARAMETER temperature 0
pdftoppm -r 200 -png book.pdf page
for p in page-*.png; do
ollama run "$@" "Read all the text in the image. ./$p" > "${p%.png}.md" || exit 1
done
cat page-*.md > book.md
The prompt is the full-page OCR prompt of the Qwen3-VL cookbook.
The plain qwen3-vl tag thinks first
ollama pull qwen3-vl gets the 8B thinking model.
The tags :2b, :4b and :8b are
thinking models too.
| Flag | File | Time |
|---|---|---|
| None | 2,672 bytes | 28 s |
--think=false |
2,698 bytes | 28 s |
--hidethinking |
1,170 bytes | 32 s |
With no flag, the file starts with "Thinking..." and the model's
notes. --think=false did not stop it.
The instruct model wrote 1,156 clean bytes for page 1, and took about 14 s a page.
Temperature 0 gives the same text twice
The library sets temperature 1. I read the same 10 scan pages twice: once alone, and once in the 11-page file below.
3 of 10 pages the same, temperature 1
10 of 10 pages the same, temperature 0
That run also read 1 more word, and it took 26 s less.
glm-ocr still read 2 more words
The same 10 scanned pages, scorer and Mac GPU, all in Ollama:
| Model | Words | Time |
|---|---|---|
| glm-ocr | 1,953 | 104 s |
| Qwen3-VL 8B, temperature 0 | 1,951 | 139 s |
| Qwen3-VL 8B, temperature 1 | 1,950 | 165 s |
| Qwen3-VL 4B, temperature 1 | 1,936 | 136 s |
glm-ocr is an OCR model. Qwen3-VL is a general vision model, and it came close.
The 4B model is a 3.3 GB download. It often put a space between a quote mark and the next word.
The misses: 4 words, and every header
Qwen3-VL 8B wrote "yourn" as "you rn" and "old-fashioned" as "oldfashioned". Two double dashes became one dash.
It kept the running page header on all 10 pages. Delete those lines if you need clean book text.
At temperature 1, it also fixed a dialect word: "asho'" became "ashore".
Typed pages: 13 of 13 cover words
Qwen3-VL reads every page as a picture, typed pages too. It read the whole typed cover page, title line included.
In the 11-page file, the scan words stayed at 1,951, in 118 s.
German: two columns read in order
The script has no language option. I gave it 3 German pages. One is a magazine page with two columns.
| Model | Umlauts | Two columns |
|---|---|---|
| Qwen3-VL, temperature 0 | 192 | 965 |
| Qwen3-VL, temperature 1 | 195 | 961 |
| glm-ocr, Ollama | 193 | 955 |
At temperature 0, the 3 pages took 101 s.
dots.ocr is still the best here, with 204 umlauts.
Qwen3-VL and our Actor: 3 wins, 1 loss
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 | Qwen3-VL | Actor |
|---|---|---|
| Scan words in order | 1,951 | 1,874 |
| Typed cover words | 13 | 13 |
| Umlauts | 192 | 192 |
| Two columns, in order | 965 | 954 |
| Time, 11 pages | 118 s | 133 s |
| Time, 3 German pages | 101 s | 59 s |
Qwen3-VL read more scan words. The Actor was faster on German.
The Actor needs no GPU and no 6.2 GB download. It costs $0.006 a page.
The license allows business use
The Ollama download holds the plain Apache 2.0 license. It is the same text as the Qwen3-VL license on GitHub.
The model cards say apache-2.0, with no added use or region terms. I read all of it 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. qwen3-vl:8b-instruct and qwen3-vl:4b-instruct, Q4_K_M, from the Ollama library.
- Times count the script only, one model start included. The Ollama server ran before each script.
- One run each. My first temperature 0 run stopped on page 1 with no answer from the server. The same command on its own worked, and a second run worked.
- The glm-ocr rows: the same files and scorer, on the same Mac, on November 12. They have their 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
- The 2B, 30B and larger Qwen3-VL models, and Q8_0 or BF16.
- The cookbook's text spotting and key-value prompts.
- Qwen3-VL in Transformers, vLLM or llama.cpp.
- The Qwen-VL-OCR model of the Alibaba Cloud API.
- 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 Qwen3-VL do OCR?
Yes. In Ollama on a Mac GPU, the 8B instruct model read 10 scanned pages in 139 s.
Why does my Qwen3-VL OCR text start with Thinking...?
The plain qwen3-vl tags are the thinking models. Pull qwen3-vl:8b-instruct instead. The --think=false flag did not stop it.
Which Qwen3-VL size is best for OCR?
The 8B model read 14 more words on our scan, but its download is 2.9 GB bigger.
Related guides
- Florence-2 OCR on a scanned PDF: Mac setup, tested
- docTR OCR on a scanned PDF: Mac setup and results, tested
- GOT-OCR 2.0 on a scanned PDF: Mac setup and results, tested
- Ollama OCR on a scanned PDF: 2 models tested on a Mac
- GLM-OCR on a scanned PDF: Mac setup and results, tested
- LightOnOCR-3 4B on a scanned PDF: Mac setup and results
- dots.ocr on a scanned PDF: Mac setup and results, tested
- DeepSeek OCR on a scanned PDF: Mac setup and results, tested
- PDF to Markdown in Python: 5 libraries tested (2026)