Document OCR toolkit
Run docTR 1.1.0 on your own GPU — detection, recognition, layout and tables in one local pipeline
docTR is Mindee's open-source document OCR library, Apache 2.0, shipped on PyPI as python-doctr. The default fast_base + crnn_vgg16_bn pipeline is 32.1M parameters — under 130MB in fp32. VRAM was never the bottleneck here; throughput is.
DocTR · self-hosted
docTR is a classic two-stage system: a detection model localises every word, then the cropped word images go through a recognition model that decodes them character by character. `ocr_predictor()` defaults to det_arch="fast_base" and reco_arch="crnn_vgg16_bn", with detection fixed at 1024×1024×3 input and recognition at 32×128×3 (official benchmarks use batch 64). Since 1.0.0 the TensorFlow backend is gone entirely — PyTorch only, torch>=2.0,<3.0 — and 1.1.0 raised the minimum Python from 3.10 to 3.11, which is the first thing most upgrades trip over.
1.1.0 is the biggest change this project has shipped. It added LW-DETR layout analysis (lw_detr_s at 15.1M params, mAP@[.5:.95] 66.89; lw_detr_m at 29.5M) covering 11 element classes including titles, body text, tables, headers and footers. It added TableCenterNet table structure recognition (7.1M params, StarNet backbone, Recall 82.31 / Precision 96.01 / F1 88.64) that reconstructs a table into a logical row/column grid you can hand straight to pandas. On top sits a reading-order-aware linearizer with exporters for Markdown, AsciiDoc, HTML and XML, plus the new doctr-cli, vocab whitelisting, ignore_regions layout masking and preserve_original_coords.
One thing worth saying plainly: the performance table in docTR's own docs was measured on an 11th Gen Intel Core i7-11800H @ 2.30GHz — a CPU. So when you see master at 17.6 sec/it for batch 64, or db_resnet50 detection at 1.1 sec per page, that is not a GPU scorecard. On GPU with bf16 the picture changes completely: the ONNX sibling project OnnxTR publishes roughly 0.05 s/page on FUNSD with GPU float16 versus roughly 0.38 s/page on CPU 8-bit. NexGPU runs 1,175 verified rentable nodes and 2,498 GPUs across 51 countries and regions, metered per second with no minimum and no quota request — which is exactly the shape of a bursty batch OCR job.
01 —
The docTR model zoo: detection, recognition, layout, tables
Parameter counts and accuracy from the official zoo; weight footprints computed at 4 bytes per parameter in fp32
| Version | Parameters | VRAM | Context | Notes |
|---|---|---|---|---|
| fast_base (detection, ocr_predictor default) | 16.3M (10.6M after reparameterisation) | fp32 weights ~65MB / bf16 ~33MB | 1024×1024×3 input, B=1 | Replaced db_resnet50 as the default detector in 0.9.0. FUNSD Recall 84.95 / Precision 86.73, CORD Recall 94.39. The speed/accuracy sweet spot — use it unless you have a reason not to. |
| db_resnet50 (detection, differentiable binarization) | 25.4M | fp32 weights ~102MB / bf16 ~51MB | 1024×1024×3 input, B=1 | The long-standing workhorse: FUNSD Recall 83.56 / Precision 86.68, CORD Recall 92.61. Higher ceiling when you have fine-tuning data, and it is the architecture used in the references/detection/train.py examples. For something lighter, db_mobilenet_v3_large is only 4.2M params. |
| crnn_vgg16_bn (recognition, default) | 15.8M | fp32 weights ~63MB / bf16 ~32MB | 32×128×3 input, benchmarked at B=64 | FUNSD exact match 88.21, CORD 95.47, and only 0.6 sec/it at batch 64 even on CPU. 1.0.0 shipped a fresh crnn_vgg16_bn checkpoint. Need cheaper? crnn_mobilenet_v3_small is 2.1M params at 0.05 sec/it. |
| parseq (recognition, permuted autoregressive) | 23.8M | fp32 weights ~95MB / bf16 ~48MB | 32×128×3 input, B=64 | FUNSD 88.53 / CORD 95.56 — the best all-round accuracy in the PyTorch zoo, at 2.2 sec/it on the CPU benchmark. The community multilingual checkpoint Felix92/doctr-torch-parseq-multilingual-v1 uses this architecture; pull it with from_hub(). |
| viptr_tiny (recognition, added in 0.12.0) | 3.2M | fp32 weights ~13MB / bf16 ~7MB | 32×128×3 input, B=64 | Vision Permutable Extractor. FUNSD 86.03 / CORD 93.08 at 0.08 sec/it — built for edge deployment and high-concurrency serving, and only about two points behind CRNN. |
| lw_detr_s + tablecenternet (1.1.0 layout & tables) | 15.1M + 7.1M | fp32 weights ~89MB combined | both 1024×1024×3 input, B=1 | detect_layout=True enables layout analysis, detect_tables=True enables table structure recognition. With everything on you hold four models in VRAM at once — the only docTR configuration that genuinely needs headroom. |
02 —
Picking a GPU for self-hosted docTR
Weights are negligible; the card is chosen by det_bs, page concurrency, and whether you are training a non-Latin vocab
Batch document OCR inference, default fast_base + crnn_vgg16_bn, bf16
RTX 3090 24GB$0.193/GPU-hour
Ampere, compute capability 8.0+, so the officially recommended .cuda().bfloat16() path works natively; 24GB lets you push det_bs and reco_bs freely — and it is the cheapest card on our list.
Online serving / high throughput with all four models on (detection + recognition + layout + tables)
RTX 4090 24GB$0.540/GPU-hour
lw_detr_s and tablecenternet both consume 1024×1024 inputs, so compute becomes the bottleneck before memory does; Ada gets the most out of the torch.compile support added in 0.11.0, which lowers cost per page.
Fine-tuning detection on your own document layouts at input_size 1024, raising the default batch_size=2
RTX A6000 48GB$0.817/GPU-hour
references/detection/train.py defaults to batch_size 2 precisely because 1024×1024 segmentation feature maps are memory-hungry; 48GB gets you to batch 8–16, and with --amp it converges overnight.
Training a Simplified Chinese recognition model from scratch, --vocab simplified_chinese, multi-GPU torchrun
A100 SXM4 80GB$1.088/GPU-hour
The Simplified Chinese vocab runs to twenty-thousand-plus characters, and output-layer plus decoder memory scales directly with vocab size; 80GB with NCCL across cards is the only comfortable setup, and a node here takes up to 14 GPUs.
03 —
Empty instance to Markdown output in four steps
A PyTorch image boots ready; the whole thing takes under ten minutes
- 01
Spin up an instance and install python-doctr
Pick an RTX 3090 24GB at console.nexgpu.net and use a prebuilt PyTorch image (there are 2,000+, including vLLM, ComfyUI, Whisper ASR and plain Ubuntu CLI). Note that 1.1.0 requires Python ≥ 3.11 and torch >=2.0,<3.0. The official Docker images are built on CUDA 12.2, so your host CUDA must be 12.2 or newer.
pip install "python-doctr[viz,html]" - 02
Turn a PDF into table-aware Markdown with one command
The doctr-cli added in 1.1.0 needs no Python at all. --detect_layout runs LW-DETR layout analysis, --detect_tables runs TableCenterNet, and output is linearised in reading order; --format covers json / txt / md / xml / html, and --ignore_regions can mask out picture regions entirely.
doctr-cli --input_path doc.pdf --detect_layout --detect_tables --device cuda:0 --output doc.md - 03
Move the Python API onto the GPU and enable half precision
docTR only supports half-precision inference on GPU devices. Use bfloat16() on Ampere and newer (compute capability 8.0+ — 3090, 4090, A6000, A100, H100) and fall back to half() on older cards. Swapping the recognition branch is a one-word change: parseq for accuracy, viptr_tiny for speed. det_bs and reco_bs are the two knobs that saturate the card.
from doctr.models import ocr_predictor predictor = ocr_predictor("fast_base", "parseq", pretrained=True, detect_tables=True).cuda().bfloat16() - 04
For non-Latin scripts, you must train the recognition branch yourself
This is docTR's biggest surprise: --vocab in references/recognition/train.py defaults to "french", and every official pretrained recognition checkpoint uses a Latin character set. No amount of tuning will make it emit a Chinese character — the output layer has no such class. Train with simplified_chinese or traditional_chinese, or start from from_hub("Felix92/doctr-torch-parseq-multilingual-v1") and fine-tune. The detection branch usually transfers as-is.
torchrun --nproc_per_node=4 references/recognition/train.py crnn_mobilenet_v3_large --vocab simplified_chinese --train_path /data/train --val_path /data/val -b 64 --amp --backend nccl
What 100,000 scanned pages actually costs
Take a realistic workload: 100,000 PDF pages through the default fast_base + crnn_vgg16_bn pipeline in bf16. OnnxTR reports about 0.05 s/page on FUNSD with GPU float16; being conservative for the PyTorch backend at 0.1 s/page, that is 100,000 × 0.1 s = 10,000 seconds ≈ 2.78 hours. On an RTX 4090 24GB: 2.78 × $0.540 ≈ $1.50. On an RTX 3090 24GB, even assuming it runs 40% slower at 3.9 hours: 3.9 × $0.193 ≈ $0.75 — the GPU bill for a hundred thousand pages costs less than a coffee. Training is a different order of magnitude: a Simplified Chinese crnn_mobilenet_v3_large from scratch at, say, 40 hours on one A100 SXM4 80GB is 40 × $1.088 = $43.52; run it across 4 GPUs with torchrun and finish in 10 hours for 4 × 10 × $1.088 = $43.52 — identical, because we bill per GPU-hour, so parallelism costs nothing extra and just removes three quarters of the wall-clock. Storage is separate at a $0.414/GB-month median (50GB of source PDFs ≈ $20.70/month) with egress at a $0.0081/GB median. Compute billing stops the moment the instance stops; storage runs until you destroy it. No minimum, no setup fee, no quota request.
04 —
FAQ
How much VRAM does DocTR need? Is an 8GB card enough?
Can docTR read Chinese? Why is my Chinese document coming out as garbage?
How does docTR compare to PaddleOCR or EasyOCR?
Can I still use the TensorFlow backend? What breaks when upgrading to 1.1.0?
Does docTR run on CPU? Why does the official speed table look so slow?
How do I turn tables in a scan into structured data?
Start building on NexGPU
Enterprise R&D team or solo developer — either way, your first job can be running in minutes.
Sign up to browse live network pricing. No payment method required.
