tesseract://¶
OCR via the Tesseract open-source engine. Producer-only — feed it image / PDF bytes, receive extracted text on the body.
Two backends, picked by mode=:
| Mode | What runs | When to use |
|---|---|---|
cli (default) |
Local tesseract binary, shelled out via os/exec. Pure-Go from Helix's side. |
Single host, you control the install. Fastest setup — apt install tesseract-ocr / brew install tesseract and you're done. |
http |
A Tesseract HTTP wrapper (hertzg/tesseract-server, otiai10/ocrserver, or any compatible variant). | Shared OCR service, sidecar deployment, or you don't want the tesseract binary on the Helix host. Auto-detects JSON / plaintext responses. |
No CGO. We deliberately did NOT pick otiai10/gosseract/v2 (the
canonical CGO binding) — it would force every Helix build to link
libtesseract, break CGO_ENABLED=0 static binaries, and complicate
cross-compilation. The CLI gets the same engine with none of the
build-system drag, and Tesseract's CLI has been stable since 3.x.
Companion: pkg/component/tesseract.
URI shape¶
tesseract://?<param>=<value>… # CLI mode
tesseract://<host>:<port>?<param>=<value>… # HTTP mode (inferred)
tesseract://?mode=http&endpoint=http://ocr:8884 # HTTP mode (explicit)
When a host segment is present and mode= is not set, the component
infers mode=http and uses the host as the endpoint. Pure-param form
(tesseract://?lang=eng) stays in cli mode.
When to use this vs. rag-ingest¶
| Need | Use |
|---|---|
| OCR inside a RAG pipeline (ingest → chunk → embed → store) | rag-ingest reader: ocr backend: tesseract |
| Call tesseract as a tool from an agent | tesseract:// |
| OCR an image mid-route (route is NOT a RAG pipeline) | tesseract:// |
| Need PDF page-splitting / parallel page OCR | rag-ingest reader: ocr backend: tesseract page_split: true |
Body shape¶
Request:
[]byte→ uploaded (HTTP mode) or written to a temp file (CLI mode).string→ treated identically to[]byte.io.Reader→ consumed.
Helix sniffs magic bytes to pick a file extension (.png, .jpg,
.pdf, .gif, .webp, .bmp, .tiff) so the Tesseract CLI's
leptonica loader picks the right decoder.
Response:
- Body: extracted text as a
string. HelixTesseractModeheader:cliorhttp.HelixTesseractLangheader: the language(s) used.
Parameters¶
Connection¶
| Param | Type | Default | Description |
|---|---|---|---|
mode |
enum | cli |
cli or http. |
endpoint |
string | from URI host (HTTP mode only) | Tesseract HTTP service base URL. |
path |
string | /tesseract (HTTP mode) |
HTTP path appended to endpoint. Use /ocr for otiai10/ocrserver, /tesseract for hertzg. |
apiKey |
string | — | Bearer token sent as Authorization header (HTTP mode only). |
timeout |
duration | 2m |
Per-call timeout. Accepts Go duration (30s, 2m) or bare seconds. |
Tesseract knobs¶
Apply to both modes.
| Param | Type | Default | Description |
|---|---|---|---|
lang |
string | eng |
-l value. Combine with +: eng+fra+deu. Requires the matching tessdata language files installed. |
psm |
integer | 3 |
Page Segmentation Mode (--psm). 0=OSD only, 3=fully automatic, 6=uniform block, 7=single line, 11=sparse text, 12=sparse with OSD, 13=raw line. See tesseract --help-psm. |
oem |
integer | (unset) | OCR Engine Mode (--oem). 0=legacy, 1=LSTM only (recommended), 2=legacy+LSTM, 3=default. Omit to use the binary's default. |
CLI-mode only¶
| Param | Type | Default | Description |
|---|---|---|---|
binary |
string | tesseract (via $PATH) |
Explicit path to the tesseract binary. |
tessdataPrefix |
string | (inherits) | Overrides $TESSDATA_PREFIX. Useful when language data lives outside the system default (e.g. a CI cache mount). |
HTTP response auto-detection¶
mode=http reads the response and tries known JSON shapes before
falling back to plaintext:
| Shape | Server |
|---|---|
{"data":{"stdout":"text",...}} |
hertzg/tesseract-server |
{"result":"text"} |
otiai10/ocrserver |
{"text":"..."} / {"stdout":"..."} / {"markdown":"..."} / {"content":"..."} |
other common wrappers |
| Raw body | plain-text response |
You don't configure this — it just works. The same decoder powers the
rag-ingest backend: tesseract path so JSON envelopes never leak into
embeddings.
Examples¶
CLI mode — OCR a PNG from disk¶
workflows:
- id: ocr-incoming-image
trigger:
uri: file:///var/scans?move=.done&include=.*\.png
steps:
- target: tesseract://?lang=eng&psm=6
- target: log://ocr-result
The file:// trigger streams each PNG body into the tesseract step;
the local binary OCRs it; the resulting text lands in the log.
HTTP mode — point at a tesseract-server sidecar¶
workflows:
- id: ocr-via-http
trigger:
uri: http-server://0.0.0.0:8080/ocr
steps:
- target: tesseract://ocr-sidecar:8884?lang=eng+deu
Posts every uploaded body to the sidecar. The component auto-detects the response JSON shape.
RAG ingest — full pipeline¶
workflows:
- id: ingest-scanned-pdfs
trigger:
uri: file:///var/intake/pdfs?include=.*\.pdf
steps:
- rag-ingest:
reader: ocr
backend: tesseract
endpoint: http://ocr-sidecar:8884
language: eng
page_split: true # pdfcpu splits → parallel OCR
concurrency: 4
- rag-chunk:
strategy: recursive
chunk_size: 800
- rag-embed:
provider: openai
model: text-embedding-3-small
- rag-store:
backend: qdrant
url: ${QDRANT_URL}
collection: scanned-pdfs
When endpoint: is omitted the rag-ingest path drops to the local CLI
exactly like the standalone component does — no service needed.
Failure modes¶
| Error | Cause | Fix |
|---|---|---|
tesseract not found on PATH — install Tesseract OCR (apt-get install tesseract-ocr / brew install tesseract) |
mode=cli and the tesseract binary isn't reachable. |
Install it, or set binary= to an explicit path. |
tesseract cli: exit status 1 (stderr: Error opening data file …) |
Language data missing for lang=. |
Install the matching tessdata package (tesseract-ocr-deu, etc.) or set tessdataPrefix=. |
status 500: ... (HTTP mode) |
Service returned a non-200. The body snippet is preserved in the error. | Check the service logs; verify multipart file field is what the wrapper expects. |
psm N out of range (0-13) |
Invalid psm= value. |
Use 0-13 per tesseract --help-psm. |
unknown parameter "x" |
Typo in a URI param. | The describable surface above lists every accepted key. |
Performance notes¶
- CLI mode forks per call. Fine for hundreds of pages/min; for
thousands/min run a
mode=httpsidecar so the model stays warm. - PDF inputs. Tesseract opens PDFs via leptonica (one page at a
time). For multi-page PDFs the
rag-ingestpath withpage_split: trueparallelises better than a single tesseract call. - Language combinations cost time.
eng+fra+deuis roughly 1.5–2× slower thaneng. Only list languages you actually need.