Indra OCR: tiny CPU-only OCR for PDFs and scans (Linux, Windows, Mac)
Before you start
- 18 min read
- 16 to run in terminal
Boxes marked Run in terminal are what you type; plain text explains why. Check what you need first

What you get in one minute#
Indra OCR is a 1M-parameter OCR model that runs entirely on your CPU - no GPU, no PyTorch - and turns PDFs and images into markdown, plain text, or JSON with a box, a label and a reading order for every line and block.

Logo: Datalab, the maker of Indra OCR, from the official model card (huggingface.co/datalab-to/indra-ocr) It comes from Datalab, the lab behind Marker and Surya, and it exists for one situation: you have many documents, no GPU, and you need "good enough" text fast. On the maker's benchmarks it reads about 44 pages per second on 32 CPU cores - 15x Tesseract and 10x PaddleOCR's PP-OCR text models on the same machine - and a single page takes about 210 ms on 4 cores. It handles 80+ languages on scans, any script through a digital PDF's text layer, and pages tilted up to 45 degrees. It is weak on handwriting, complex tables and degraded scans, and the maker says so in the README's own limitations section.
| Current version | indra-ocr 1.1.2 (PyPI, released Oct 20, 2026; models tag v1.1.0) |
| Time needed | About 10 minutes (our estimate: one pip install plus a 76 MB model download) |
| Size on disk | About 76 MB of models (30 MB of networks + 46 MB of language models); no GPU, no PyTorch |
| Ports | 8765, only if you run the local viewer; the CLI opens no port |
| Licence | Code Apache 2.0; weights a modified OpenRAIL-M (free for research, personal use, and startups under $20M funding/revenue) |
| Official docs | github.com/datalab-to/indra and huggingface.co/datalab-to/indra-ocr |
At a glance:
- What it is: a pip-installable OCR package built around a 1.25M-parameter recognizer (7.3M parameters for the whole default pipeline), running on ONNX Runtime.
- What you get out: markdown (headings, lists, tables as HTML), plain text, or JSON with line boxes, block labels and confidences.
- Speed: about 44 pages/s on 32 cores and about 210 ms per page on 4 cores, in the maker's own benchmarks (October 2026).
- Languages: 80+ scripts on scans and images; any script when a digital PDF's text layer passes the checks.
- Weak spots: handwriting (25.2% on the benchmark's handwriting tests), complex tables, degraded scans, some rotated non-Latin scans.
- Platforms: Linux (x86_64, aarch64) and macOS (Apple silicon) are the maker's tested platforms; Windows runs but is not in the tested list.
How it fits together#
One command reads your file; everything else happens on your machine.
The fast path (green) is why digital PDFs are quick: if the text layer passes the checks, no OCR runs at all. The 76 MB of models download from Hugging Face on the first run only, then run from the local cache. Drawn from the official README, October 2026.
Before you start#
You need any reasonably modern machine; there is no GPU requirement and no large download.
Linux (x86_64 or aarch64): officially tested by Datalab on Python 3.10 to 3.13. Check with:
python3 --version
Windows: not in the maker's tested list. Users do run it on Windows - three of the reports we read were Windows machines - but treat it as untested, and see the known --math bug in Troubleshooting below. Check with:
python --version
Mac (Terminal): officially tested on Apple silicon. Check with:
python3 --version
Checklist before you install:
- [ ] Python 3.10 or newer
- [ ] Free disk space for the 76 MB of models, the Python packages (ONNX Runtime and OpenCV are not tiny) and your output files
- [ ] No GPU needed - CPU only
- [ ] If you will use the viewer: port 8765 free, or pick another with
--port
Not tested by DIY Lab Hub - we ran nothing in this guide. Every command and number here comes from the official README, changelog, PyPI page and issue tracker, read on 2026-10-30.
Step 1: Install Indra OCR#
The package is indra-ocr on PyPI. It installs ONNX Runtime, OpenCV and pypdfium2, and no PyTorch.
Linux#
pip install indra-ocr
Windows (PowerShell)#
pip install indra-ocr
Windows is not officially tested (see Before you start). The install itself is the same command.
Mac (Terminal)#
Same commands as Linux:
pip install indra-ocr
Check it worked. Both the CLI and the viewer take --version (added in release 0.3.1):
indra-ocr --version
The command prints the package version; at the time of writing that is 1.1.2. If you want the newest code straight from GitHub instead of PyPI, the README also gives pip install git+https://github.com/datalab-to/indra.git.
Tip: If
indra-ocris not found after install, the pip script directory is probably not on your PATH. Re-run the check after fixing your PATH rather than reinstalling.
Step 2: Convert your first documents#
The first run downloads about 76 MB of models from Hugging Face and caches them; later runs work from the cache.
Linux#
indra-ocr paper.pdf # markdown to stdout indra-ocr *.pdf --out results/ # one .md per input, all cores indra-ocr scan.png --format json # lines, boxes, layout blocks, confidences
Windows (PowerShell)#
indra-ocr paper.pdf indra-ocr *.pdf --out results/ indra-ocr scan.png --format json
Mac (Terminal)#
Same commands as Linux:
indra-ocr paper.pdf indra-ocr *.pdf --out results/ indra-ocr scan.png --format json
Check it worked. Run one file with timings on:
indra-ocr paper.pdf --timings
Per the README, --timings prints each page's source and time to stderr, so you can see which pages used the PDF's text layer and which needed OCR. Useful options: --format text for plain text, --mode ocr to ignore the text layer, --cores 8 to limit workers, --math to write math as LaTeX (slower; see What the numbers mean), --keep-furniture to keep page headers and footers.
Tip: Digital PDFs with a good text layer skip OCR entirely and are the fastest pages you can feed it. Do not force
--mode ocron born-digital PDFs unless you truly want every page read as an image.
Step 3: Try the local viewer#
The package ships a local web viewer that draws lines, blocks and reading order over each page, with the markdown and JSON side by side.
Linux#
indra-ocr-viewer --port 8765
Windows (PowerShell)#
indra-ocr-viewer --port 8765
Mac (Terminal)#
Same commands as Linux:
indra-ocr-viewer --port 8765
Check it worked. Open http://localhost:8765 in your browser and drop in a PDF or an image. The README is explicit: "Files stay on your machine." To compare Indra OCR with Tesseract side by side in the viewer, install the extra and a Tesseract binary: pip install "indra-ocr[tesseract]".
Network access: keep the viewer local#
There is no server to put behind HTTPS. Indra OCR is a CLI and a Python library; the only thing that listens on a port is the viewer, and the viewer has no authentication and no multi-user design. It is meant for localhost.
- The CLI opens no port at all.
- The viewer binds locally; the README's documented way to reach it from another machine is SSH port forwarding:
ssh -N -L 8765:localhost:8765 host. - Do not expose the viewer through a reverse proxy on the public internet. It would let anyone who can reach it feed documents into your machine - the opposite of why you would pick a local OCR tool.
If you need OCR as a network service for other machines, wrap the Python API (indra_ocr.load() and convert()) in your own small service with authentication - but that is your code, not something the package provides.
Security and testing#
- What leaves your machine: the first run downloads about 76 MB of models from huggingface.co. After that, the cached model folder is checked against the Hub at most once a day; all other runs use the cache with no network, and a failed (offline) check keeps the cached models. Your documents are processed locally; the README documents no telemetry, and the viewer states that files stay on your machine. We read the README and changelog, not every line of code.
- Secrets: none needed. No API key, no account, no
.envfile. If you use the optional Datalab platform, that is a separate cloud product with its own keys - this guide is only about the local package. - Functionality test: convert one known page and check the markdown:
indra-ocr paper.pdf --max-pages 1. The CLI continues past files it cannot read and exits with code 1 if any file failed, so a silent exit 0 means every file was read. - Licence check before commercial use: the code is Apache 2.0, but the model weights use a modified OpenRAIL-M licence - free for research, personal use, and startups under $20M funding/revenue, and not usable competitively with Datalab's API. Above those limits, see their pricing page.
What the numbers mean#
All numbers in this section are the maker's own benchmarks (Datalab builds the OmniParseBench benchmark and sells a paid OCR API, so treat them as vendor numbers - the benchmark script is published in the repo if you want to rerun it). Throughput was measured on x86 (AMD EPYC 9004 Genoa, no GPU), OCR mode, one single-threaded worker per core, on 300 OmniParseBench pages, model loading not timed:
| Engine | 4 cores | 8 cores | 16 cores | 32 cores |
|---|---|---|---|---|
| Indra OCR | 6.2 | 11.9 | 23.7 | 43.9 |
| PaddleOCR PP-OCRv6 small (text models) | 0.65 | 1.24 | 2.42 | 4.28 |
| Tesseract 5 | 0.78 | 1.37 | 2.27 | 2.92 |
At 32 cores that is 10x PaddleOCR's PP-OCR text models and 15x Tesseract. Throughput depends on the CPU: on other x86 containers the maker measured 25 to 51 pages per second at 32 cores. A 4-core machine still gets 6.2 pages/s - about 210 ms per page (212 ms median in the benchmark table).
Accuracy comes from OmniParseBench: 16,288 pass/fail tests on 2,937 pages, every engine on the same pages with the same scorer, x86 with 4 vCPUs, one page at a time:
| Engine | Headline | Text | Tables | Layout | Median ms/page |
|---|---|---|---|---|---|
| Indra OCR (auto) | 66.7 | 46.7 | 61.1 | 92.2 | 212 |
Indra OCR --math | 71.4 | 62.7 | 59.6 | 92.0 | 357 |
| PaddleOCR PP-StructureV3 | 58.4 | 55.6 | 47.8 | 71.7 | 40,958 |
| PaddleOCR PP-OCRv6 small (text only) | - | 35.8 | 0.0 | - | 2,685 |
| Tesseract 5 | - | 19.3 | 0.0 | - | 5,496 |
Three honest readings of that table:
- PP-StructureV3 reads plain text better than default Indra OCR (55.6 vs 46.7). Indra wins the headline because it also does tables and layout, and it is about 190x faster per page. With
--mathon, Indra passes it on text too (62.7). --mathcosts speed: the median page goes from 212 ms to 357 ms, and throughput drops about 30% on 4 cores and 38% on 32. Tables lose 1.5 points because numbers in some cells get read as math. That is why it is off by default.- Against the big open models, Indra is at the back - by design. In Datalab's October 2026 comparison of 17 open-weight OCR models, chandra-ocr-2 (4.5B parameters) scores 90.1, Surya OCR 2 (0.67B) 83.1, DeepSeek-OCR-2 75.2, Indra OCR 71.4, HunyuanOCR 64.6. Indra is the only one of the 15 that runs like this on a CPU, at 12.3M parameters - more than 50x smaller than any other model in the table. The maker's own advice: "If you only have CPUs: Indra OCR."
Where Indra OCR is weak#
The README has a limitations section, and it matches what users report. Know these before you batch-convert anything important.
- Handwriting. "Handwritten pages read, but not well" - 25.2% on the OmniParseBench handwriting tests, and about a third of the words on held-out handwritten pages. Cursive and faint pencil read worst. A Hebrew user put it plainly: "Pointed Hebrew is still unusable with accuracy below 5%" (issue #26). Clear handwriting in Latin script is the best case; do not pick a CPU OCR tool for handwriting.
- Complex tables. Merged or spanning cells, cell text that wraps over several lines, nested headers, or no ruling lines can come out with cells in the wrong rows or columns. Simple grid tables read well. On OmniDocBench the table TEDS is 0.47 - usable, not great.
- Non-English and script coverage. 80+ languages OCR on scans (95 measured; 83 at character F1 0.90 or higher), but Syriac, Tibetan, Mongolian, Santali, Meitei and other scripts outside the recognizer list work only through a digital PDF's text layer. Khmer (70.6) and Malayalam (65.0) are "fair" on OmniParseBench. In Latin-script languages with many diacritics (Kurmanji, Czech, Lithuanian, Icelandic, Turkish, Slovak) a close diacritic can replace the right one; English, French, German and Spanish are not affected. One user found Spanish Ñ is lost in the condensed Impact font used in memes and video captions, while the same words in Arial Bold read perfectly (issue #16).
- Rotated scans - mostly fixed, with real exceptions. Version 1.1 straightens tilts up to 45 degrees and turns sideways or upside-down pages upright (rotated-page score 25.3% to 50.3% from 1.0 to 1.1). But the orientation model only turns a page when it is at least 95% sure: sideways plan sheets often stay unturned (issue #17), a 60-degree rotated table page returned four empty lines (issue #29), and upright Odia scans were turned 180 degrees on 18 of 30 Wikisource pages, coming out as Sinhala, Armenian or Latin letters (issue #32).
- Degraded scans. Old, faded or low-resolution scans read poorly: 29.5% on the OmniParseBench degraded-scan tests.
- Also: math comes out as plain text unless
--mathis on; vertical newspaper layouts can come out in the wrong article order; very wide banner-shaped pages read poorly; labels in engineering drawings often become small tables; pages above 100 megapixels at 200 dpi render at a lower dpi, which can lose small text.
For handwriting, heavy math, complex tables and degraded scans, the README itself points to Datalab's larger Chandra models (their API or self-hosted) or to other tools.
Common mistakes#
| Mistake | Why it happens | Do this instead |
|---|---|---|
| Expecting good handwriting OCR | The 1.1 release notes say it "reads handwriting", which sounds stronger than it is | Read the README's limit first: 25.2% on handwriting tests, about a third of words on held-out pages. Use it for print, not handwriting |
| Trusting complex tables | The pipeline is built for speed on clean print | Check table output by hand; keep simple grid tables; use a table-focused tool for merged cells and nested headers |
Running --math on Windows without UTF-8 mode | Windows reads the UTF-8 math metadata as cp1252 and crashes (issue #27) | Set PYTHONUTF8=1 before the run (the issue's workaround); the fix PR is still open |
Turning on --math after a first run without it | The first run caches a partial model snapshot without the math files, and retrying never fixes it (issue #18) | Delete the cached indra-ocr model folder in your Hugging Face cache (or point --model-dir at a fresh folder) so all files download |
| Expecting every rotated scan to be recovered | The orientation model needs 95% confidence before it turns a page | Pre-turn known-sideways pages yourself; see Troubleshooting for the wrong-turn cases |
| OCRing scripts the recognizers do not cover | The four recognizers cover 80+ languages, not all scripts | Check the README's language list; for uncovered scripts on scans, use another tool (text layers still work in any script) |
| Trusting an AI assistant's numbers or platform claims for Indra | The launch post (Oct 13) says 49 pages/s and "doesn't read handwriting yet"; both changed six days later with 1.1 (about 44 pages/s, handwriting read poorly). Assistants also call Windows "supported" (the README tests Linux and macOS) and invent Docker images (none published) | Check the current README and changelog before quoting anything; the repo is the source of truth, and this tool moves fast |
Tip: Run
indra-ocr --versionafter installing to confirm the CLI is on your PATH, andindra-ocr paper.pdf --timingson a sample to see where the time goes before you batch 10,000 pages.
Tip: Start without
--math. It is the slowest mode (357 ms vs 212 ms median per page) and it slightly lowers table scores. Turn it on only for documents that actually contain math.
Tip: Use
--cores Nto cap workers when the machine is busy with something else; the default is all usable cores, one single-threaded worker each.
Troubleshooting#
| Problem | Solution |
|---|---|
UnicodeDecodeError: 'charmap' codec can't decode byte 0x81 when loading math models on Windows | Known bug, issue #27. Set PYTHONUTF8=1 for the run (PowerShell: $env:PYTHONUTF8 = "1"), or skip --math until the fix lands |
FileNotFoundError: math=True needs the math models in ... | The cache was primed by a run without --math, issue #18. Delete the cached indra-ocr model folder in your Hugging Face cache, or pass --model-dir to a fresh folder, then run again |
| An upright non-Latin scan comes out in the wrong script | The orientation model turned it 180 degrees, issue #32 (18 of 30 Odia pages). The issue's diagnostic workaround is indra_ocr.pipeline.ORIENT_MIN = 1.01, which disables the turn |
| A sideways or heavily rotated page returns almost nothing | The orientation model only turns at 95% confidence, issues #17 and #29. Rotate the image upright yourself before OCR |
| One page crashes the run on a very narrow detected line | Rare, issue #24 (1 in 337 pages in that report); newer onnxruntime CPU builds tolerate it. Update onnxruntime; fix PR #25 is open |
| Output is empty or short on a huge page | Pages above 100 megapixels at 200 dpi render at a lower dpi and can lose small text (README). Try a higher --dpi, or split the page |
Known bugs (open on 2026-10-30)#
- #32 (Oct 28): upright Odia scans turned 180 degrees; also hit Gujarati, Malayalam, Hindi and Telugu pages in the same run.
- #29 (Oct 26): 60-degree rotated page returns empty text; a manual 90-degree turn recovers it.
- #27 (Oct 25): Windows
--mathcp1252 crash; workaround above; fix PR #28 open. - #18 (Oct 22):
--mathfails forever after a no-math first run; fix PR #19 open. - #24 (Oct 23): crash on a detected line narrower than 32 px with onnxruntime 1.19.2; fix PR #25 open.
- #22 (Oct 23): on the undocumented CUDA path, GPU memory grows with every page and is never released. If you run Indra on a GPU via onnxruntime-gpu, watch your memory; the documented path is CPU.
Fixed since release: Arabic letter-reversal from Chrome-printed PDFs (#11, fixed in 1.1.1), negative --max-pages silently dropping pages (#10, fixed in 1.1.0), and a surrogate-pair crash on PDFs with characters outside the BMP (#3, closed as completed).
Updates and backups#
Update. The package moves fast - six releases between Oct 13 and Oct 20, 2026 - and each release pins a model tag (1.1.x uses the Hugging Face tag v1.1.0), so an update can bring new models on the next run:
pip install -U indra-ocr
Back up your results. The tool keeps no database; your outputs are whatever you wrote with --out. Back up that folder (generic commands, not from Datalab):
mkdir -p backups tar -czf "backups/indra-ocr-results-$(date +%F).tar.gz" results/
New-Item -ItemType Directory -Force backups | Out-Null Compress-Archive -Path results -DestinationPath "backups\indra-ocr-results-$(Get-Date -Format yyyy-MM-dd).zip"
Restore test. Unpack an archive, open one markdown file, and re-run indra-ocr on its source page - the text should match. If you rely on the cached models for offline work, back up the model folder you set with INDRA_OCR_MODEL_DIR too; a failed daily Hub check keeps the cached models, but a deleted cache needs the network again.
Performance and resources#
- Cores are the main knob. The CLI and
convert_manyrun one single-threaded worker process per usable core, one page per task, so a single long PDF uses every core.--cores Nlimits it. In the changelog's test, 40 documents took 30.0 s on 1 core, 8.7 s on 4, and 2.8 s on 16. - Mode beats hardware. A digital PDF page with a good text layer skips OCR and is the cheapest page there is; in the maker's throughput run, text-layer pages took a median of 130 ms against 304 ms for OCR pages (release-post numbers for 1.0; 1.1 keeps the same design).
--dpi(default 200) raises quality and cost together on scans.- Memory: no official minimum is published. The changelog's bounded-memory work reports a 40-page large scan peaking at 1.4 GB with the CPU arena off (it was 4.9 GB before that fix, in 0.3.0). A normal page is far lighter.
- Monitoring:
--timingsprints per-page source and time to stderr; the JSON output carries per-step milliseconds intimingswithtotal_ms.
FAQ#
Does it need a GPU? No. It runs on ONNX Runtime on the CPU, installs no PyTorch, and the maker's speed numbers are all CPU numbers. Running it on a GPU via onnxruntime-gpu is possible but undocumented, and has a known memory-growth bug (issue #22).
Does Windows work? It installs and users run it, but Windows is not in the maker's tested list (Linux x86_64/aarch64 and macOS Apple silicon are). There is one confirmed Windows bug: --math crashes with a cp1252 UnicodeDecodeError until you set PYTHONUTF8=1 (issue #27).
What leaves my machine? The first run downloads about 76 MB of models from huggingface.co. After that, runs use the local cache with no network, apart from a model check against the Hub at most once a day (an offline failure keeps the cache). Your documents are processed locally and the viewer keeps files on your machine.
Is it free for commercial use? The code is Apache 2.0. The model weights use a modified OpenRAIL-M licence: free for research, personal use, and startups under $20M funding/revenue, and not usable competitively with Datalab's API. Bigger companies need their commercial licence.
Why not just use Tesseract? On the maker's benchmarks, Tesseract 5 scores 19.3 on OmniParseBench text against Indra's 46.7, and reads 2.92 pages/s on 32 cores against Indra's 43.9. Tesseract is older, slower here, and returns lines only - no layout blocks or reading order. Tesseract remains the more battle-tested choice for odd builds and every platform; Indra is the faster, more structured one on supported platforms.
Can I get word-level bounding boxes? Not yet - boxes are per line and per layout block. Word-level boxes are an open feature request (issue #7).
Sources#
- Indra OCR README (install, usage, languages, limitations, benchmarks) - read October 2026
- Indra OCR model card on Hugging Face - read October 2026
- indra-ocr on PyPI (version 1.1.2, release history) - read October 2026
- Indra OCR changelog - read October 2026
- Datalab: Indra OCR release post (Oct 13, 2026) - read October 2026
- Datalab: Indra OCR 1.1 (Oct 19, 2026) - read October 2026
- Datalab: open-source OCR models on OmniParseBench (Oct 23, 2026) - read October 2026
- GitHub issues #32, #29, #27, #26, #24, #22, #18, #17, #16, #11, #10, #7, #6, #3 - read October 2026
- Hugging Face discussions on indra-ocr - read October 2026
Checked against the official docs on 2026-10-30.