I had a folder full of scanned PDFs - old contracts, receipts, a couple of books - and none of them were searchable. No Ctrl-F, no copy-paste, just pictures of text. I wanted to fix that. I did not want to upload any of it to a website, and I really did not want to spend an evening installing a toolchain to do it.
That turns out to be a surprisingly awkward corner.
The two usual answers, and what each one costs
OCRmyPDF is the tool everyone points you to, and deservedly - it's excellent, mature, does PDF/A, handles dozens of languages. But "just install it" means Python plus Tesseract plus Ghostscript plus unpaper plus pikepdf. On Windows especially that's a bad afternoon. And Ghostscript is AGPL - a copyleft dependency I'd rather not build a product on top of. Great tool; the install is the tax.
Online OCR sites are the easy path - until you look at what you're uploading. A passport. A signed contract. A medical scan. A tax form. "Drag your sensitive document onto our server" is exactly the thing you shouldn't do with the documents that most need OCR. Ads, limits, watermarks are the least of it.
The third option most people pick is nothing - they just live with PDFs they can't search.
None of these answered the thing I actually wanted: make this scan searchable, on my machine, with one command.
So I built it. It's called DeepOCR.
What it does
$ deepocr scan.pdf -o scan.ocr.pdf
scan.pdf 1 of 1 page(s) 9 words → scan.ocr.pdf
Enter fullscreen mode Exit fullscreen mode
It takes a scanned PDF (or an image), recognizes the text, and writes a new PDF where the original page image is untouched and an invisible, selectable text layer sits on top, positioned word by word. Open it in any viewer and Ctrl-F just works. The original file is never modified - the result is a separate .ocr.pdf, the same way a good tool should never overwrite your input.
It's a single static Rust binary. No Python, no Tesseract, no Ghostscript. The OCR engine is ocrs - pure Rust - and the recognition model ships inside the release binary, so it runs completely offline. Nothing touches the network, nothing leaves the machine.
A few flags cover the real cases:
deepocr scan.pdf --sidecar # also drop the recognized text as a .txt
deepocr book.pdf --deskew --rotate auto # straighten and orient before OCR
deepocr ./scans --recursive -o out/ # a whole folder, tree mirrored
deepocr contract.pdf --optimize # recompress the page images in the output
Enter fullscreen mode Exit fullscreen mode
Batch skips pages that already have a text layer instead of double-OCR'ing them:
scans/a.pdf → out/a.ocr.pdf (12 pages)
scans/c.pdf ↷ already has text (skipped; use --force)
✓ 2 processed, 1 skipped
Enter fullscreen mode Exit fullscreen mode
The privacy part, said plainly
This is the reason I care about it being local. The documents that most need OCR are the ones you least want to upload: IDs, contracts, financial records, anything medical. DeepOCR never sends them anywhere - the model is on your disk, the work happens in-process, and there's no account, no queue, no "we don't store your files, promise." Because the model is embedded, it works air-gapped, on a machine with the network cable pulled.
Honest about the edges
I'd rather undersell than oversell, so: v0.1 is Latin script only (that's the current limit of the ocrs model), and it produces a normal searchable PDF, not strict archival PDF/A. Other scripts (CJK, more languages via other backends) and PDF/A are on the roadmap behind a backend abstraction that's already in place - but they are not in v0.1, and I'd rather tell you that up front than have you find out on a Cyrillic scan.
Where it fits: the DeepLab loop
DeepOCR is part of a small set of local-first, dependency-light tools I'm building under DeepLab, and it closes a nice loop with its sibling DeepDoc (any document → clean Markdown for RAG). DeepDoc handles born-digital documents - real embedded text - and honestly refuses a scan instead of inventing content. DeepOCR is what turns that scan into something born-digital:
deepocr scan.pdf -o scan.ocr.pdf # add the text layer
deepdoc scan.ocr.pdf # now it extracts like any other document
# ### HELLO WORLD
# make scans searchable
# DeepOCR reads Latin text
Enter fullscreen mode Exit fullscreen mode
Same OCR core under both, so an ingestion pipeline can route a text-layerless scan through DeepOCR and back into DeepDoc without a cloud step anywhere in the chain.
Try it
brew install deeplabua/tap/deepocr
# or
cargo install deepocr
Enter fullscreen mode Exit fullscreen mode
It's open source (MIT / Apache), pure Rust, and the whole dependency graph is permissive - no AGPL, no C -sys crates. Repo: https://github.com/deeplabua/deepocr · landing page with all the install options: https://deeplab.tools/products/deepocr/
If you've been living with unsearchable scans, or fighting the OCRmyPDF install, I'd love for you to try it and tell me where it falls short - especially which language or script you'd want next.
Part of DeepLab - small, local-first, dependency-light Rust tools. See also DeepDoc (documents → Markdown) and DeepShrink (fit any video under a size limit).
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.