Five pages of a forty-page PDF come back empty
A mixed PDF passes every average-based check and still loses its scanned pages. Quality is checked page by page, and one bad page sends the whole file to OCR.
The document is forty pages, generated by somebody's system, and in the middle of it there are five pages that were printed, signed and scanned back in. Annexes, a countersigned page, a form somebody filled in by hand and photographed.
The file opens, the text comes out, the summary reads fine. Five pages are blank and nobody says so. Your agent answers questions about the contract without ever having seen the part that was signed.
This is the same failure as a fully scanned PDF, except worse, because the document does not look broken. A scan that returns nothing is obvious within seconds. A document that returns thirty-five pages out of forty looks like a document that worked.
Every extraction pipeline has a moment where it decides whether the text layer is good enough, and almost all of them decide it with an average: characters per page across the file, or total characters over page count. Forty dense digital pages plus five empty ones produce a very high average. The check passes, extraction is declared successful, and the five pages are simply absent from the output.
An average over parts always hides the worst part. It is not a tuning problem, it is the wrong shape of measurement: no threshold on a mean can tell forty-five good pages from forty good pages and five that are pictures. The signal you need is per page, and once you have thrown it away by averaging you cannot get it back downstream.
The other half is what to do about it. Sending only the five bad pages to an engine sounds thrifty and produces a document assembled from two different readings, with two different notions of layout and reading order, and no record of which page came from where.
Nothing special to ask for. The per-page check is in balanced, and the response says which engine did the work.
upload(filename="contract-with-annexes.pdf", content_type="application/pdf")
-> key, upload_url
curl -T contract-with-annexes.pdf "<upload_url>"
read(key="<key>")
-> handle, engine, used_fallback, cost_eur, structure
result(handle="<handle>", pages="18-22")
-> the scanned annexes, as text like every other pagebalanced tries local extraction first, which costs nothing, and checks the result page by page. If every page passes, the read is free. If a single page fails, the whole document goes to an engine and the whole document is charged: forty pages at 0.007 EUR each, about 0.28 EUR, for five pages you could not read.
That is deliberate, and it is the honest version of the trade. Charging you for five pages and delivering a document read two different ways would be cheaper on the invoice and worse to work with, and you would have no way to tell which pages were which.
exact costs 0.016 EUR per page and skips the free attempt entirely, which is what you want when you already know the file is mixed and would rather not pay for a local attempt that is going to be discarded.
Pages are counted from the file, so a forty-page PDF is forty pages, and reading the same file again returns the first result and charges nothing.
- The rule is all or nothing on purpose: there is no option to OCR only the pages that failed.
- Handwriting, stamps and signatures on those scanned annexes are not reliably read by any engine, ours included. What was signed comes back as an image nobody transcribed.
- Email files (EML, MSG) and ebooks (EPUB) are read by no engine. Extract the text or convert to PDF.
Without markup
This page in markdown: /problems/read-a-pdf-where-only-some-pages-are-scanned.md. All 20 of them in one file: /llms-full.txt.