Blog/Guides

Make Scanned PDFs Searchable with OCR

Add a searchable text layer to scanned PDFs, verify the output, and compare clean and degraded scans using downloadable test files.

Guides··3 min read

A scanned PDF can display perfectly while containing no extractable text. OCR recognizes text in the page image and adds a text layer so readers can search and copy it. The output remains a PDF; it is not automatically a structured invoice record or an editable Word document.

This guide submits two synthetic scans to POST /v1/pdf/ocr and verifies the resulting text. One scan is clear. The other is downsampled, blurred, reduced in contrast, and rotated. Keeping both makes the limitations visible. Download the example projects, fixtures, and results.

Inspect the source before running OCR

Use a PDF reader's text-selection tool or Poppler's pdftotext:

pdftotext fixtures/scan-clean.pdf -

Our two input scans produced zero non-whitespace text characters. They were created from our own invoice fixture, so the ground truth is known. For a document that already has a usable text layer, start with text extraction rather than OCR.

Mixed documents need more care. A ten-page PDF might have selectable text on the cover and scanned pages in the appendix. Inspect per-page text rather than treating a nonempty whole-document string as evidence that every page is readable.

Submit an OCR job

The archive's api.py handles authenticated REST requests, stable idempotency keys, polling, and downloads. Authenticate using npx @relaypdf/cli setup --env .env, load the environment, and run this from the archive root:

import base64
from pathlib import Path
from api import submit, wait, download

job = submit("/v1/pdf/ocr", {
    "file": base64.b64encode(Path("fixtures/scan-clean.pdf").read_bytes()).decode(),
    "options": {"language": "eng", "deskew": True}
})
completed = wait(job["id"])
download(completed, "work/searchable.pdf")

English is the default installed OCR language. Do not assume every Tesseract language pack is available in a deployment. Check the OCR reference before selecting another language.

The job result includes a temporary download URL. Copy the output to your own storage when you need it beyond the retention window. The example does this immediately. It sends no API key to the file download URL.

Measured results on two scans

These measurements were taken on September 7, 2026 against RelayPDF's staging API. They are a reproducible example, not a production SLA or an accuracy benchmark across customer documents.

InputSource text charactersExact phrases recoveredJob and download wall time
Clean 150-DPI scan04 of 412.20 seconds
Degraded 75-DPI scan00 of 47.96 seconds

The four phrases were INV-1042, Example Workshop, 125.00, and Design review. A phrase passed only if it appeared exactly in pdftotext output. This small check says nothing about every character on the page, reading order, or recognition in other languages.

Download the clean source, clean searchable output, degraded source, and degraded searchable output. The measurement file records the checks.

The degraded job completed successfully but did not recover our target phrases. Successful processing and useful recognition are different acceptance criteria. A production pipeline should check the content it needs, not just the job status.

A separate production availability check on September 7 also completed the clean scan and recovered all four target phrases. Inspect the production output and additional production checks. The timing table above remains the original staging measurement.

Verify your own output

pdftotext work/searchable.pdf work/searchable.txt

Search for document-specific anchors: an expected invoice number, a known account identifier, or a heading. Inspect whether copying a paragraph produces sensible reading order. Also compare page count, rotation, and the visual appearance of the output.

Do not use generic checks such as “text length is greater than zero” as the only acceptance condition. A page number or scanner watermark can satisfy that condition while the actual document remains unreadable.

Improve inputs before increasing automation

Start with a better scan when possible. Cropped characters, motion blur, faint printing, and severe downsampling destroy information that an OCR engine cannot reliably reconstruct. Deskew can straighten a page; it cannot recreate missing strokes in a digit.

Use a review queue for low-quality results. Retain the source file and the OCR output as separate artifacts, and make it possible to retry with a better scan. Avoid claiming that OCR validates an invoice's financial accuracy or preserves an existing digital signature.

OCRmyPDF's cookbook explains searchable text layers and input-processing options. For the RelayPDF operation, see searchable PDF OCR. If your next step is extracting amounts and line items, continue with validated invoice extraction; that is a separate output contract.

Ready to generate?

One API for HTML, Markdown, URLs, and Office. REST, SDK, CLI, or MCP.