mac-ocr: macOS OCR CLI for Text and Searchable PDFs
mac-ocr is a macOS command-line tool that runs Apple's Vision framework locally to pull text out of images and PDFs, and to turn scanned documents into searchable PDFs. Reach for it if you want OCR that never leaves your Mac and you're comfortable working from a terminal or a small Node.js script. Skip it if you need Windows or Linux support, or a GUI app you can hand to a non-technical coworker.
What is mac-ocr?
mac-ocr is a native Swift binary that wraps Apple's VNRecognizeTextRequest API from the Vision framework to recognize text in images and PDFs, entirely on-device. It ships as an npm package with a prebuilt universal binary, so you install it like any other CLI tool with npm install -g mac-ocr, and it also exposes a typed Node.js API for scripting the same recognition and searchable-PDF logic.
Core Capabilities
- ✓Reads text from a single image or many images in one call (`mac-ocr photo.png`, `mac-ocr *.png`), with plain text as the default output.
- ✓Streams recognized text from a multi-page PDF page by page using `--format jsonl`, so a large document starts producing output before the whole file finishes.
- ✓Builds a searchable PDF from a scanned document or photo with the `searchable-pdf` subcommand, adding an invisible, selectable text layer instead of just printed text.
- ✓Runs an optional partitioned-OCR pass that recursively splits large, high-resolution pages into smaller regions when small text is missed on the first full-page pass.
- ✓Accepts input from files, stdin, or a plain GET request to a URL, and can merge multiple images or PDFs into one output PDF with `--merge`.
- ✓Exposes a typed, promise-based Node.js API (`ocr`, `ocr.pages`, `createSearchablePdf`, `supportedLanguages`) that mirrors the CLI flags for use inside scripts.
- ✓Supports BCP-47 language selection, custom vocabulary words, and a confidence threshold to drop low-confidence text.
Practical Applications
- •Turning a folder of scanned receipts or invoices into text files for bookkeeping, using `-o '[dir]/[name].txt'` to write one .txt per image and then grepping the results.
- •Making an old scanned PDF, like a lease or a form, searchable and selectable without re-typing it, via `mac-ocr searchable-pdf scan.pdf`.
- •Giving a coding agent local OCR instead of burning vision-model tokens on screenshots or documents — the README notes a bundled agent skill for exactly this.
- •Extracting structured text with bounding boxes and confidence scores (`--format json`) for a downstream pipeline that needs word positions, not just raw text.
- •Merging several photographed pages into one ordered searchable PDF with `--merge`, useful when a multi-page document was scanned with a phone camera.
Getting Started
Install it globally with `npm install -g mac-ocr`, or skip the install and run it once with `npx mac-ocr receipt.jpg`. The npm package ships a prebuilt universal binary, so there's no Xcode or Swift toolchain to set up — you need macOS 10.15 or later, and that's it. If you only want the Node.js API inside a project, `npm install mac-ocr` pulls in the same binary and exposes `ocr`, `ocr.pages`, and `createSearchablePdf` as functions instead of a CLI.
Strengths
- ✓Recognition runs on-device through Apple's Vision framework, so there's no per-page cloud OCR bill and no document leaving the Mac.
- ✓The npm package bundles a prebuilt universal binary, so `npm install -g mac-ocr` works without an Xcode or Swift toolchain.
- ✓Streaming output (`--format jsonl`, page-by-page PDF processing) means a large scanned document starts producing text immediately instead of after the whole file finishes.
- ✓The CLI and the Node.js API share the same flags and defaults, so a script built around `ocr()` behaves the same as the equivalent command line.
- ✓Partitioned OCR is an actual fallback strategy, not just a claim — it recursively re-crops regions with small or missing text rather than giving up after one full-page pass.
Considerations and Constraints
- △It only runs on macOS — the whole design leans on Apple's Vision framework, so there's no Linux or Windows build.
- △Partitioned OCR trades speed for accuracy: the README says large partitioned runs can take longer because Vision processes regions serially.
- △There's no documented language list or accuracy benchmark in the README — you find out which recognition languages are available by running `mac-ocr languages` on your own machine, not from a published list.
Other OCR Tools for macOS
Frequently Asked Questions
mac-ocr requires macOS 10.15 or later. The npm package installs a prebuilt universal binary, so you don't need Xcode or the Swift toolchain to run it.
mac-ocr does not send documents to the cloud: it runs entirely on your Mac using Apple's Vision framework, and the README states nothing is uploaded.
Recognition languages depend on your macOS version's Vision framework install, not a fixed list in mac-ocr itself. Run `mac-ocr languages` to see what's available on your machine, or add `--fast` for the fast recognizer's set.
Yes, mac-ocr's npm package exposes a typed, promise-based API with `ocr()`, an async `ocr.pages()` iterator for multi-page PDFs, and `createSearchablePdf()`, all wrapping the same binary the CLI uses.
mac-ocr is free for commercial use — it's released under the MIT license.
Partitioned OCR is the default strategy for searchable PDFs: mac-ocr OCRs the full page first, then recursively splits regions with small or missing text into smaller crops until Vision can read them or the region hits a size floor.
The problem it solves
Most CLI OCR options on macOS mean either sending documents to a cloud OCR API for per-page billing, or installing Tesseract with its own language-data packs and dependency chain. mac-ocr instead calls into the Vision framework already built into macOS, so recognition runs locally with nothing to download beyond the npm package and nothing uploaded anywhere.
How to use
OCR is the default action, so you don't need a subcommand: `mac-ocr receipt.jpg` prints recognized text to stdout, and `mac-ocr scan.pdf` walks a multi-page PDF. It also reads from stdin (`cat screenshot.png | mac-ocr`) and from a URL with a plain GET request. Default output is plain text; add `--format json` for bounding boxes and confidence per observation, or `--format jsonl` to stream one JSON object per PDF page as it's recognized. For searchable PDFs, `mac-ocr searchable-pdf scan.pdf` writes `scan.ocr.pdf` next to the input, keeping the original image intact and placing an invisible text layer word by word with Core Graphics and Core Text, at the coordinates Vision reported. Pages that already have selectable text are skipped by default in non-merge mode — pass `--ocr-all-pages` to force every page through OCR anyway. Under the hood, both commands call Apple's `VNRecognizeTextRequest` from the Vision framework, so recognition happens on the machine running the command, and the README states nothing is uploaded.
Who should try it — and who should skip
Try mac-ocr if you're building a macOS-only script, agent, or internal tool that needs to pull text out of screenshots, receipts, or scanned PDFs without sending anything to a cloud API — the Node.js API and the streaming JSON output make it easy to wire into an existing pipeline. Skip it if your code needs to run on Linux servers or Windows machines too, since the whole tool is built around a macOS-only framework, or if you just need one document read once, where dragging a file into Preview's Live Text is faster than installing anything.
Related repositories
Curious whether mac-ocr is right for you?
Let ChatGPT, Claude, or Perplexity look into it — click below and see what AI actually says about mac-ocr.
