On your server
Self-hosted OCR API: installation guide for a GPU server
After this page the OCR API runs on your own Linux server with an NVIDIA card and has read your first page. From then on your pages stay on the server, on-premise and offline once the models are fetched, so no outside service sees them. A start check tells you which pipelines your card carries. The model weights come from pinned, SHA-256-checked sources; ocr-fetch-models.sh --list prints every source before anything is downloaded.
The whole install, as run in the steps below (the file name and folder come with the package):
sha256sum -c ocr-software-2026.11.11-352765c-linux-amd64.tar.gz.sha256 && tar -xzf ocr-software-2026.11.11-352765c-linux-amd64.tar.gz && cd ocr-software-2026.11.11-352765c-linux-amd64
sudo ./install.sh
sudo /opt/ocr/current/deploy/ocr-fetch-models.sh
sudo /opt/ocr/current/install.sh --start --pipeline scan-ctc@2
sudo /opt/ocr/bin/ocrctl key new -id mykey -paid -keys /etc/ocr/keys.txt
Then the first call.
Download the OCR software package and verify its SHA-256
| File | ocr-software-2026.11.11-352765c-linux-amd64.tar.gz |
| Version | 2026.11.11-352765c |
| Size | 14.7 MB |
| SHA-256 | ff9bdfb2812ba2c5ed038ecf2a7a09f07aaaed60f9e47ab9d77db278b7648ea7 |
| Checksum file | ocr-software-2026.11.11-352765c-linux-amd64.tar.gz.sha256 |
| Terms | EULA |
Download ocr-software-2026.11.11-352765c-linux-amd64.tar.gz
The release contains the API service ocrd, the key tool ocrctl, the installer with update and rollback, and the pipelines, from everyday scans to tables and the hardest pages. The model weights are fetched in step 4. Release notes ยท Everything in the package
Put the checksum file in the same folder as the package and check the package before you unpack it: sha256sum -c ocr-software-2026.11.11-352765c-linux-amd64.tar.gz.sha256. The installer checks every file inside once more. Licence terms: EULA. Private use and tests are free; for productive use in a company, or to run it for others, ask for a contract.
Which NVIDIA GPU does the OCR server need? Cards per pipeline
The start check tells you which pipelines your card carries: the fast reading pipelines from compute capability 7.5 (GTX 16xx, RTX 20xx) with 8,192 MiB of video memory free, and the language-model pipeline from 8.0 (RTX 30 series and newer) with 17,920 MiB free. A GTX 10xx (compute capability 6.1) is below the limit of every pipeline.
The language-model pipeline reads a page with a language model and with a character OCR engine and compares both. That needs video memory: an NVIDIA card with compute capability 8.0 or higher (RTX 30 series and newer), driver 580 or newer and at least 17.5 GiB (17,920 MiB) of video memory free. Measured on an NVIDIA RTX PRO 4500 Blackwell with 32 GB.
Find your own numbers first. Run this on the server:
nvidia-smi --query-gpu=name,compute_cap,memory.free,driver_version --format=csv
The columns are the card, its compute capability, the video memory that is free right now, and the driver. Free means free: a desktop session or another program holding the card lowers it. Compare with the table; the start command in step 5 reads the same numbers from the card and compares them with the limits of the pipeline.
| Card | Compute capability | What it carries |
|---|---|---|
| GTX 10xx (Pascal), including Titan X | 6.1 | No pipeline: the start check stops below 7.5, and the engines of the language-model pipeline need 7.5 or higher |
| GTX 16xx, RTX 20xx (Turing), including Titan RTX | 7.5 | The fast pipelines with 8,192 MiB free |
| RTX 30xx, 40xx, 50xx with less than 17.5 GiB free, for example RTX 3050, 3060, 3070, 4060, 4080, 5080 | 8.6 and up | The fast pipelines with 8,192 MiB free |
| RTX 30xx, 40xx, 50xx with 17.5 GiB or more free, for example RTX 3090, 4090, 5090 | 8.6 and up | All pipelines pass the check; for the language-model pipeline the start command works out the memory of the language model from the free memory |
| Datacenter cards (A10, A100, L4, L40S, H100) | 8.0 and up | Decided by the same numbers |
| NVIDIA RTX PRO 4500 Blackwell | 12.0 | The language-model pipeline with 32 GB, test card |
The start command in step 5 checks compute capability, driver and free memory and stops with exit code 4 if one is too low; it says what your card does carry. Above the limit it works out how much memory the language model gets from the memory that is free on your card (the rule is in the file deploy/gpu-vlm.conf of the package) and prints "same memory size as the card we measured (only the RTX PRO 4500 Blackwell has run)" for every card within three percent of the test card (32,623 MiB), "not verified on this card size, it may fail to start or run out of memory" for the others. Only the first card (GPU 0) is checked and used, also on a server with several: the services run with CUDA_DEVICE_ORDER=PCI_BUS_ID and CUDA_VISIBLE_DEVICES=0, so the card that is checked is the card that is used.
The language-model process held 16,544 MiB on the 32 GB card, set to use half of it (own measurement, test GPU, 6 Nov 2026).
If the start fails or the language model runs out of memory, the command stops with exit code 6 and names the service; each service gets up to eleven minutes to start, then the API up to ten more, so this can take longer than eleven minutes. A failed start stops everything it began, ocrd too, so the services show as inactive and the reason is in the log. Read why with
journalctl -u 'ocr*' --since '30 minutes ago' --no-pager(the log of all services of this package), close other programs that hold the card, and start again; the second start stops the package services first and measures again. If it fails again, send the card, the line "model sidecar: ..." and the log through the contact page.
The fast reading pipeline used 3.5 GB of video memory with one worker and 14.1 GB with four on the test card (own measurement, 5 Nov 2026); the start check asks for 8,192 MiB free.
GPU too small: what the start check reports
- Before it installs anything, install.sh asks nvidia-smi -L. If no card answers, it stops with exit code 4 and starts nothing.
- The start command (step 5) reads the compute capability, the free memory and the driver from nvidia-smi and compares them with the limits of the pipeline (file deploy/gpu-grenzen.tsv of the package). If one is below, it stops with exit code 4, names the number and the cards it does carry, and starts nothing. It also stops if the memory left for the language model is below its least. Only GPU 0 is read and used, also for foreign processes. A second start stops the services of this package that are running (only those, never a foreign process), waits five seconds and measures again (if the card has not freed its memory by then, the check stops with exit code 4 and "does not fit"); if the check then fails, the workers of this package no longer run; ocrd keeps running.
- Before each service starts, a check stops it with a clear line in the log if another program already computes on GPU 0. It kills nothing; stop that program first.
- If a page does not fit into memory anyway, it comes back as failed with an error code. It is never returned empty and never guessed. A failed page costs nothing.
- Then start a pipeline from the table that your card passes (--pipeline), or use a bigger card. A card below compute capability 7.5, such as every GTX 10xx, passes none.
Driver and CUDA: NVIDIA driver 580 or newer with the open kernel module.
System requirements of the on-premise OCR server
| Need | What |
|---|---|
| System | Linux x86_64 with systemd, root. Built for Ubuntu 22.04 (Ubuntu 24.04: see below); NVIDIA driver 580 or newer. |
| GPU | NVIDIA with driver 580 or newer. Which card: see the table above. |
| Main memory | Peak per page, measured on CPU: up to 3.6 GiB. The service unit limits itself to 8 GiB. |
| Disk | Room for the model weights and the Python packages under /var/lib/ocr. Step 4 prints the weights (about 3,587 MiB, 3.5 GiB) and says the Python environments need several GiB more. |
| Packages | python3.10 with venv and pip (not in the standard repositories of Ubuntu 24.04; install.sh checks it first and stops with exit code 7 if it is missing), poppler-utils, libgl1, libglib2.0-0, libgomp1, curl. |
| Internet | For step 4 only. |
On Ubuntu 24.04, step 3 (install.sh) stops with exit code 7 and installs nothing until python3.10 is installed, because step 4 needs it and 24.04 does not ship it; the message names the command. That command uses the deadsnakes package source (PPA). After it, install.sh runs through.
Install the OCR server and read your first page
Run these in the folder with the package. Steps 1 to 3 can be repeated without harm. Step 4 can be repeated after it has finished; if it was cut off, run it again with --rebuild (see step 4). Step 5 stops the services of this package that are running before it measures the card, so a running service is interrupted. Step 6 makes a new key every time.
Check.
sha256sum -c ocr-software-2026.11.11-352765c-linux-amd64.tar.gz.sha256Must print OK. If not, download again.
Unpack.
tar -xzf ocr-software-2026.11.11-352765c-linux-amd64.tar.gzand
cd ocr-software-2026.11.11-352765c-linux-amd64Install.
sudo ./install.shFirst checks that python3.10 with the venv module exists; if not, it stops with exit code 7 and installs nothing (see "Install errors"). Then checks every file and installs. It listens on 127.0.0.1 only. On the first install add --listen 0.0.0.0:8080 to open it to your network; later runs keep your config.yaml and say so, then edit
listen:in /etc/ocr/config.yaml.Fetch the models.
sudo /opt/ocr/current/deploy/ocr-fetch-models.shShows source, licence and size, then asks "Fetch this now? [y/N]" each time you run it; without a terminal add --yes. The only step that downloads, several GiB of models. It fetches all environments of the package, also those the language-model pipeline does not need. If GPU 0 is below the limit of the language-model pipeline, this step prints a warning before it asks; it does not stop. Step 5 checks the card before it looks at the models. Check your card against the table above first: the warning points to it. With --list it only shows, and needs no root. If step 4 was cut off and the next run says "venv differs", an environment was left half built: run
sudo /opt/ocr/current/deploy/ocr-fetch-models.sh --rebuild(the script prints this hint itself and exits with code 4). A finished step 4 is skipped on a second run.
Start.
sudo /opt/ocr/current/install.sh --start --pipeline scan-ctc@2Starts only the services this pipeline needs, after the card check above. Needs the models and a GPU; only GPU 0 is used. If the card is too small it starts nothing. If you start again, it first stops the services of this package that are running, and only those. It waits until the API answers; each service gets up to eleven minutes to start, then the API up to ten more, before an abort comes. If it stops earlier, it prints the reason and an exit code; the table under "Install errors" explains them. If a service does not start (exit code 6) or the language model runs out of memory on a 24 GB card, the start stops everything it began, so the services show as inactive; read why with
journalctl -u 'ocr*' --since '30 minutes ago' --no-pagerTo see what runs after a good start:
systemctl status 'ocr*' --no-pagerMake a key.
sudo /opt/ocr/bin/ocrctl key new -id mykey -paid -keys /etc/ocr/keys.txtThe key is printed once. Keep it.
Read a page. The calls below go to your own server,
http://127.0.0.1:8080. The hosted API athttps://api.ocr-software.comtakes the same calls.
export OCR_KEY=<your key>
curl -s -X POST "http://127.0.0.1:8080/v1/jobs?pipeline=scan-ctc@2&formats=json" \
-H "Authorization: Bearer $OCR_KEY" --data-binary @page.pdf
The answer names a job_id. Ask for the job until its state is done, then fetch the result (pipeline choice, reading the result, errors and retries: API guide):
JOB_ID=<the job_id from the answer>
curl -s "http://127.0.0.1:8080/v1/jobs/$JOB_ID" -H "Authorization: Bearer $OCR_KEY"
curl -s "http://127.0.0.1:8080/v1/jobs/$JOB_ID/result?format=json" -H "Authorization: Bearer $OCR_KEY" -o result.json
Each word in result.json carries its text, a confidence and where it came from. The format is described on the page about JSON output.
Step 3 installs to /opt/ocr/releases/<version>; the installer creates the configuration and the key file only if they are missing, so a second run never overwrites yours. Step 5 stops at the first problem and names the service. Check the API with
curl -s http://127.0.0.1:8080/healthz
Third-party software and model weights of the OCR package
| Part | Where from | Licence | Size |
|---|---|---|---|
The API service ocrd, the key tool ocrctl, the pipelines, the worker code, the install script | In the package | The licence terms (see above); Go libraries under their own licences, listed in NOTICE | 14.7 MB |
| Python packages of the workers | You fetch them (step 4): pypi.org, download.pytorch.org, paddlepaddle.org.cn; pinned versions, every file hash-checked | Their own, shown by step 4 | Several GiB |
| Model weights: text, layout, tables, language model | You fetch them (step 4): huggingface.co, pinned by commit, every file checked against a SHA-256 list | Apache-2.0, MIT or CDLA-Permissive-2.0 per model, shown by step 4 | Shown by step 4 |
| NVIDIA driver, CUDA parts | You install them | NVIDIA | Not part of the package |
| poppler (PDF to image) | You install it from your distribution | GPL, from your distribution | Not part of the package |
Before anything is downloaded, ocr-fetch-models.sh --list prints every source, licence, size and checksum, without root and without a connection.
The full list of licences is on the page third-party software; the licence texts of the Go libraries are in the file NOTICE inside the package.
Not in the package: model weights, NVIDIA parts, poppler and your keys. After the model step the package processes everything locally: on-premise and offline, with no mail and no alerts sent. Your documents stay on your server, inside your network.
OCR speed: seconds per page per pipeline
How fast each pipeline reads, in seconds per page and pages per second (multiply by 3,600 for pages per hour), with the run behind each figure, is in the speed table on the pipelines page. Your card and your pages will differ; measure a sample of your own.
More pages at a time make the language-model pipeline faster. Set it with scheduler.vlm_slots in the server config (default 8, at most 64). Read one page at a time, the output is the same after every restart; use a fast reading pipeline for identical bytes at any load.
Update and roll back the OCR server
- Update. Unpack the new package and run
sudo ./install.shin it. The old release stays asprevious(the last three are kept); your configuration, keys and models are kept. Run the first call of the API guide again afterwards as the acceptance. The database is at/var/lib/ocr/ocr.db;ocrctl backupcopies it online andocrctl restoreputs it back withocrdstopped. Keep that copy,/etc/ocrand the key file on another machine. - Roll back.
sudo /opt/ocr/current/install.sh --rollbackswitches to the previous release in one command. If the services do not start with a new release, the installer goes back by itself.
Install troubleshooting: errors and exit codes
Its exit code tells you where to look; 0 means it worked.
| Exit code | Meaning | What to do |
|---|---|---|
| 2 | Wrong option, for example a bad --listen; or step 4 without a terminal | Use HOST:PORT with a port from 1 to 65535. ./install.sh --help shows the options. Step 4 without a terminal stops with "ERROR: not a terminal: add --yes to confirm the download": add --yes. |
| 3 | Wrong machine, not root, or no systemd | Run as root on Linux x86_64 with systemd. Step 4 not run as root says "ERROR: run as root (sudo): the files are fetched as user ocr into /var/lib/ocr". Git Bash, MSYS and Cygwin are refused, because the release switch needs real symbolic links. |
| 4 | No GPU answers, the models are missing, or step 4 failed | Check nvidia-smi -L shows a card, then run step 4 (ocr-fetch-models.sh) before --start. A card that is too small is covered under "Which NVIDIA GPU does the OCR server need?". If the model step stops with "venv differs", run it again with --rebuild (step 4). Step 4 before step 3 says "ERROR: user ocr does not exist: run install.sh first". If the download fails, step 4 ends with "ERROR: fetching the models failed (see above). Nothing runs on half-fetched models: fix the cause and run this again."; the cause is in the lines above it. |
| 5 | A file of the package is missing or differs | Download it again and compare the .sha256 file. A file added or removed also stops the install. If the message says fetch/pins/models.tsv is missing, the package is not intact: download it again and check it (step 1). Step 4 says "ERROR: fetch/pins is incomplete: this is not an intact package": the same remedy. |
| 6 | A service did not start, or the install failed | Read journalctl -u 'ocr*' --since '30 minutes ago' --no-pager; the message names the unit that failed. On a 24 GB card the language model may not fit: close other programs that use the card and run step 5 again. A failed start stops everything it began, ocrd too, so the units show as inactive and the log has the reason. A version is never overwritten: the same version with other content is refused. |
| 7 | python3.10 with the venv module is missing (install.sh, before anything is installed) | Install it with the command in the message, then run install.sh again. The message reads, on stderr: "ERROR: python3.10 with the venv module is missing, but the model step (fetch/pins/models.tsv) builds its environments with it. Detected: <your system>. Install it, then run this again: <command>. Nothing was installed." On Ubuntu 22.04 the command is sudo apt install python3.10 python3.10-venv. On Ubuntu 24.04 it is sudo apt install software-properties-common && sudo add-apt-repository ppa:deadsnakes/ppa && sudo apt update && sudo apt install python3.10 python3.10-venv; the deadsnakes PPA is not tested. Other systems: your package manager (Debian and Ubuntu: python3.10 and python3.10-venv). |
The API does not answer. Check
curl -s http://127.0.0.1:8080/healthzthe first start can take ten minutes.
No access from other machines. Default is localhost only, plain HTTP: put TLS or a firewall in front.
A new release does not start. The installer switches back by itself.
Not solved. Send the exit code and the log through the contact page.
OCR release notes: what changed in each version
| Version | What changed | Your action |
|---|---|---|
| 2026.11.11-352765c | First version listed on this page. | Install as described above. |
Each later package adds a row here: version, what changed, and whether you need to do anything. An update keeps your configuration, keys and fetched models; if a version needs more than sudo ./install.sh, the row says so.
Support, managed server and custom OCR pipeline
Running it for third parties, support, maintenance or a fixed update promise come with a contract. Prices are on the pricing page.
Production use, high volume or your own server?
Private use and tests are free. For a company in production, a server of your own or a pipeline built on your pages, send the kind of page and the volume, and get a written offer, or a clear no when the fit is not there.