Skip to main content

ocracy

One façade over many OCR engines — plus a ledger to help you choose between them.

OCR ("read the text in this image") is solved a dozen ways: local engines (Tesseract, EasyOCR, PaddleOCR), cloud APIs (Google Vision, AWS Textract, Azure), and VLM readers — each with its own install, API, pricing, and language coverage. ocracy gives you a uniform call, a browsable catalog of every option, and the tools to wrap any of them.

import ocracy

text = ocracy.read_text("scan.png")  # just the text, default backend
result = ocracy.ocr("scan.png")  # full result: text + word boxes + confidence
print(result)  # -> the recognized text
for word in result.words:
    print(word.text, word.bbox.as_tuple, word.confidence)

Install

import ocracy is dependency-free. Install only the backends you use, via extras:

pip install "ocracy[tesseract]"     # local, free (also needs the system `tesseract` binary)
pip install "ocracy[easyocr]"       # local, pip-only
pip install "ocracy[google-vision]" # cloud API
pip install "ocracy[table]"         # pandas, for catalog.to_dataframe()

Backends that ship today

The Blocks column is the one people get caught by: each backend reports exactly one granularity, so result.words is empty on a line-level backend and result.lines is empty on a word-level one — an empty list, not an error. See Granularity just below.

Backend backend= id Local / Remote Cost Install Blocks Notable
Tesseract tesseract local free ocracy[tesseract] (+ system tesseract) word 100+ language baseline
EasyOCR easyocr local free ocracy[easyocr] line 80+ languages, scene text
RapidOCR rapidocr local free ocracy[rapidocr] line same PP-OCR models as Paddle, light CPU/ONNX — recommended default for local plain text
PaddleOCR paddleocr local free ocracy[paddleocr] line the platform: server models, GPU, on-ramp to tables/layout (PP-Structure) & VL — heavier install
ocrmac (Apple Vision) ocrmac local (macOS) free ocracy[ocrmac] line on-device, handwriting
pix2tex (LaTeX-OCR) pix2tex-latex-ocr local free ocracy[pix2tex] text only one printed equation → LaTeX, offline
TrOCR (handwritten) trocr-handwritten local free ocracy[trocr] text only one pre-segmented handwritten line, MIT weights
OCR.space ocr-space remote free tier ocracy[ocr-space] word zero-install REST
Google Cloud Vision google-vision remote paid (+free tier) ocracy[google-vision] word high accuracy, handwriting, structure
AWS Textract aws-textract remote paid (+free tier) ocracy[aws-textract] word business docs, handwriting (forms/tables in analyze mode)
Azure Document Intelligence azure-document-intelligence remote paid (+free tier) ocracy[azure] word layout/tables/handwriting, on-prem container option
Mistral OCR mistral-ocr remote paid (pay-as-you-go) ocracy[mistral] text only cheap VLM → clean Markdown + math/tables
Mathpix mathpix remote paid (+free tier) ocracy[mathpix] text only math/handwriting → LaTeX & Markdown
Claude Vision claude-vision remote paid ocracy[anthropic] text only prompt-driven "read + reason" over messy/mixed documents
GPT-4o Vision gpt-4o-vision remote paid ocracy[openai] text only same, via OpenAI; schema-constrained JSON output

…plus 49 more engines/services catalogued in the ledger that you can turn into a working façade with one command (see Add a backend below).

Granularity: which backends fill .words, which fill .lines

Every backend emits exactly one granularity level. Nothing promotes words into lines or splits lines into words, and result.words / result.lines are just filters over the one flat blocks list — so asking for the level a backend does not produce returns [], silently:

r = ocracy.ocr("scan.png", backend="rapidocr")
r.lines  # populated
r.words  # [] — rapidocr reports lines, and nothing raises

r = ocracy.ocr("scan.png", backend="tesseract")
r.words  # populated
r.lines  # [] — tesseract reports words
  • word-level (.words populated, .lines empty): tesseract, google-vision, aws-textract, azure-document-intelligence, ocr-space.
  • line-level (.lines populated, .words empty): easyocr, rapidocr, paddleocr, ocrmac.
  • text only (blocks == [], so both are empty and mean_confidence is None): claude-vision, gpt-4o-vision, mathpix, mistral-ocr, pix2tex-latex-ocr, trocr-handwritten. Use result.text / result.markdown.

Iterating a result (for block in result:) yields whatever units that engine gave you, at its own level — it is not "lines by default".

The ledger's bounding_boxes flag describes the engine, not ocracy's adapter. claude-vision, mathpix and mistral-ocr are all bounding_boxes: true (their APIs can return geometry) while ocracy's façades for them return text only. Treat ocracy.find(bounding_boxes=True) as "engines worth wrapping for geometry", and the list above as what you get today. If your code needs a level, assert it:

result = ocracy.ocr(img, backend=chosen)
if not result.words:
    raise ValueError(f"{chosen} does not report word-level boxes")

Getting a backend running

Some backends need more than pip install (Tesseract's system binary, Paddle's framework, GPU wheels, first-run model weights, or an API key). ocracy turns that into structured, OS-aware guidance — handy for humans and AI agents alike:

ocracy.doctor()  # what's usable now vs what each missing one needs
ocracy.check("paddleocr")  # -> True/False (usable right now?)
print(
    ocracy.requirements("paddleocr").instructions()
)  # exact plan: pip + system deps + GPU + weights
ocracy.install(
    "rapidocr", yes=True
)  # run the pip install + verify (yes=False = dry run)
ocracy doctor · ocracy requirements paddleocr --gpu · ocracy install rapidocr --yes

requirements() even suggests a lighter alternative when one exists (e.g. PaddleOCR → RapidOCR). The ocracy-install-backend skill drives all of this.

Three tiers of access

From simplest to most powerful — reach for the next tier only when you need it:

ocracy.ocr(img)  # 1. facade, default (installed) backend
ocracy.ocr(img, backend="easyocr", languages=["en", "fr"])
ocracy.services.tesseract.read(img, psm=6)  # 2. pick a backend explicitly
ocracy.services.tesseract.adapter  # 3. the raw engine adapter, full control

Every backend returns the same OcrResult, so your code doesn't change when you switch engines: result.text, result.words / result.lines, each block's .bbox and .confidence (normalized to 0..1), result.mean_confidence, result.markdown (when a backend produces it), and result.raw (the untouched engine output).

The shape is uniform; the granularity is not. Each engine fills either .words or .lines (or neither), and the other is an empty list rather than an error — see Granularity before writing code that depends on one.

Command line

Install the CLI extra (pip install "ocracy[cli]") for an ocracy command:

ocracy read scan.png                          # print recognized text
ocracy read scan.png --backend easyocr --languages en,fr
ocracy read scan.png --output json            # text + blocks (boxes, confidence)
ocracy backends                               # backends you can run now
ocracy backends --capability math
ocracy status                                 # readiness table: all / implemented / set-up / tested
ocracy status --level set_up --names          # one level + the "Name (website)" lists
ocracy status --run-tests                     # also OCR-test set-up backends (real calls for remotes)
ocracy find --local --free --handwriting      # browse/filter the ledger
ocracy info google-vision                     # a backend's full record
ocracy scaffold surya                          # start a new façade from the ledger
ocracy validate tesseract                      # smoke-test a backend

Everything is also reachable as python -m ocracy <command>. cw builds the parser from the function signatures in ocracy/tools.py; argcomplete gives tab completion when activated.

The ledger — choose a backend with eyes open

ocracy ships a curated, data-driven catalog of every engine we researched — not only the ones with a working façade — so you can compare on the axes that matter (local vs remote, price, accuracy, languages, handwriting, math, tables, privacy). The data lives in ocracy/data/backends.json, separate from code.

ocracy.catalog  # <Catalog … backends … implemented …>
ocracy.catalog["google-vision"]  # one backend's full record
ocracy.find(is_local=True, open_source=True)  # filter the ledger
ocracy.find(handwriting="yes", is_remote=True)
ocracy.catalog.can("math")  # engines that read formulas
ocracy.catalog.supports_language("Arabic")
ocracy.find(implemented=True)  # only what ocracy can run today
ocracy.catalog.to_dataframe()  # browse as a pandas table
ocracy.catalog.compare(["tesseract", "google-vision", "mathpix"])

implemented is computed live from the code, so the ledger never lies about what actually runs. See ocracy/data/SCHEMA.md for every field. The full cited research report behind the ledger is in misc/docs/ocr_landscape_research.md.

Getting API keys (remote backends)

Remote backends need a credential in an environment variable. ocracy tells you exactly which one — with a link to get it — the moment it's missing:

>>> ocracy.ocr("receipt.png", backend="ocr-space")
MissingCredentialError: No credential found for ocr-space (set one of: OCR_SPACE_API_KEY).
How to get a credential for ocr-space: Register a free API key by email; free tier
allows 25,000 requests/month. Get a key: https://ocr.space/ocrapi/freekey
Backend Environment variable(s) Where to get a key
ocr-space OCR_SPACE_API_KEY https://ocr.space/ocrapi/freekey (free, 25k/month)
google-vision GOOGLE_APPLICATION_CREDENTIALS (service-account JSON path) https://cloud.google.com/vision/docs/setup
aws-textract AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY + AWS_DEFAULT_REGION https://docs.aws.amazon.com/textract/latest/dg/getting-started.html
azure-document-intelligence AZURE_DOCUMENT_INTELLIGENCE_KEY + AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT https://learn.microsoft.com/azure/ai-services/document-intelligence/create-document-intelligence-resource
mistral-ocr MISTRAL_API_KEY https://console.mistral.ai/api-keys
mathpix MATHPIX_APP_ID + MATHPIX_APP_KEY https://mathpix.com/ocr-api

The same guidance (and links for AWS, Azure, Mistral, OpenAI, Anthropic, Gemini) lives in ocracy.credentials.CREDENTIAL_GUIDANCE, and powers the dynamic errors. Tip: drop the variables in a .env file — ocracy soft-loads it via python-dotenv if that package is installed.

Add a backend (wrap any engine in minutes)

The catalog is large; ocracy ships façades for a curated subset and gives you the machinery to add any other one. Scaffold a backend straight from its ledger entry, fill in the adapter, and validate it:

from ocracy.make_backend import scaffold_backend, validate_adapter

scaffold_backend(
    "mathpix"
)  # creates ocracy/backends/mathpix/ prefilled from the ledger
# ... implement adapter.py's _read (call the engine, return an OcrResult) ...
validate_adapter("mathpix")  # smoke-test it end to end

The full, step-by-step process — including the adapter contract, input/output normalization helpers, credential handling, and packaging — is captured as an agent skill at ocracy/data/skills/ocracy-add-backend/SKILL.md. The ocracy/backends/tesseract/ package is a complete worked example.

Agent skills (Claude Code & other AI agents)

ocracy ships four Anthropic-style skills (under ocracy/data/skills/, installed with the package) so AI coding agents can both use and extend it:

Skill Audience What it helps with
ocracy users OCR an image/PDF, choose & install a backend, read the result
ocracy-choose-backend users filter & compare the 64-backend ledger to pick the right engine
ocracy-install-backend users / agents get a backend running — heavy installs, system deps, GPU, weights, keys
ocracy-add-backend developers wrap a new engine behind ocracy's interface (scaffold → adapter → validate)

In a repo using Claude Code they're discoverable via the .claude/skills/ symlink bridge; they also travel with pip install ocracy under ocracy/data/skills/.

How it works

  • ocracy/base.py — the normalized types (OcrResult, TextBlock, BBox).
  • ocracy/catalog.py — the ledger reader/filter (ocracy/data/backends.json).
  • ocracy/registry.py — lazy backend discovery + default selection.
  • ocracy/services.py — the three-tier service layer.
  • ocracy/make_backend.py — the façade-building toolkit (BaseOcrAdapter, make_block, scaffold_backend, validate_adapter).
  • ocracy/backends/<id>/ — one subpackage per engine (config.py + adapter.py).
  • ocracy/credentials.py — credential resolution for remote backends.
  • ocracy/kit/ — the facade kit: the param_map translator, the credential chain and install plans, stdlib-only and shared with other facades (see below).
  • ocracy/tools.py + ocracy/__main__.py — the ocracy CLI (cw).

The facade kit, for building other facades

The machinery under ocracy is not OCR-specific, and other facades (foley, falaw, voxy, scribed) use it instead of copying it:

from ocracy.kit import make_translator, resolve_credential, using_credentials

translate = make_translator(
    {"languages": {"native_name": "lang", "coerce": "+".join}, "dpi": None},
    backend="tess",
    on_unsupported="note",
    always_raise=("seed",),
)
t = translate({"languages": ["eng", "fra"], "dpi": 300})
# t.kwargs == {"lang": "eng+fra"}; t.notes == ["dpi=300 is not supported by tess; dropped"]

key = resolve_credential("acme", env_var="ACME_API_KEY")  # explicit -> bound -> env
with using_credentials(acme=request_key):  # per-request BYO key
    ...

ocracy.kit imports only the standard library; the design is in docs/adr/0001-facade-kit.md.

The architecture mirrors the sibling façade packages denote (audio→symbol) and aix (LLM providers).

Metadata

Release files for ocracy 0.1.13

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ocracy 0.1.13
File Size Uploaded
ocracy-0.1.13.tar.gz 273.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ocracy 0.1.13
File Interpreter ABI Platform
ocracy-0.1.13-py3-none-any.whl Python 3 none any Details

Total release size: 557.6 kB

Release files / ocracy-0.1.13.tar.gz

Download URL ocracy-0.1.13.tar.gz
Size 273.4 kB
Tags Source
SHA-256 checksum
How to use checksums
28ab0af12655034461b77750124ee3ceafd8d921adc65f2bd277d2eb07003a57
BLAKE2b-256 checksum
How to use checksums
6acb5f7f1fbfd63c1b25398eed080d8f02e5862cfaac7db25e21dabb571b6bd7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / ocracy-0.1.13-py3-none-any.whl

Download URL ocracy-0.1.13-py3-none-any.whl
Size 284.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
de6e8935e8350fcd72c7d28b3c4fc48711090f6838980901236e24fcc7a28f10
BLAKE2b-256 checksum
How to use checksums
5acc41131f49a7112d19e0f31c6e376ac1a7d5d2812c3e3f0977df934398f18d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.1.14

2 release files

This release

0.1.13 This release

2 release files

0.1.11

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.0.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page