docling-serve OCR, tested on a scanned PDF
504
after 120 seconds, with the job still running
The default engine works
1,846 of 1,955 true words found
36.1 seconds for 10 pages
Send a scan to the convert endpoint:
curl -s -F files=@scan.pdf -F to_formats=md http://localhost:5001/v1/convert/file \
| jq -r .document.md_content > scan.md
With no engine named, docling-serve 1.38.2 picked RapidOCR. A typed cover page in front of the scan changed nothing. It kept all 13 cover words and the same scan words.
Sync calls stop at 120 seconds
A sync call waits 120 seconds, then answers HTTP 504:
Conversion is taking too long. The maximum wait time is configure as DOCLING_SERVE_MAX_SYNC_WAIT=120.
EasyOCR hit it on just 10 pages, and the default engine on 40. The server went on and finished that long job, but the 504 carries no task id. That text was lost.
Raise the limit when you start the server:
docker run -d --name docling -p 127.0.0.1:5001:5001 \
-e DOCLING_SERVE_MAX_SYNC_WAIT=600 \
quay.io/docling-project/docling-serve-cpu
Long scans: use the async endpoint
It returns a task id at once. Poll it, then get the result:
id=$(curl -s -F files=@long.pdf -F to_formats=md http://localhost:5001/v1/convert/file/async | jq -r .task_id)
while curl -s "http://localhost:5001/v1/status/poll/$id?wait=10" | jq -e '.task_status | test("pending|started")' > /dev/null; do :; done
curl -s http://localhost:5001/v1/result/$id | jq -r .document.md_content > long.md
On 40 pages it got 7,384 of 7,820 words in 136 seconds.
Tesseract needs ocr_lang=eng
With ocr_preset=tesseract and no language, the call
failed in 2 seconds with HTTP 404, Task result not found. The log
named the real cause:
TesseractOcrCli has no model for the OCR language 'spa'. No traineddata file 'spa' is installed. Supported: iso:en.
The image holds English data only. The API docs show tags like
en, and that failed the same way. The three-letter code
worked and found the most words:
curl -s -F files=@scan.pdf -F to_formats=md -F ocr_preset=tesseract -F ocr_lang=eng \
http://localhost:5001/v1/convert/file | jq -r .document.md_content > scan.md
Six setups, one scan
| Setup | Words found | Seconds |
|---|---|---|
| Default (RapidOCR) | 1,846 | 36.1 |
| Tesseract, ocr_lang=eng | 1,875 | 36.1 |
| Tesseract, no ocr_lang | 0 (404) | 2.0 |
| EasyOCR | 0 (504) | 120.2 |
| EasyOCR, wait raised | 1,427 | 174.2 |
| Our OCR Actor | 1,874 | 155.0 |
docling-serve ran in Docker on a Mac, limited to 2 CPUs. The Actor's time includes its start in the cloud.
No server? Use the Actor
The image takes 7.2 GB on disk. Our OCR Actor runs in the cloud instead. It takes a PDF URL and returns Markdown:
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/docling-serve-scan-10-pages.pdf"]}' \
| jq -r '.[].markdown' > actor.md
It found 1,874 words, one fewer than Tesseract in docling-serve. It costs $0.006 a page.
How I tested it
- Scan: the 10-page PDF of OCR in n8n, the first 10 of 55 proofread Wikisource book scans, with no text layer. 1,955 true words.
- Typed page: a 13-word cover sheet, put in front of the scan. Long scan: the same 10 pages 4 times.
- Score: true words found in order, with the scorer of the tessdata test.
- quay.io/docling-project/docling-serve-cpu:latest on arm64: docling-serve 1.38.2, Docling 2.142.1, Tesseract 4.1.1. A fresh container for each setup, with --cpus 2.
- The code blocks above are the files that ran. After start.sh I set the 2-CPU limit with docker update. The Actor: one real run.
What I did not test
- GPU images, other OCR languages, and the VLM pipeline.
- Tables, figures, handwriting, and faster or slower CPUs.
- A proxy in front of the server, and the RQ or Ray engines.
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
Which OCR engine does docling-serve use by default?
The preset auto. In the docling-serve-cpu image, version 1.38.2, it picked RapidOCR. It found 1,846 of 1,955 words on my 10-page scan.
How do I fix the docling-serve 504, Conversion is taking too long?
Sync calls wait 120 seconds. Start the server with DOCLING_SERVE_MAX_SYNC_WAIT=600, or send the file to /v1/convert/file/async and poll the task.
Why does docling-serve answer 404 with ocr_preset tesseract?
The OCR failed. The image has English Tesseract data only, and the default languages need more. Send ocr_lang=eng. The tag en failed too.