⟳ Automation

OCR for scanned documents: searchable PDFs with OCRmyPDF

How to make scanned PDFs searchable with OCRmyPDF and Tesseract: installation, language packs, deskewing, processing whole folders and checking the output.

An archive of scanned documents without OCR is an archive where nothing can be found. The PDF contains only photographs of the pages: Windows search can't see the text, the PDF reader's "find" function finds no words, copying a paragraph is impossible. Optical character recognition solves the problem by adding an invisible text layer beneath the image. The most practical free tool for doing this automatically is OCRmyPDF, which uses the Tesseract engine.

What OCRmyPDF does

OCRmyPDF takes a scanned PDF and returns a PDF that at first glance is identical to the original. The difference is that every recognised word is present as selectable text, positioned exactly over its image. The result reads as before, but it can be searched, copied and indexed. By default the output file is a PDF/A, the format designed for long-term preservation.

Installation

OCRmyPDF is a command-line program written in Python that relies on Tesseract and Ghostscript. On Linux you install it from the distribution's package manager, on macOS with Homebrew; on Windows the official documentation says to install Tesseract and Ghostscript separately and then OCRmyPDF via pip. It is essential to add the Tesseract language pack for the language of your documents: for Italian texts, without it recognition falls back to English and systematically gets accents and apostrophes wrong.

To check the available languages:

tesseract --list-langs

The list must include the code you need, such as ita or eng.

The first document

ocrmypdf -l ita scan.pdf scan_ocr.pdf

For mixed documents you can specify several languages joined with a plus sign, for example -l ita+eng: handy for contracts with clauses in English or technical manuals. Adding unnecessary languages, however, slows recognition down and makes it slightly worse.

Options that improve the result

Real scans are rarely perfect. A few options correct the most common defects:

Option Effect
--deskew Straightens slightly crooked scanned pages
--rotate-pages Rotates upside-down or sideways pages based on the recognised text
--clean Cleans noise from the image before OCR (requires the unpaper program)
--skip-text Skips pages that already contain text, instead of stopping with an error
--optimize 1 Optimises file size without visible loss of quality

--skip-text matters for automated jobs. As a precaution, OCRmyPDF refuses to process a PDF that already contains text, to avoid spoiling a digital document. With this option, pages that are already readable are left untouched and only the scanned ones are processed, a frequent situation in files that mix computer-generated documents with hand-signed sheets.

Processing whole folders

The real advantage comes when OCR becomes part of the workflow. A small Python script can process every PDF in a folder:

import subprocess
from pathlib import Path

source = Path("incoming_scans")
destination = Path("searchable_archive")
destination.mkdir(exist_ok=True)

for pdf in sorted(source.glob("*.pdf")):
    output = destination / pdf.name
    if output.exists():
        continue
    result = subprocess.run(
        ["ocrmypdf", "-l", "ita", "--deskew", "--rotate-pages",
         "--skip-text", str(pdf), str(output)],
        capture_output=True, text=True,
    )
    print(pdf.name, "OK" if result.returncode == 0 else result.stderr[-300:])

The output.exists() check lets you rerun the script every evening without reprocessing files already done. Scheduled with Windows Task Scheduler or cron, the script turns the scanner folder into a searchable archive with no intervention at all.

Scan quality matters more than software

No OCR engine can recover what the scan has lost. Some practical pointers:

  • 300 dpi is the resolution commonly recommended for text; much lower resolutions noticeably worsen recognition;
  • for text-only documents, greyscale scanning is often better than pure black and white, which can wipe out thin characters;
  • crumpled paper, overlapping stamps and handwriting remain difficult: Tesseract is designed for printed text;
  • complex tables are recognised word by word, but the column structure is not always preserved in the copied text.

Checking the result

In my work, after setting up an OCR workflow, I spot-check a few documents by searching for words I know are there: a surname, an invoice number, an amount. If the search finds them, the text is reliable for everyday use. Bear in mind, though, that OCR is not a certified transcription: for data on which important decisions depend, such as amounts to be entered in the accounts, the recognised value must always be compared with the image.

In short

  • OCR adds invisible text beneath the image and makes the PDF searchable.
  • OCRmyPDF uses Tesseract: install the right language pack and pass it with -l.
  • --deskew, --rotate-pages and --skip-text cover the most frequent problems.
  • A script that skips already-processed files automates whole folders.
  • Scan at 300 dpi and check important data against the image.
MM
Marco Marzaduri

Marco Marzaduri works in cybersecurity, digital forensics and web development. A computer science graduate, he combines rigorous technical analysis with attention to the people who use technology.

Read also