Quickstart
TurboOCR ships as a single container. Pull it, run it on a GPU, POST a document, parse the JSON. This page gets you from zero to a real response in under five minutes. It’s a full document parser — text, layout, tables, and formulas — not just OCR.
1. Requirements
Section titled “1. Requirements”Linux host with an NVIDIA Turing or newer GPU (RTX 20-series / GTX 16-series and up) and driver 595+. Docker with the NVIDIA Container Toolkit so --gpus all works. Plan for ~4 GB VRAM text-only and ~8 GB for the full pipeline (layout + tables + formulas). Every model and language bundle is baked into the image.
2. Run the container
Section titled “2. Run the container”Pull and start :latest from GHCR (pin :v3.1.0 in production). HTTP serves on port 8000, gRPC on 50051. The named volume keeps the compiled TensorRT engines around between restarts.
docker run --gpus all -p 8000:8000 -p 50051:50051 \ -v trt-cache:/home/ocr/.cache/turbo-ocr \ ghcr.io/aiptimizer/turboocr:latestThe first start compiles TensorRT engines from ONNX (about 90 seconds on a 5090, up to an hour on older GPUs — set TRT_OPT_LEVEL=3 to cut that 3–5× with a small speed regression). Every restart after that loads from the trt-cache volume and is instant. Use a named volume, not a host bind-mount — bind-mounting an empty directory shadows the baked-in models.
When the logs report ready, sanity-check the server:
curl http://localhost:8000/health3. Send your first request
Section titled “3. Send your first request”Several endpoints cover most workloads. POST /ocr/raw takes raw image bytes (fastest path); POST /ocr/pdf renders and OCRs every PDF page in parallel. Other routes: POST /ocr (base64 image in JSON), POST /ocr/pixels (zero-decode raw pixel buffer), POST /ocr/batch (many images per request), POST /infer (OCR + layout / reading-order / blocks in one structured response) and POST /ocr/markdown (page → faithful Markdown). See the API Reference for full schemas.
curl -X POST http://localhost:8000/ocr/raw \ --data-binary @document.png \ -H "Content-Type: image/png"curl -X POST http://localhost:8000/ocr/pdf \ --data-binary @document.pdf \ -H "Content-Type: application/pdf"Or call from Python
Section titled “Or call from Python”pip install turboocrfrom turboocr import Client
with Client( base_url="http://localhost:8000", api_key="tocr_live_...",) as client: response = client.recognize_image("invoice.jpg") print(response.results[0].text)4. Read the response
Section titled “4. Read the response”Image endpoints return a flat results array. Each entry has the recognized text, a confidence score in [0, 1], and a 4-point bounding polygon in pixel coordinates (top-left, top-right, bottom-right, bottom-left).
{ "results": [ { "text": "Invoice Total", "confidence": 0.97, "bounding_box": [[42, 10], [210, 10], [210, 38], [42, 38]] }, { "text": "$1,284.00", "confidence": 0.95, "bounding_box": [[220, 10], [320, 10], [320, 38], [220, 38]] } ]}PDF responses wrap one results array per page under pages[], with the page index, render DPI, and pixel dimensions. Append ?layout=1 to either endpoint to also detect document regions; each result then carries a layout_id linking it to the containing region. /infer also accepts ?reading_order=1 (adds a reading-order array, XY-cut over the layout regions) and ?as_blocks=1 (aggregates lines into paragraph blocks); both auto-enable ?layout=1.
If a configured stage produces nothing, the JSON carries text_degraded / table_degraded / formula_degraded (plus a *_warning string) rather than a silent empty result — a partial result is never an unmarked clean 200.
5. Tables, formulas & Markdown
Section titled “5. Tables, formulas & Markdown”Tables and formulas are strictly opt-in: the backend must be loaded at startup and the request must ask for it. All weights are already baked into the image — you just set the backend env var to load the stage (no paths needed). Layout is on by default; each extra stage still only runs when the request asks for it.
# Text + layout is the default. Add backends to load the table and# formula stages, and pick a bigger / other-language OCR tier.docker run --gpus all -p 8000:8000 -p 50051:50051 \ -e TABLE_BACKEND=slanext \ -e FORMULA_BACKEND=ppformulanet_s \ -e OCR_MODEL=medium \ -v trt-cache:/home/ocr/.cache/turbo-ocr \ ghcr.io/aiptimizer/turboocr:latest
# OCR_MODEL: tiny (default) | small | medium | arabic | eslav | korean | thai | greek# FORMULA_BACKEND: ppformulanet_s (Latin/EN) | ppformulanet_plus_m (Chinese-capable) | vlmThen opt in per request — ?tables=1 and ?formulas=1 combine freely and auto-enable layout:
# Full structured parse: layout regions + tables -> HTML + formulas -> LaTeX.# tables=1 / formulas=1 auto-enable layout. The backends must be loaded at# startup (TABLE_BACKEND / FORMULA_BACKEND) or you get a 400, never empties.curl -X POST "http://localhost:8000/ocr/raw?layout=1&tables=1&formulas=1" \ --data-binary @paper.png \ -H "Content-Type: image/png"The response gains a tables array (HTML + cell quads) and/or a formulas array (LaTeX). Asking for a stage the server wasn’t started with is a hard 400 (TABLE_BACKEND_DISABLED / FORMULA_BACKEND_DISABLED), never a silent empty result.
For a whole-page export, POST /ocr/markdown returns faithful Markdown with tables and formulas inline (GPU build; requires layout):
# Page -> faithful Markdown (GPU build). Requires layout; tables + formulas# are always included best-effort, since a faithful export needs them.curl -X POST "http://localhost:8000/ocr/markdown" \ --data-binary @page.png \ -H "Content-Type: image/png"Not sure which stages a running server has loaded? Ask it:
# Discover which stages and routes a running server actually has loaded.curl http://localhost:8000/capabilities6. Try the Web GUI (Studio)
Section titled “6. Try the Web GUI (Studio)”Prefer to point and click? The Studio web UI lets you drop in an image or PDF, run OCR, see the layout overlay and reading order, select recognized text on the page, and download a searchable PDF. Server + GUI start together with one command from the repo root (the demo compose already enables the table and formula stages):
docker compose -f docker-compose.demo.yml up --buildThen open http://localhost:3000. For CPU-only dev, use docker-compose.demo.cpu.yml instead (CPU is dev/CI only — single-digit img/s).