Why PDF OCR Behaves Differently on Every Page
Within a single PDF, some pages produce extracted text instantly while others make you wait. If you've ever thought "why is this OCR tool so inconsistent?", that's not a bug — it's the design. A PDF document can be built differently page by page, and a good OCR tool detects that difference at the page level, spending the expensive computation only on the pages that need it. This article looks at exactly what criterion that decision uses, and at what point it's made, at the code level.
1. PDFs are often "digital cover, scanned body"
Contracts, official filings, and academic papers very frequently pair a word-processed cover page and signature block with a body that came in from a fax or scanner. If a tool looks at just the first page of a file like this and decides "this PDF is a text PDF" or "this PDF is a scan" for the whole document at once, you get errors: it needlessly OCRs the entire file even though text is already present, or it "extracts text" from a scanned body and returns an empty string. That's why the PDF OCR text extractor is built to make its decision per page, not per document.
2. The criterion: a threshold of "more than 5 text items"
PDF.js, the library that reads PDFs in the browser, returns an array of embedded text fragments (character- and word-level items) when you call getTextContent() on a page object. A normal PDF with a text layer produces dozens of items from even a single sentence, but a pure scanned-image PDF has no text layer at all, so this array comes back empty or with just a tiny number of fragments (a watermark, a page number, some incidentally embedded text). The tool judges a page to "have a text layer" based on whether the length of this array is greater than 5.
const tc = await pg.getTextContent(); if (tc.items.length > 5). If true, it joins the text immediately with tc.items.map(item => item.str).join(' '); if false, it renders that page alone to a canvas at 2x scale and hands it to Tesseract.js for OCR. This test-and-branch repeats independently for every page.
3. Why "5" — what the threshold does
Set the threshold to 0 (treat a page as a text PDF if it has even one text item) and an image-only page can be misjudged as "has text" because of a page-number stamp inserted by the scanner or one or two fragments of a hidden text layer that OCR software automatically laid down. The margin of 5 is a safety device that filters out this kind of noise text and only flags pages that contain real paragraphs and sentences as "has a text layer." Because the value is fixed, though, a cover page holding just one short title line may not clear 5 items and can get routed to OCR — a natural limitation that falls out of this structure.
4. Mixed-document processing example
Suppose a 10-page document where page 1 is a word-processed cover, pages 2–8 are a scanned body, and pages 9–10 are a digitally authored appendix. The processing flow looks like this:
| Page | getTextContent item count | Verdict | Processing |
|---|---|---|---|
| 1 (cover) | 42 | Has text | Immediate text extraction |
| 2–8 (scanned body) | 0–2 | No text | 2x render + Tesseract OCR |
| 9–10 (appendix) | 30+ | Has text | Immediate text extraction |
Here actual OCR computation happens only on the 7 pages 2–8; the other 3 are processed instantly. That's why processing time isn't proportional to the total page count but only to the "number of scanned pages."
5. What to remember as a user
- Uneven processing speed is normal: text-page stretches fly by, and the progress bar only crawls through the scanned section.
- You can save time with a page range: if you know where the scanned pages are, narrow the range to cut out the unnecessary full walk.
- To check the page count and structure first, use the PDF page counter to get the total, then set your OCR range.
- If you're sure a text layer already exists, using a PDF to text extractor directly instead of OCR is faster.
Frequently Asked Questions
Q. What happens on a page that mixes text and images?
A. If that page's getTextContent() returns more than 5 items, it's treated as having a text layer and extracted directly. In that case, characters that live inside an image on the page (a caption baked into a picture, for example) are not sent through OCR and may not be extracted.
Q. Is there a way to know in advance whether the whole document is a scan?
A. There's no dedicated check, but if you open the file in a PDF viewer and try to drag-select text, you can get a rough idea. If nothing selects at all, it's very likely a scan.
Q. Can the user change the 5-item threshold?
A. It's currently a fixed value with no UI option to adjust it. Just be aware that a cover page with very little text can get routed to OCR.
Q. How do I make processing faster?
A. Narrow the page range to the scanned section so the tool doesn't waste time walking through text pages, and reduce the number of pages that actually need OCR — that's the most effective lever.