cd /news/computer-vision/a-faster-tesseract-alternative-ocr-p… · home › topics › computer-vision › article
[ARTICLE · art-163592] src=dev.to ↗ pub= topic=computer-vision verified=true sentiment=↑ positive

A faster Tesseract alternative: OCR PDFs to markdown on CPU with Indra OCR

Datalab's Indra OCR, a 1M-parameter OCR model that runs on CPU via ONNX Runtime without PyTorch or a GPU, converts PDFs and images into markdown, text, or JSON with bounding boxes and reading order, and handles handwriting and 80+ languages. The project's own benchmarks put its overall score at 61.3, ahead of PaddleOCR's PP-StructureV3 pipeline at 58.4, with a text score of 46.7 versus 35.8 for PaddleOCR's PP-OCR and 19.3 for Tesseract. It ships as a pip-installable CLI and Python library with an auto mode that reads existing PDF text layers and OCRs only missing pages, plus a local viewer for side-by-side comparison with Tesseract.

by read3 min views2 publishedNov 4, 2026

Tesseract is still the default OCR engine in a lot of pipelines, mostly because it is free, local and needs no GPU. Indra OCR from Datalab keeps all three of those properties and adds layout, reading order and handwriting. This post shows how to install it, convert PDFs to markdown or JSON, and use it from Python.

datalab-to/indra describes Indra OCR as a 1M-parameter OCR model that runs on CPU. It turns PDFs and images into markdown, text, or JSON with boxes, and reads handwriting, 80+ languages and pages at any angle. It runs on ONNX Runtime, with no PyTorch and no GPU.

--math), ahead of PaddleOCR's full PP-StructureV3 pipeline at 58.4. Its text score of 46.7 is ahead of PaddleOCR's PP-OCR text models (35.8) and Tesseract (19.3). These are the project's own benchmarks, so treat them as a reason to test on your documents, not as a guarantee.

You need Python 3.10 or newer. The README lists testing on Linux (x86_64 and aarch64) and macOS on Apple silicon.

pip install indra-ocr

The first run downloads the models from Hugging Face and caches them. To use a local copy, set INDRA_OCR_MODEL_DIR or pass --model-dir, which is what you want on an air-gapped server.

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
indra-ocr paper.pdf --format text         # plain text, one line per detected line
indra-ocr paper.pdf --mode ocr --timings  # ignore the text layer, OCR every page
indra-ocr paper.pdf --math                # write math as LaTeX

The default --mode auto is the part that saves time on mixed archives: it reads the PDF text layer where it passes the checks and only OCRs what is missing. Use --mode ocr when a text layer is present but garbage, which happens a lot with old scans. Page headers and footers are left out of the markdown unless you pass --keep-furniture.

The CLI keeps going past files it cannot read and exits with 1 if any failed, so it is safe to point at a big folder.

indra-ocr-viewer --port 8765

Open http://localhost:8765 and drop in a PDF or image. Each page shows its lines, layout blocks and reading order drawn over the page, with the rendered markdown, the lines with their confidences and the JSON. Files stay on your machine. Install pip install "indra-ocr[tesseract]" plus a Tesseract binary and the viewer can compare the two side by side, which is the fastest way to decide whether to switch.

import indra_ocr

conv = indra_ocr.load(threads=4)          # mode="auto" | "ocr" | "text"
for i, page in conv.convert("paper.pdf"):
    print(page.source, page.timings["total_ms"])
    print(page.markdown)                  # headings, lists, tables as HTML
    page.blocks                           # [{"label", "bbox", "text"}] in reading order
    page.lines                            # [Line(box, text, conf)] in reading order

For batches, convert_many runs one single-threaded worker per core and returns results in input order. Keep the if __name__ == "__main__": guard on macOS and Windows:

import indra_ocr

if __name__ == "__main__":
    for path, result in indra_ocr.convert_many(["a.pdf", "b.pdf"], cores=None):
        if isinstance(result, indra_ocr.InputError):
            continue                      # unreadable or locked file
        for i, page in result:
            print(path, i, page.source)

Every block carries a label (Text, Section-Header, Table, Caption, Footnote, Form and more) and a bounding box, so feeding clean chunks to an LLM or a search index is a filter, not a regex project.

The builds collected on the Indra page are mostly about replacing Tesseract in existing tools:

If you run Paperless-ngx at home, those two plugins are the quickest real-world win.

Indra is built for speed on CPUs. For very long documents, Baidu's Unlimited OCR is an open OCR model aimed at parsing documents of any length within a finite context window, and it is worth comparing on that kind of input. The Indra README itself points to Datalab's larger Chandra model for the hardest handwriting, math, complex tables and degraded scans.

Source repo: datalab-to/indra.

Want the setup commands for 50 AI repos people actually ship with? Get the free AI Repos That Actually Ship pack: https://dedupedai.com/ship-pack/?utm_source=devto&utm_medium=article&utm_campaign=shippack

── more in #computer-vision 4 stories · sorted by recency
── more on @datalab 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/a-faster-tesseract-a…] indexed:0 read:3min 2026-11-04 · —