Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

turboocr

Python for TurboOCR: the typed client for a TurboOCR server (sync + async, HTTP + gRPC, layout-aware Markdown rendering, searchable-PDF generation) — and, via one extra, the in-process native engine, so the same package OCRs locally with no server at all.

PyPI Python Typed License: MIT

Install

pip install turboocr             # HTTP client + CLI + searchable-PDF
pip install 'turboocr[grpc]'     # add the gRPC transport
pip install 'turboocr[all]'      # everything optional (currently == [grpc])

To also run OCR in-process (no server), add exactly one backend extra — it pins the matching native turboocr-engine-* wheel:

pip install 'turboocr[cpu]'       # any CPU
pip install 'turboocr[apple]'     # Apple Silicon — Metal GPU + Neural Engine
pip install 'turboocr[cuda12]'    # NVIDIA (TensorRT + CUDA EP), driver R525+
pip install 'turboocr[cuda13]'    # same, CUDA 13 — driver R580+
pip install 'turboocr[openvino]'  # Intel CPU / iGPU / Arc / NPU
pip install 'turboocr[rocm]'      # AMD (ROCm)

turboocr doctor names the right one for your machine. With an engine installed, turboocr.OCR() runs locally:

import turboocr

page = turboocr.OCR().read("invoice.png")   # in-process, no server
print(page.text)

The in-process engine has the full API — replica pools, read_pdf with page fan-out, read_pdf_stream / aread_pdf_stream streaming, and async twins for every read — see the Python library reference.

Without one, the client API works everywhere and turboocr.OCR() raises an ImportError naming the extra to install. Feature extras combine with any backend: 'turboocr[cuda,pandas]'. PDF in/out is built in — no extra needed.

Requires Python 3.12+.

Quickstart

Start a TurboOCR server (the C++/CUDA OCR engine; for serverless in-process OCR see the backend extras above):

docker run --gpus all -p 8000:8000 -p 50051:50051 \
  -v trt-cache:/home/ocr/.cache/turbo-ocr \
  -e TABLE_BACKEND=slanext -e FORMULA_BACKEND=ppformulanet_s \
  ghcr.io/aiptimizer/turboocr:latest

(:latest is the v3.5 release image — this client talks to it fine; the v4-alpha server has no published image yet and builds from the repo.)

The default OCR_MODEL=tiny covers Latin + Chinese (Japanese needs small/medium — tiny omits kana); small/medium trade speed for accuracy, and arabic, eslav, korean, thai, greek are baked in too. The two backend env vars enable table → HTML and formula → LaTeX recognition (strict per-request opt-ins). See the TurboOCR repo for build-from-source, benchmarks, and the full set of server env vars.

Then recognise an image and turn a PDF into Markdown:

from pathlib import Path

from turboocr import Client

with Client(base_url="http://localhost:8000") as client:
    # Image OCR
    img = client.recognize_image("page.png", layout=True, include_blocks=True)
    print(f"{len(img.results)} text items, {len(img.blocks)} blocks")
    print(img.text)

    # PDF → Markdown file (rendered server-side: tables → HTML, formulas →
    # LaTeX, figures embedded as data URIs — a real, self-contained .md)
    Path("paper.md").write_text(client.pdf_markdown("paper.pdf", dpi=150))

    # Tables + formulas as structured fields (strict opt-in, v3.1+ server)
    rich = client.recognize_image("paper.png", tables=True, formulas=True)
    for table in rich.tables:
        print(table.html)
    for formula in rich.formulas:
        print(formula.latex)

    # Searchable PDF (invisible text overlay)
    overlay = client.make_searchable_pdf("scan.pdf", dpi=200)
    open("scan.searchable.pdf", "wb").write(overlay)

That's the 80% case. Full runnable examples for async, gRPC, batch, retries, custom httpx.Client, hooks, Markdown styling, folder pipelines, and more live in examples/ — every script runs end-to-end against the bundled ACME invoice fixture.

What you get

  • Sync + async, HTTP + gRPC. Four clients (Client, AsyncClient, GrpcClient, AsyncGrpcClient) with identical method surfaces.
  • Typed, immutable responses (pydantic v2). IDE autocomplete, and if a newer server adds a field your SDK doesn't know about, parsing still succeeds — the extra lands on .model_extra instead of crashing.
  • Layout-aware Markdown. render_to_markdown(...) walks the reading order and maps each layout class (doc_title, display_formula, table, …) to a Markdown construct. Pluggable via MarkdownStyle.
  • Searchable PDFs. make_searchable_pdf(...) overlays an invisible text layer aligned to the page geometry. Auto-discovers a Unicode font for non-Latin scripts, or pass font_path=.
  • Production-friendly. Configurable retry policy (HTTP status + gRPC status
    • Retry-After), per-request timeouts, custom httpx.Client, on_request / on_response event hooks, uuid7 X-Request-ID per call.
  • Tables → HTML, formulas → LaTeX. tables=True / formulas=True (server v3.1+, strict opt-in) populate response.tables[*].html and response.formulas[*].latex; client.capabilities() tells you what the running server has loaded.
  • Server-side Markdown. client.pdf_markdown(...) converts a whole PDF in one call (as_pages=True for per-page chunks — the RAG-friendly shape); client.page_markdown(...) does a single image. render_to_markdown(...) stays for client-side, style-customizable rendering.
  • Per-page streaming. client.stream(...) yields NDJSON events as each page completes, so you can start consuming page 1 while page N is still being OCR'd.
  • Precise exception hierarchy. Maps the server's error codes to typed exceptions — see Errors.
  • turbo-ocr CLI included in the default install.

Configuration

from turboocr import Client, RetryPolicy

client = Client(
    base_url="http://localhost:8000",   # or TURBO_OCR_BASE_URL env
    api_key="sk-...",                   # or TURBO_OCR_API_KEY env
    auth_scheme="bearer",               # "bearer" | "x-api-key"
    timeout=30.0,
    default_headers={"X-Tenant": "acme"},
    retry=RetryPolicy(attempts=5, backoff=0.5),
)

Pass http_client=httpx.Client(...) for custom TLS, connection limits, or proxies — see examples/08_custom_httpx_client.py.

Retry defaults: HTTP {429, 502, 503, 504}, gRPC {UNAVAILABLE, DEADLINE_EXCEEDED, RESOURCE_EXHAUSTED}, 3 attempts, exponential backoff + jitter, Retry-After honoured. Tune via RetryPolicy(...) — see examples/07_retry_and_timeout.py.

Errors

TurboOcrError
├── APIConnectionError       # transport-level
│   ├── Timeout
│   ├── NetworkError
│   └── ProtocolError
├── InvalidParameter         # 4xx: bad params / headers / dims
├── EmptyBody                # 4xx: empty body / batch / PDF
├── BackendDisabled          # tables/formulas/autorotate without that backend
│   └── LayoutDisabled       # layout requested with DISABLE_LAYOUT=1
├── ImageDecodeError         # bad bytes / bad base64
├── DimensionsTooLarge       # image / PDF / batch over server limits
├── PoolExhausted            # "Server at capacity" / SERVER_BUSY
├── PdfRenderError           # PDF rasterization failed
├── InferenceTimeout         # per-request deadline elapsed (504)
└── ServerError              # 5xx, no specific code

Server-side exceptions carry .code, .status_code, and .payload. Transport exceptions inherit from APIConnectionError.

Symptom Cause Fix
NetworkError: Connection refused server not running start the docker container (above)
DimensionsTooLarge image > MAX_IMAGE_DIM (default 16384) downscale, or raise the server limit
LayoutDisabled server started with DISABLE_LAYOUT=1 restart without that env var
BackendDisabled tables=True/formulas=True without the backend start with TABLE_BACKEND=slanext / FORMULA_BACKEND=ppformulanet_s
PoolExhausted server queue full retry with backoff, or scale PIPELINE_POOL_SIZE
Timeout per-request timeout hit pass timeout=N, or raise RetryPolicy.attempts

CLI

turbo-ocr ocr page.png --output markdown --tables --formulas
turbo-ocr pdf doc.pdf --dpi 150 --output json
turbo-ocr markdown doc.pdf -o doc.md        # server-side PDF → Markdown
turbo-ocr searchable-pdf doc.pdf -o out.pdf --font-path /path/to/font.ttf
turbo-ocr capabilities
turbo-ocr health --ready

--output accepts json | blocks | text | markdown. Reads TURBO_OCR_BASE_URL and TURBO_OCR_API_KEY from the environment. Run turbo-ocr --help for the full surface.

Logging

import logging
logging.getLogger("turboocr").setLevel(logging.DEBUG)

Emits method path -> status (Xms) [req=<short-id>] per HTTP request. Retry warnings go to turboocr.retry / turboocr.grpc.retry. Searchable-PDF font resolution logs to turboocr.searchable_pdf. Every HTTP request sends a uuid7 X-Request-ID header (gRPC uses x-request-id metadata).

Learn more

  • examples/ — 14 runnable scripts (each runs against the bundled ACME invoice fixture, no server config needed beyond TURBO_OCR_BASE_URL)
  • docs/ — full docs source (MkDocs + mkdocstrings, deployed at https://aiptimizer.github.io/TurboOCR-python/). Preview locally with uv run --extra docs mkdocs serve -f docs/mkdocs.yml
  • Server compatibility: SERVER_API_VERSION_MIN / SERVER_API_VERSION_MAX_EXCLUSIVE document the supported server range; extra="allow" on response models means additive server changes don't break parsing

Testing

pytest -q                                                # offline (respx)
TURBO_OCR_BASE_URL=http://localhost:8000 pytest tests/integration -v
python examples/03_searchable_pdf.py                         # smoke test

License

MIT. See LICENSE.

turboocr.com · ⭐ Star TurboOCR on GitHub
Sponsored by Miruiq — AI-powered data extraction from PDFs and documents — and DiaIQ.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

turboocr-4.0.0a7.tar.gz (252.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

turboocr-4.0.0a7-py3-none-any.whl (68.8 kB view details)

Uploaded Python 3

File details

Details for the file turboocr-4.0.0a7.tar.gz.

File metadata

  • Download URL: turboocr-4.0.0a7.tar.gz
  • Upload date:
  • Size: 252.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for turboocr-4.0.0a7.tar.gz
Algorithm Hash digest
SHA256 6643e60ee863fe15d3095e249eddd9b2e07874d855be795d944e6e9176454fe8
MD5 6090813e5ba0dbf9e6b633b9364faaec
BLAKE2b-256 7a84acda14e48bb44c2f7c89f55bdf5e15b0ceee64104492fefd8bac7df76e4d

See more details on using hashes here.

Provenance

The following attestation bundles were made for turboocr-4.0.0a7.tar.gz:

Publisher: wheels.yml on aiptimizer/TurboOCR

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file turboocr-4.0.0a7-py3-none-any.whl.

File metadata

  • Download URL: turboocr-4.0.0a7-py3-none-any.whl
  • Upload date:
  • Size: 68.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for turboocr-4.0.0a7-py3-none-any.whl
Algorithm Hash digest
SHA256 16d07b1077569c2e6aa8c014c218695a5b856cc714941adb7e0a5cc154acb918
MD5 f0bee48f297fed13ab3c396d48395610
BLAKE2b-256 57802ec5df3cb5972f6d1fd093385bb0d01deab66830b447531ad55940c395ac

See more details on using hashes here.

Provenance

The following attestation bundles were made for turboocr-4.0.0a7-py3-none-any.whl:

Publisher: wheels.yml on aiptimizer/TurboOCR

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

4.0.0a7 This release

2 files

0.3.0

2 files

0.2.0

2 files

0.1.0

2 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