space ocr
GuidesArticlesPricingDocs

The best OCR software for receipts and invoices

A buyer's guide to the best OCR software for receipts and invoices: verifiable accuracy, line items, export, API, webhooks, audit trail, and transparent pricing — proven with a live demo.

Every business that handles paper handles receipts and invoices — and both are miserable to type in by hand. The promise of OCR is obvious: photograph the document, get structured data, move on. The problem is that most OCR tools stop at plausible. They hand you a vendor name and a total and leave you to trust them. For a personal expense log that is fine. For accounts payable, expense reconciliation, or anything that gets audited, "the model said so" is not an answer you can stand behind.

This guide is a buyer's checklist. It walks through what actually separates the best OCR software for receipts and invoices from a flashy demo — verifiable accuracy, line-item extraction, clean exports, a real API with webhooks, an audit trail, and pricing you can predict — and then shows how space-ocr delivers each one, with a live, checkable demo rather than a screenshot.

Proof first: see a real extraction you can check

Before any feature list, here is the thing most vendors won't show you: an extraction where every value points back to the exact spot on the page it came from. Hover any field below — the box on the receipt is where that value was read.

Receipts with extracted-field bounding boxes
Verified fields
KINSHO · 合計 2,045
ライフ · 合計 4,286

Each value with a box carries a verified on-page location — in data.cells[path], that is box + 4-point quad + evidence.match_ratio — on a 0–1000 normalized grid (0,0 top-left → 1000,1000 bottom-right), the same shape the live API returns. Hover a field to trace it back to the pixels it came from.

What to look for in receipt and invoice OCR

Receipts and invoices are the hardest "easy" documents. Layouts vary by vendor, totals hide among subtotals and tax lines, line items wrap, and a phone photo arrives tilted and glare-streaked. A tool that nails one clean PDF can fall apart on the next crumpled thermal receipt. Use these criteria to cut through the marketing.

What mattersWhy it mattersWeak toolStrong tool
Verifiable accuracyA number you can't trace is a number you have to re-key anywayReturns a value, maybe a confidence scoreReturns each value with its source coordinates — an axis-aligned box and a quad that follows the page's tilt
A review list, not just a scoreSomeone has to decide what gets checked firstLeaves you to invent a thresholdReturns the paths that need review with machine-readable reasons, plus a deterministic parse of declared numbers and dates
Line itemsInvoices and receipts are tables, not flat fieldsGrabs the total, drops the rowsExtracts repeating line-item rows with per-cell positions
ExportData has to leave the tool to be usefulCopy-paste or locked-in viewerCSV (Excel/CJK-safe) and JSON over an API
API + webhooksReal volume means automation, not clickingUI-only, or a thin sync endpointREST API with async jobs and signed webhooks
Audit trailReviewers need to see what changedOverwrites OCR output silentlyKeeps the original value beside human edits
Transparent pricingBudgeting hates surprises"Contact us" for everythingA published per-image price and a free tier

The rest of this article takes each row in turn.

Verifiable accuracy beats a confidence score

A confidence score tells you the model feels sure. It doesn't tell you whether total: 2,045 is the number actually printed on the receipt. space-ocr answers a stricter question. The business data comes back in data.values, and every path into it — total, line_items[0].unit_price — addresses an entry in data.cells:

  • box — an axis-aligned rectangle { xmin, ymin, xmax, ymax } on a 0–1000 normalized grid (0,0 = top-left, 1000,1000 = bottom-right). data.image carries the width and height of the page as it was read, and that is what converts those numbers to pixels.
  • quad — four ordered points that follow the document's tilt, always returned alongside box. Nothing is deskewed, so a skewed phone photo still boxes cleanly against the page as it was read.
  • verified — the verdict: false when the cell carries review reasons, true when a check ran and nothing was raised, null when there was nothing to check (a line-item row's union box, for instance).
  • review — either null or { reasons }, naming why the cell wants a second look.
  • evidence — the supporting detail behind the verdict: text_match for the character cross-check itself, match_ratio for how much of the value was located on the page, printed_text for the raw glyphs read at those coordinates.

The work list is data.review.flagged — an array of { path, reasons } whose paths use the same grammar as the cells keys, so a flagged item is a direct lookup. Because the location travels with the value, you can render the box, cite the coordinates, or re-check a flagged field without re-running OCR. That's the foundation of the OCR audit trail — and it's why the demo above isn't a mockup.

✓ Verified

The coordinates aren't taken on the model's word. The language model returns each field's text — and a hint of which word tokens it used — but never the boxes themselves. The engine then character-matches that text against the symbols the vision OCR actually detected on the page, so a box lands on the real pixels those characters were found at, and each value gets a match_ratio for how much of it was located. The model's token hints can be noisy (it sometimes swaps them between repeated rows), so column- and row-consistency checks validate them instead of trusting them blindly. The point isn't that the AI can't be wrong — it's that every value is checked back against the receipt, with a score that says how well it matched.

Line items, not just totals

The single biggest gap in cheap receipt OCR is the table. Anyone can grab a grand total; the value is in the rows — each product, quantity, unit price, and discount. space-ocr extracts these as repeating rows, and every cell keeps its own position, so a wrapped or merged line item is still traceable.

You request them with a field of type: "array" whose children describe one row. For deeper coverage of the row model, see extracting line items from invoices.

line-item field spec
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
  "fields": [
    { "name": "vendor", "type": "string" },
    { "name": "invoice_date", "type": "string" },
    { "name": "total", "type": "string" },
    {
      "name": "line_items",
      "type": "array",
      "children": [
        { "name": "description", "type": "string" },
        { "name": "quantity", "type": "number" },
        { "name": "unit_price", "type": "number" }
      ]
    }
  ]
}

Declare the fields you need — or let autoFields propose them

You pass the extraction schema as a fields array: the items your database actually stores, each with a name and a type, and line items as a type: "array" field whose children describe one row. When you don't yet know what a document carries, send autoFields: true instead and the model proposes a schema — copy the names it returns into a fixed declaration and you have your production call.

Declarations are not an accuracy dial. required, pattern, min/max, enum, near and not_near are never shown to the model, so the extracted value is the same either way. What they add is two things: a rule that is broken puts the value in data.review.flagged with a reason (missing, pattern_mismatch, out_of_range, near_mismatch, near_conflict), and declaring number, integer or date adds data.normalized beside values — the same reading parsed deterministically, so the same page yields the same number every run. near and not_near don't make the model pick the right company name off an invoice that prints two of them; they make a wrong pick visible.

The whole call is one HTTP request — no SDK, no PDF preprocessing (the engine reads raster images: photos and scans).

declare fields, or let autoFields propose them
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# A. Production — declare exactly what your system stores
curl -s https://api.space-ocr.com/ocr/fields \
  -H "Authorization: Bearer $SPACE_OCR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "image": "https://example.com/invoice.jpg",
    "imageType": "url",
    "fields": [
      { "name": "issuer",         "type": "string", "near": ["Tax ID", "Tel"] },
      { "name": "recipient",      "type": "string", "not_near": ["Tax ID", "Tel"] },
      { "name": "invoice_no",     "type": "string", "required": true,
        "pattern": "^[A-Z0-9-]{4,}$" },
      { "name": "invoice_date",   "type": "date" },
      { "name": "payment_method", "type": "string", "enum": ["cash", "credit card", "bank transfer"] },
      { "name": "total",          "type": "number", "required": true, "min": 0 },
      {
        "name": "line_items",
        "type": "array",
        "children": [
          { "name": "description", "type": "string" },
          { "name": "quantity",    "type": "number" },
          { "name": "unit_price",  "type": "number" }
        ]
      }
    ]
  }'

# B. Exploring — no schema yet, let the API propose one
curl -s https://api.space-ocr.com/ocr/fields \
  -H "Authorization: Bearer $SPACE_OCR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "image": "https://example.com/invoice.jpg",
    "imageType": "url",
    "autoFields": true
  }'

Export and the API: where the data goes

Extraction is worthless if the data is trapped. space-ocr gives you two clean exits:

  • CSV — sheets export with a UTF-8 BOM so Excel opens Japanese, Korean, and Chinese text correctly. Array (line-item) rows unfold into sub-rows, and any manual correction overrides the OCR value in the output.
  • JSON over REST — POST /ocr/fields for a single document, POST /upload to push images straight into a sheet, and GET /view to query a stored sheet server-side (where, sort, select, limit) without re-running OCR or paying again.

For automation at volume, /upload is async by default: it returns a job per file and notifies you on completion via webhooks — one signed (HMAC-SHA256) endpoint per space, with events like ocr.completed and ocr.failed. That's the difference between a tool you click and a pipeline that runs itself. The full surface is in the invoice data extraction API guide and the API docs.

Drop a receipt or invoice and structured fields come back — each one positioned on the source image.

Audit trail: what the machine read vs. what a human changed

The best receipt and invoice OCR doesn't just record its own output — it records corrections. When you edit a cell in space-ocr, your value is stored separately from the original OCR value, and an Original tooltip always shows what the engine first read. A reviewer sees the machine value and the human override side by side, which is exactly what an audit asks for.

Click any cell and the matching region lights up on the original image — the fastest way to spot-check a batch.

Transparent, predictable pricing

Verifiable accuracy and an honest price tend to come from the same place. space-ocr is $0.05 per image. There's a free tier of 100 credits a month with no credit card, and Pro at $39/month includes 1,100 credits, unlimited sheets, and 100 GB of storage. No per-field charges, no per-page surcharge, and queries against a stored sheet (GET /view) are free.

How to extract a receipt or invoice

  1. Send the image
    POST the receipt or invoice to /ocr/fields with imageType 'url' or 'base64'. The engine reads raster images — a phone photo or a scan.
  2. Declare the fields
    Pass a fields array naming what you store, with line items as an array field whose children describe one row. If the schema isn't settled yet, send autoFields instead and let the model propose one.
  3. Read the structured result
    data.values holds the business data, data.cells[path] holds box, quad, verified, review and evidence for each value, and data.image gives the page size those coordinates are measured against.
  4. Verify and correct
    Work through data.review.flagged: each item names a path and its reasons (text_mismatch, missing, out_of_range, and so on). Click the cell to highlight the exact region it was read from; edits are stored beside the original value.
  5. Export or query
    Download CSV (UTF-8 BOM, line items unfolded) or query a stored sheet with GET /view using where, sort, and select — no re-OCR, no extra charge.
What is the best OCR software for receipts and invoices?
The best tools do more than read text — they extract line items, export clean CSV and JSON, expose a REST API with webhooks, keep an audit trail of corrections, and price transparently. space-ocr adds verifiable accuracy: every value comes back with its source coordinates in data.cells[path], and data.review.flagged lists the paths worth checking with the reasons attached, so you can trace any number back to the pixels it came from. You declare the fields you need — or send autoFields to have a schema proposed — and it starts free at 100 credits a month.
Can OCR extract line items from a receipt or invoice, not just the total?
Yes. With space-ocr you request line items as a field of type 'array' whose children describe one row (description, quantity, unit price, and so on). Each cell keeps its own entry in data.cells under an indexed path like line_items[0].unit_price, so a wrapped or merged line item is still traceable to its position on the page.
Does receipt and invoice OCR work on phone photos?
Yes. The engine applies EXIF rotation on load so returned coordinates match the page as it was read, and alongside the axis-aligned box it returns a quad — four ordered points that follow the document's tilt. Nothing is deskewed, so a skewed or rotated phone photo still boxes cleanly. Input is raster images: photos and scans.
How much does receipt and invoice OCR cost?
space-ocr is $0.05 per image. There's a free tier of 100 credits a month with no credit card, and a Pro plan at $39/month that includes 1,100 credits, unlimited sheets, and 100 GB of storage. Querying stored data with GET /view is free, and there are no per-field or per-page surcharges.
Can I automate receipt and invoice processing at volume?
Yes. POST /upload pushes images straight into a sheet and runs asynchronously by default, returning a job per file and notifying you on completion via signed (HMAC-SHA256) webhooks such as ocr.completed and ocr.failed. You can also poll GET /jobs/{jobId} as an alternative to webhooks.

Try the best OCR for your own receipts and invoices

Free tier — 100 credits a month, no credit card. Every value comes back with its on-page location.

Related