> Source: https://txtfetch.com/fixes/pdf-extracts-no-text > Plain-text twin — every page on txtfetch.com has one. https://txtfetch.com/text --- # Why did my PDF come back with no text at all? Almost always because there's no text layer to read. It's not a bug in whatever you're using to extract it. Here's how to tell for certain, and the one shape of PDF that fools a naive check. looks-like ``` >>> extracted_text '' ``` Your extraction call succeeds and returns nothing. Or, with txtfetch specifically, the call itself fails with a typed extraction\_failed error instead of a silent empty string. why-it-happens A PDF page is one of two fundamentally different things. It has real text, drawn with font and character-code operators. Or it's a picture of a page, with no text operators at all. pdftotext, pypdf, pdfminer.six, and Apache Tika all read the first case correctly. They all correctly return nothing for the second case. An empty result isn't a parsing failure. It's the honest answer to "is there text here?" That's the answer when the file is a scanned image, a fax, or a flatbed scan saved straight to PDF. You can run this check yourself: open the PDF and try to select a word with your cursor. If nothing highlights, there's no text layer on that page. No library finds one either, because none exists. The trickier case is a mixed PDF. Some pages are born-digital and some are scanned. A common example is a digital cover page or coversheet stapled ahead of a faxed body. The document isn't blank overall, so a check that only asks "did we get text back at all" passes. The scanned pages behind the cover contribute nothing, and nobody notices. confirm-it - Drop the file into the PDF text-layer checker. It reads each page individually, so it catches the mixed-document case a whole-document check misses. [Run the PDF text-layer check](https://txtfetch.com/tools/pdf-text-check) - Or just try selecting text in your PDF viewer. No highlight on a given page means no text layer on that page. fix-it-yourself OCR it yourself ocrmypdf adds an invisible, searchable text layer over the existing scanned page images. It's the fastest way to get real text out of a scan without discarding the original page images. bash ``` ocrmypdf input.pdf output.pdf pdftotext output.pdf output.txt ``` Confirm it's genuinely empty before reaching for OCR A quick byte-count sanity check on the plain-text extraction. It's cheaper than assuming and running OCR on a file that already had text. bash ``` pdftotext -layout input.pdf - | wc -c ``` what-txtfetch-does txtfetch runs the plain-text extraction pass first. It then automatically escalates the whole document to Tesseract OCR, but only when that first pass comes back completely blank. A fully scanned PDF gets OCR'd automatically, in the same request. metadata.ocr: true in the response confirms it happened. Know the mixed-document case before you rely on that. Tesseract escalation only fires when the entire first pass is blank. A digital cover page ahead of a scanned body means the document isn't blank overall. So the scanned pages behind it do not trigger OCR on their own. For those documents, pass ?quality=premium. Every page then routes through a vision-language model instead of the text-or-OCR fork, so a digital cover page and a scanned body both get read. Premium always routes async: you get a 202 response plus a job\_id to poll. It also safely falls back to the Tika baseline, flagged metadata.tier\_downgraded: true, if a cost or size guardrail trips. Run the PDF text-layer check above first on anything you suspect is mixed, since it reports per page rather than per document. There's a second safety net on the async path specifically. A request that did NOT pin ?quality= explicitly gets a premium retry automatically. This happens when the Tika baseline for a PDF either needed OCR (metadata.ocr: true) or came back extraction\_failed. So an unpinned async request gets a vision-model second read before it gives up. Pinning ?quality=standard opts out of that. A small synchronous upload doesn't take this path at all. If the document genuinely has no recoverable text after those attempts, txtfetch returns a typed extraction\_failed error, not a silent empty success. Failed extractions never count against your monthly quota. what-it-costs-you-downstream An empty or partially-empty extracted\_text produces a chunk with nothing to embed, silently shrinking that document's presence in the vector store. Or, worse, an ingestion job reports success while a whole document, or the scanned half of one, has quietly never entered the index at all. faq **Is an empty PDF extraction always a bug in the library I'm using?**: Almost never. It's the correct answer when the PDF has no text layer at all: a scan, a fax, or a photographed page saved as a PDF. Try selecting text in the PDF viewer itself. If nothing highlights, there's genuinely nothing there for any library to find. **Why did my mixed PDF come back with SOME text but I know pages are missing?**: Automatic Tesseract escalation, in txtfetch and in most extractors that offer it, only fires when the whole document's first-pass text comes back blank. A digital cover page ahead of a scanned body means the first pass isn't blank. So the scanned pages behind it never trigger OCR on their own. Pass ?quality=premium for these documents. It reads every page through a vision-language model instead of the text-or-OCR fork. Check with the PDF text-layer checker first if you're unsure, since it reports per page instead of per document. **Does txtfetch charge me for a PDF that comes back with no text?**: No. A whitespace-only result returns a typed extraction_failed error. This applies after the OCR retry and, on an unpinned async request, the automatic premium retry. Failed extractions don't count against your monthly document quota. related-reading - [PDF text-layer checker →](https://txtfetch.com/tools/pdf-text-check) - [Image OCR-readiness checker →](https://txtfetch.com/tools/image-ocr-check) - [Scanned PDF extraction →](https://txtfetch.com/extract/scanned-pdf) - [Docs: the premium quality tier for mixed PDFs →](https://txtfetch.com/docs#premium-quality) - [OCR scanned documents through one API call →](https://txtfetch.com/blog/ocr-scanned-documents-api) - [Error reference: extraction\_failed →](https://txtfetch.com/docs/errors) - [See the actual OCR output: a scanned invoice, raw vs. corrected →](https://txtfetch.com/diff#pdf-scanned-invoice-scan) PDF - [extraction returns nonsense glyphs from a PDF that clearly has real text →](https://txtfetch.com/fixes/garbled-pdf-text) - [All fixes →](https://txtfetch.com/fixes) ## Fix the text you already have. The free cleaner repairs this damage in your browser. Nothing leaves the page. [Clean up your text →](https://txtfetch.com/tools/clean-extracted-text) [Get an API key →](https://app.txtfetch.com/signup)