This is a gateway for the dots.OCR model. Preprocesses PDFs into images and submits to backend dots.OCR endpoint in a concurrent and resilient way.
Currently only outputs Markdown.
A lightweight, resilient API gateway for the dots.OCR model. It preprocesses PDFs into images, performs concurrent OCR requests against a backend service, and returns Markdown text.
This project is intended as a scalable microservice wrapper around a vision-capable LLM OCR backend such as a self-hosted dots.ocr inference server. (GitHub)
-
PDF → Markdown OCR API
- Convert whole PDF documents to clean Markdown text.
-
Concurrent page processing
- Processes multiple pages in parallel for throughput.
-
Resilient inference
- Retries OCR on problematic pages with multiple sampling strategies.
-
No disk I/O
- All uploads and intermediate data stay in memory.
-
Stateless
- Easy to deploy in containers, HPC nodes, or serverless contexts.
git clone https://github.com/ui-insight/dots_ocr_api.git
cd dots_ocr_apipython3 -m venv venv
source venv/bin/activatepip install -r requirements.txtThis service uses environment variables to configure backend connectivity and processing behavior.
-
BACKEND_ENDPOINTURL of your OCR backend (e.g., a vision LLM inference server). -
BACKEND_MODELThe model identifier to send with each OCR request.
Example:
export BACKEND_ENDPOINT="http://my-llm-backend:8000"
export BACKEND_MODEL="DotsOCR"| Variable | Default | Description |
|---|---|---|
OCR_DPI |
100 |
DPI for PDF rendering |
OCR_TIMEOUT |
900 |
Timeout (s) per page OCR call |
OCR_PAGE_WORKERS |
8 |
Parallel worker count |
MAX_PDF_MB |
100 |
Max upload size (MB) |
MAX_PAGES |
500 |
Max pages allowed |
Returns basic service configuration and status.
curl http://localhost:5010/healthSample JSON
{
"ok": true,
"endpoint": "http://my-llm-backend:8000",
"model": "DotsOCR",
"dpi": 100,
"timeout": 900,
"workers": 8
}OCR a PDF and return Markdown.
Send a PDF as either:
- Multipart form upload (
file=@document.pdf) - Raw PDF bytes in body
Example:
curl -X POST http://localhost:5010/dotsocr \
-F "file=@document.pdf" \
-H "Accept: text/markdown"| Param | Default | Description |
|---|---|---|
dpi |
100 | Rendering DPI |
timeout |
900 | Inference timeout per page |
workers |
8 | Parallelism level |
The response is returned as text/markdown with extracted text merged from all pages. (GitHub)
- Pages processed in parallel using threads.
- If a page OCR attempt returns very short or repetitive output, it’s retried with different sampling configs.
- Pages that continue to fail are omitted, but the rest of the document still returns valid text.
This prioritizes usable text over strict completion. (e.g., if one page fails, the rest still succeed)
python app.pyBy default it listens on:
http://0.0.0.0:5010
Deploy behind a reverse proxy or container orchestrator as needed.
You can containerize this service by writing a simple Dockerfile:
FROM python:3.10-slim
WORKDIR /app
COPY . .
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 5010
CMD ["python", "app.py"]Build and run:
docker build -t dotsocr-api .
docker run -e BACKEND_ENDPOINT="http://..." -e BACKEND_MODEL="DotsOCR" -p 5010:5010 dotsocr-apiimport requests
url = "http://localhost:5010/dotsocr"
with open("document.pdf","rb") as f:
r = requests.post(url, files={"file": f})
print(r.text)This project is licensed under Apache-2.0. (GitHub)
Contributions welcome! Please open issues or pull requests to:
- Improve reliability
- Add auth / rate limit support
- Add tests and CI workflows
Luke Sheneman, sheneman@uidaho.edu