Skip to main content
Glama

📄 free-ocr-api

Free, self-hosted OCR & document data extraction API

Turn PDFs, scans and phone photos of invoices, receipts, bank statements, payslips and forms into clean JSON, CSV or Excel. No API keys, no cloud, no per-page fees.

CI License: MIT Python Docker MCP

Quick start · API · Data-entry autopilot · Templates · CLI · MCP


Why?

Data entry means re-typing invoice numbers, totals and line items from PDFs into spreadsheets, and it eats hours every week. Paid document AI services charge per page and need your documents to leave your network.

free-ocr-api does the boring part on your own machine:

docker run -p 8000:8000 ghcr.io/ethos6/free-ocr-api   # or: docker compose up
curl -F file=@invoice.pdf localhost:8000/v1/extract
{
  "doc_type": "invoice",
  "fields": {
    "invoice_number": "INV-2026-0042",
    "invoice_date": "2026-03-15",
    "due_date": "2026-04-14",
    "vendor_name": "Northwind Supplies Ltd",
    "customer": "Blue Harbor Cafe, 14 Mill Street, Bath BA1 1AA",
    "currency": "GBP",
    "subtotal": 288.0,
    "tax": 57.6,
    "total": 345.6,
    "vendor_tax_id": "GB123456789",
    "iban": "GB82 WEST 1234 5698 7654 32",
    "totals_check": "ok"
  },
  "line_items": [
    {"description": "Espresso beans 1kg", "quantity": 4.0, "unit_price": 18.5, "amount": 74.0},
    {"description": "Oat milk carton", "quantity": 12.0, "unit_price": 2.25, "amount": 27.0}
  ]
}

Related MCP server: document-intelligence-mcp

✨ Features

🔍 OCR that just works

Reads digital PDFs instantly from the text layer and OCRs scans and photos automatically. Supports Tesseract (100+ languages) or RapidOCR (pure pip install).

🧾 8 document types, auto-detected

Invoices, receipts, bank statements, purchase orders, payslips, resumes/CVs, ID documents and generic forms

📊 Line items & tables

Description, quantity, unit price and amount for every row. Bank statement transactions come out with debit, credit and balance. Ruled PDF tables are extracted cell by cell.

✅ Totals check

Verifies subtotal + tax + shipping − discount = total, so bad reads get flagged

🏷️ Entities

Emails, phones, URLs, dates (normalised to ISO), amounts, IBAN (checksum-validated), SWIFT, EU VAT, US EIN, India GSTIN/PAN/IFSC/UPI, and card numbers (masked)

🧩 Custom templates

Describe your own fields in a 10-line YAML file, with label or regex matching, and have them applied automatically by keyword

📥 Excel / CSV / JSON / Markdown

Batch export gives one row per document plus a Line items sheet. Ready for Excel, Google Sheets and accounting tools.

🤖 Data-entry autopilot

freeocr watch ./inbox keeps a spreadsheet up to date as files land in a folder

✏️ Review & correct UI

Drag-and-drop web app where you click any value to fix it, and the exports include your edits

🕵️ PII redaction

Masks emails, phones, cards, IBANs, tax IDs, SSN and Aadhaar before you store or share text

🧠 Optional model assist

Point it at any local model server (Ollama, LM Studio, vLLM, LocalAI…) to fill custom fields the rules missed. It's off by default.

🔌 MCP server

Lets AI assistants and editors read your local documents with freeocr mcp

🔒 Private by design

Runs fully offline with no telemetry and optional API-key auth. Nothing leaves your machine.

🌍 Smart dates

Works out whether a document writes 03/04 as day-first or month-first from its other dates and its currency

🚀 Quick start

docker run -d -p 8000:8000 ghcr.io/ethos6/free-ocr-api:latest

Or build it yourself:

git clone https://github.com/Ethos6/free-ocr-api && cd free-ocr-api
docker compose up -d
open http://localhost:8000          # web UI
open http://localhost:8000/docs     # interactive API docs

Add OCR languages at build time: docker build --build-arg OCR_LANGS="hin deu fra spa ara chi-sim jpn" .

pip

# 1) an OCR engine (only needed for scans/photos - digital PDFs work without one)
sudo apt install tesseract-ocr        # macOS: brew install tesseract  · Windows: choco install tesseract
#    ...or skip Tesseract and use the pure-Python engine:
pip install rapidocr onnxruntime

# 2) free-ocr-api
pip install "free-ocr-api @ git+https://github.com/Ethos6/free-ocr-api"
# with the pure-Python OCR engine bundled:
pip install "free-ocr-api[rapidocr] @ git+https://github.com/Ethos6/free-ocr-api"
freeocr serve                          # http://127.0.0.1:8000

Try it on the bundled sample documents (fictional companies):

freeocr extract examples/samples/ -o samples.xlsx

🌐 REST API

Method

Endpoint

What it does

POST

/v1/extract

One document → fields, line items, tables, entities (format=json|csv|xlsx|md|txt)

POST

/v1/batch

Many documents → one spreadsheet (default xlsx) or JSON

POST

/v1/ocr

Plain text, page by page

POST

/v1/redact

OCR + mask personal data

POST

/v1/export/{fmt}

Convert (edited) JSON results to xlsx/csv/md

POST

/v1/templates/test

Try a YAML/JSON template against a file before saving it

GET

/v1/templates

List loaded templates

GET

/v1/info · /health

Engines, doc types, formats, status

/v1/extract form fields: file (required), doc_type (auto), lang (eng, hin, deu, eng+fra…), template, fields (extra field names), use_llm, redact, pages (1-3,5), dayfirst (auto/true/false), force_ocr, include_text, include_pages, format.

# Excel file for a whole folder of invoices
curl -F files=@jan.pdf -F files=@feb.pdf -F files=@receipt.jpg \
     localhost:8000/v1/batch -o invoices.xlsx

# CSV of the line items/fields of one document
curl -F file=@invoice.pdf -F format=csv localhost:8000/v1/extract

# Hindi + English scanned document, pages 1-2 only
curl -F file=@scan.pdf -F lang=hin+eng -F pages=1-2 localhost:8000/v1/extract
import httpx

with open("invoice.pdf", "rb") as f:
    doc = httpx.post("http://localhost:8000/v1/extract", files={"file": f}).json()

print(doc["fields"]["total"], doc["fields"]["due_date"])
for item in doc["line_items"]:
    print(item["description"], item["amount"])

Or skip the server and use it as a library:

from freeocr import extract_document

doc = extract_document(open("receipt.jpg", "rb").read(), "receipt.jpg")
const form = new FormData();
form.append("file", fileInput.files[0]);
const doc = await (await fetch("http://localhost:8000/v1/extract", { method: "POST", body: form })).json();
console.log(doc.fields, doc.line_items);

🤖 Data-entry autopilot (watch a folder)

Drop files into a folder (scanner output, email attachments, a synced Drive or Dropbox folder) and a spreadsheet updates itself:

freeocr watch ./inbox -o invoices.xlsx --done ./processed
#   + acme-0042.pdf: invoice · 16 fields
#   + IMG_2231.jpg: receipt · 12 fields
#   updated invoices.xlsx (2 rows)
  • Each file is processed once, tracked by its SHA-256, and survives restarts.

  • --once processes what's there and exits, which suits cron jobs.

  • Output can be .xlsx, .csv or .json.

🧩 Custom templates

The built-in extractors cover common layouts. For your own forms, or for documents from one vendor, create templates/my-form.yaml:

name: acme-order-form
match: ["ACME Corp"]              # auto-apply when this text appears
fields:
  order_id:      {label: ["Order #", "Order No"], type: id, required: true}
  order_date:    {label: "Order Date", type: date}
  customer_code: {regex: "CUST-(\\d{5})"}
  total:         {label: ["Grand Total", "Total"], type: amount}
  express:       {regex: "EXPRESS DELIVERY", type: bool}

Types: string, id, amount, number, int, date, email, phone, percent, bool. You can test a template without saving it:

curl -F file=@order.pdf -F template="$(cat templates/my-form.yaml)" localhost:8000/v1/templates/test

🧠 Optional: local model assist

The rules are fast and deterministic. For odd layouts you can ask a local model to fill specific fields the rules didn't find. Any server with a /v1/chat/completions endpoint works:

export FREEOCR_LLM_URL=http://localhost:11434/v1      # e.g. Ollama
export FREEOCR_LLM_MODEL=<any-model-you-have-pulled>
curl -F file=@contract.pdf -F fields="party_a,party_b,start_date,notice_period" -F use_llm=true \
     localhost:8000/v1/extract

⌨️ CLI

freeocr extract invoice.pdf                       # JSON to stdout
freeocr extract ./scans -r -o all.xlsx            # whole folder (recursive) → Excel
freeocr extract statement.pdf --type bank_statement -f csv
freeocr extract id.jpg --redact                   # mask personal data
freeocr ocr scan.png --lang deu                   # plain text
freeocr watch ./inbox -o out.xlsx                 # autopilot
freeocr serve --host 0.0.0.0 --port 8000          # API + web UI
freeocr mcp                                       # MCP server (stdio)
freeocr info                                      # engines, types, templates

🔌 MCP server

Add this to any MCP-compatible client (desktop assistants, IDEs, agent frameworks):

{
  "mcpServers": {
    "freeocr": { "command": "freeocr", "args": ["mcp"] }
  }
}

Tools: extract_document, ocr_document, and extract_folder (which saves a spreadsheet). Then ask your assistant something like "put every invoice in ~/Downloads into invoices.xlsx".

⚙️ Configuration

Variable

Default

FREEOCR_API_KEY

–

Require X-API-Key header

FREEOCR_MAX_MB

25

Max upload size

FREEOCR_MAX_FILES

100

Max files per batch

FREEOCR_ENGINE

auto

tesseract or rapidocr

FREEOCR_DPI

300

Render resolution for scanned PDFs

FREEOCR_MAX_PAGES

200

Page limit per document

FREEOCR_DAYFIRST

auto

Force true/false date order

FREEOCR_TEMPLATES

templates

Template folder(s)

FREEOCR_CORS

*

Allowed origins

FREEOCR_LLM_URL / _MODEL / _KEY

–

Optional local model assist

WORKERS

1 (2 in Docker)

API worker processes

🆚 Compared to paid document APIs

free-ocr-api

Typical cloud document AI

Price

Free, MIT

Per page / per call

Documents leave your network

Never

Yes

Works offline / air-gapped

Yes

No

Invoice + receipt + bank statement

✅

✅ (often separate models)

Excel export & folder autopilot

✅

Build it yourself

Custom fields

YAML templates

Training / paid tier

Handwriting, very complex layouts

Limited

Better

Be realistic: rule-based extraction works best on typed, reasonably clean documents. Check field_confidence, warnings and totals_check before you trust a number, and use templates or model assist for unusual layouts.

🛣️ Roadmap

  • Utility bills, shipping labels and insurance claim extractors

  • Multi-language field labels (DE/FR/ES/HI keywords)

  • Searchable-PDF output (text layer over scans)

  • Webhooks and an email-inbox (IMAP) watcher

  • Table-structure detection for scanned (image) tables

Ideas and PRs are welcome. See CONTRIBUTING.md.


If this saved you some typing, please ⭐ star the repo. It helps other people find it.

MIT © Ethos6

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables extraction of structured data from documents like invoices, receipts, and bank statements using local Vision AI (Ollama) or cloud providers (Gemini), with data stored in a local SQLite database.
    2 npm
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Local document intelligence for AI agents — extract text, detect tables, read metadata, analyze structure, search keywords, and detect language from PDF and DOCX files. No cloud API required, no API key needed.
    MIT
  • F
    license
    B
    quality
    A
    maintenance
    Enables local, offline document extraction and manipulation—PDF first but also HTML, DOCX, XLSX, PPTX, EML, EPUB, Markdown, and plain text—through tools for probing, locating, extracting, converting, assembling, OCR, protecting, and redacting documents, with nothing leaving the machine.
    7
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI agents to inspect, read, and make targeted edits to local Office documents, PDFs, images, archives, media and other files, writing changes into new reviewable copies while leaving originals intact and returning JSON receipts. It also screens supported files for hidden content and privacy risks, running entirely offline as a local server over stdio.
    Apache 2.0