# Invoice and Receipt Parser: totals, tax, dates, items (`examsens.ai/invoice-receipt-fields`) Actor

Reads invoices and receipts from image and PDF links and returns the vendor, invoice number, invoice and due dates, currency, subtotal, tax, total and line items as fields. OCR runs inside the actor; no outside service or key.

- **URL**: https://apify.com/examsens.ai/invoice-receipt-fields.md
- **Developed by:** [Ed Rayyis](https://apify.com/examsens.ai) (community)
- **Categories:** AI
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.60 / 1,000 document processeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Invoice and Receipt Parser: totals, tax, dates, items

Send it links to invoices and receipts, as photos, scans or PDF files, and get the numbers back as fields: who issued it, the invoice number, the invoice and due dates, the currency, the subtotal, the tax, the total and the line items. Each document becomes one row you can drop into a spreadsheet or an accounting import.

OCR runs inside the actor with RapidOCR and the PP-OCRv6 models, released under the Apache 2.0 license \[1] \[2]. Nothing is sent to an outside service and there's no key to supply. PDF pages that already carry text are read directly, without OCR.

### How well it reads

Fields come from rules: label words such as "Total", "Subtotal", "Tax", "VAT", "Invoice No" or "Due Date" and the amounts printed beside them. There's no language model guessing at the page, so a field is either found on the document or left empty.

On 20 printed shop receipts from the public ICDAR 2019 SROIE receipt set \[3], none of which were used while the rules were written, the actor got the total right on 17 of the 19 receipts whose answer key gives a total, the date on 19 of 20, and the vendor name exactly on 14 of 20. Two of the six vendor misses were close: one kept the company number after the name, and one carried an OCR slip, a capital I for a lowercase l. In the other four the actor returned a different line from the top of the receipt, such as a tagline or the street address.

Four more documents were checked by hand: a typed US invoice image, the same invoice saved as a scanned PDF, a PDF invoice with a text layer and a Swiss restaurant bill. On all four the invoice number, dates, currency, subtotal, tax, total and line items came out right. The vendor was right on three; the Swiss bill prints its name over two lines and the actor returned only the first.

Receipts with faded print, labels the OCR can't read, or totals printed on a different line from their label are where it misses. Check `totalsConsistent` and the `text` field when a number matters.

### What you get for each document

- `documentType`: invoice, receipt or unknown
- `vendorName` and `invoiceNumber` (also receipt, bill or document numbers)
- `invoiceDate` and `dueDate` as YYYY-MM-DD, with `invoiceDateText` and `dueDateText` as printed
- `currency` as a code such as USD, EUR, CHF or MYR, from the symbol or code on the document
- `subtotal`, `tax`, `taxRatePercent` and `total`, with `totalLabel`, the line the total came from
- `totalsConsistent`: true when subtotal plus tax equals the total, false when it doesn't, empty when the document has no subtotal
- `lineItems`: `description`, `amount`, and `unitPrice` and `quantity` where the row prints them, plus `lineItemCount`
- `fileType`, `pageCount`, `pagesRead`, `readMethod` (ocr or text-layer) and `ocrConfidence`
- `text`: everything read, one printed line per line (on by default)

When a receipt has a rounding adjustment, the total is the rounded amount the customer paid.

### Dates

A date like 03/04/2026 can be read two ways. Automatic mode looks for any date on the document that can only be read one way, such as 26/02/2019, and uses that order for the whole document. When there's none, US dollar documents are read month first and everything else day first. You can also fix the order yourself in the input.

### Input

- Invoice or receipt URLs (required): PNG, JPEG, WebP, BMP, GIF, TIFF or PDF, up to 25 MB by default
- Date order: automatic, day first or month first
- Maximum pages per document, 5 by default and up to 20
- Include the full text, on by default
- PDF render resolution, 200 DPI by default, for scanned PDF pages
- Minimum OCR confidence, 50% by default

### Output

The dataset has one row per document. A link that fails to download, answers with an error status, or isn't a PDF or image gets a row with `ok` false and the reason in `error`, and the run moves on. An `OUTPUT` record in the key value store gives documents processed, documents failed and whether the run stopped at your spending limit.

### Pricing

Pay per event: one event per document processed, whatever its page count. Documents that fail aren't charged. Before each document is read, the run checks that the maximum charge you set can still pay for it, and stops there when it can't, so every document row in the dataset is a paid one.

### Support

Questions and problems: the Issues tab on this page.

### References

\[1] GitHub, RapidAI/RapidOCR, LICENSE and python/MODEL_LICENSES.md. https://github.com/RapidAI/RapidOCR
\[2] Hugging Face, PaddlePaddle/PP-OCRv6_small_rec_onnx model card, license tag. https://huggingface.co/PaddlePaddle/PP-OCRv6_small_rec_onnx
\[3] GitHub, zzzDavid/ICDAR-2019-SROIE, receipt images and answer keys. https://github.com/zzzDavid/ICDAR-2019-SROIE

# Actor input Schema

## `fileUrls` (type: `array`):

Direct links to invoices or receipts as images (PNG, JPEG, WebP, BMP, GIF, TIFF) or PDF files. Each link is one document. Use files you own or are allowed to process.

## `dateOrder` (type: `string`):

How to read a date such as 03/04/2026. Automatic uses any date on the document that can only be read one way; failing that, month first for US dollar documents and day first for the rest.

## `maxPagesPerFile` (type: `integer`):

Pages read from each PDF or multi page TIFF. The price is per document, whatever its page count.

## `includeText` (type: `boolean`):

Add the text read from the document, one printed line per line, so you can check the fields or parse more of it yourself.

## `pdfDpi` (type: `integer`):

Resolution used to turn scanned PDF pages into images before OCR. PDF pages that already carry text are read directly.

## `minConfidencePercent` (type: `integer`):

Drop OCR text lines whose confidence is below this percentage.

## `maxFileSizeMb` (type: `integer`):

Skip files larger than this, with an error item.

## Actor input object example

```json
{
  "fileUrls": [
    {
      "url": "https://templates.invoicehome.com/invoice-template-us-neat-750px.png"
    },
    {
      "url": "https://slicedinvoices.com/pdf/wordpress-pdf-invoice-plugin-sample.pdf"
    }
  ],
  "dateOrder": "auto",
  "maxPagesPerFile": 5,
  "includeText": true,
  "pdfDpi": 200,
  "minConfidencePercent": 50,
  "maxFileSizeMb": 25
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "fileUrls": [
        {
            "url": "https://templates.invoicehome.com/invoice-template-us-neat-750px.png"
        },
        {
            "url": "https://slicedinvoices.com/pdf/wordpress-pdf-invoice-plugin-sample.pdf"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("examsens.ai/invoice-receipt-fields").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "fileUrls": [
        { "url": "https://templates.invoicehome.com/invoice-template-us-neat-750px.png" },
        { "url": "https://slicedinvoices.com/pdf/wordpress-pdf-invoice-plugin-sample.pdf" },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("examsens.ai/invoice-receipt-fields").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "fileUrls": [
    {
      "url": "https://templates.invoicehome.com/invoice-template-us-neat-750px.png"
    },
    {
      "url": "https://slicedinvoices.com/pdf/wordpress-pdf-invoice-plugin-sample.pdf"
    }
  ]
}' |
apify call examsens.ai/invoice-receipt-fields --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,examsens.ai/invoice-receipt-fields"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/UIYXOAZxdcnKVwcNO/builds/lbg58ceYbaZ1p9iO1/openapi.json
