Skip to content
OCR Service

OCR Service

UniPDF does not recognize text in images itself. The ocr package is an HTTP client: it packs an image into a multipart form, posts it to a URL you configure, and returns the response body unchanged. The recognition happens in whatever service sits at that URL, so nothing on these pages works until you have one running.

That also means UniPDF never parses the result. ExtractText returns []byte straight from the response, and decoding it is your job, whether the service sent back JSON, plain text or hOCR.

What you need

A service that accepts a file upload as multipart form data and returns recognized text. The examples were written against unidoc/ocrserver, which wraps Tesseract and answers on http://localhost:8080/file:

git clone https://github.com/unidoc/ocrserver.git
cd ocrserver
docker-compose up

The OCR service needs no UniDoc credentials of its own, and the ocr package makes no license calls. The metered key the examples load in init matters only for the reader and creator work around it, such as pulling images out of a PDF or writing a new one.

Configuring the client

Everything goes through ocr.OCROptions. Only Url has no default:

FieldDefaultNotes
UrlnoneRequired. ExtractText returns an error if it is empty.
MethodPOST
FileFieldNamefileThe multipart field the image is attached to.
HeadersemptyApplied after the multipart Content-Type, so a Content-Type here would override it.
FormFieldsemptyExtra text fields in the same form. This is how you ask for hOCR.
TimeoutSeconds30Ignored when Client is set.
MaxRetries0Retries fire on any non-2xx response, not just transport errors.
ClientnilSupply your own *http.Client for proxies, TLS config or connection pooling.
RequestModifiernilCalled just before the request is sent, for signing or auth headers.

The field is Url, not URL.

Two entry points

NewHTTPOCRService returns the low-level *HTTPOCRService. NewOCRHTTPClient wraps the same service in a *Client that adds convenience methods. Both answer ExtractText(ctx, reader, filename), so single-image code looks identical either way.

CallOnly on *ClientWhat it adds
ExtractTextnoReader plus filename.
ExtractTextFromFileyesOpens and closes the file for you.
ExtractTextFromImageyesTakes a *model.Image and posts image.Data as image.jpg.
BatchProcessyesConcurrent, over []*model.Image.
BatchProcessFilesyesConcurrent, over file paths.
CallEndpointnoPlain request to the configured URL with no multipart body, for a health check or a status endpoint.

ExtractTextFromImage posts model.Image.Data as-is under the name image.jpg. model.Image holds decoded samples rather than an encoded file, so most services will reject it. The reconstruct example works around this by calling ToGoImage and encoding to JPEG itself, which is the pattern to copy.

Output format

Plain text is the default, because it is whatever the service returns by default. Asking for hOCR is a FormFields entry, and the key depends on the service. ocrserver uses format:

opts.FormFields = map[string]string{"format": "hocr"}

hOCR is HTML with the geometry encoded in title attributes: bounding boxes, baseline, x_size for text height, and x_wconf for per-word confidence. Reach for it when you need to know where a word sits on the page. Stay with plain text when you only need the words.

Where to look

GuideCovers
Extract text from a single imageThe minimal request, and the options that shape it.
Get hOCR outputAsking for hOCR, and reading the geometry back out.
Batch processing of imagesConcurrency, and the parallel error slice.
Reconstruct PDF from hOCRImages out of a scanned PDF, hOCR in, positioned text out.
Last updated on