# PDF Invoice Extractor (`sootesting/pdf-invoice-extractor`) Actor

Turn PDF invoices into structured data from URLs. Extract vendor, invoice number, dates, line items, tax/VAT, subtotal, total, and currency. Uses pdfplumber for reliable text extraction — no upload, no API key, no manual entry. Built for accountants, bookkeepers, and expense managers.

- **URL**: https://apify.com/sootesting/pdf-invoice-extractor.md
- **Developed by:** [soot](https://apify.com/sootesting) (community)
- **Categories:** Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 result items

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## PDF Invoice Extractor

**Turn PDF invoices into structured data — paste a URL, get clean JSON. No upload, no API key, no manual entry.**

Built for **accountants, bookkeepers, and expense managers** who need reliable invoice data extraction at scale. Drop in one or a hundred PDF URLs and get back vendor, invoice number, dates, line items, tax, totals, and currency — all in a clean, analysis-ready JSON dataset.

### Why this Actor?

| Feature | PDF Invoice Extractor | Competitors |
|---------|----------------------|-------------|
| **Input method** | Direct URL (no upload needed) | Often requires file upload or base64 |
| **Processing engine** | pdfplumber (reliable, fast text extraction) | pdfjs, OCR-only, or external AI APIs |
| **Batch support** | ✅ Multiple URLs per run | Often single-document only |
| **Line items** | ✅ Structured table extraction | Often raw text only |
| **Tax/VAT** | ✅ Separate tax field extraction | Mixed with total |
| **Confidence score** | ✅ Per-document extraction confidence | Rarely provided |
| **Pricing** | $0.05 start + $0.001/result | $0.01–$0.10 per document |

**The URL input advantage:** No need to download, store, or upload PDFs. If you can link to an invoice, this Actor can parse it. Works with public URLs from supplier portals, email attachments, cloud storage — anywhere a PDF is accessible via HTTP(S).

### What it does

1. **Downloads** PDF from the URL(s) you provide
2. **Extracts text** using pdfplumber (handles native PDFs, not just scanned images)
3. **Parses structured fields:** vendor, invoice number, date, subtotal, total, tax/VAT, currency
4. **Extracts line items** from PDF tables with description and amount
5. **Scores confidence** so you know which results need manual review
6. **Outputs** a clean JSON dataset ready for CSV export, accounting software, or further processing

### Features

- 🔗 **URL input only** — no file upload, no storage needed
- 📊 **Structured line items** — table rows with description + amount
- 🧾 **Tax/VAT extraction** — separate tax field, not buried in total
- 🌍 **Multi-currency** — detects USD, EUR, GBP and explicit currency codes
- 📈 **Confidence scoring** — per-document extraction quality indicator
- ⚡ **Batch processing** — hundreds of URLs in a single run
- 🔒 **No external APIs** — runs entirely within Apify infrastructure
- 💰 **Pay-per-event** — $0.05 start fee + $0.001 per result item

### Input

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `pdfUrls` | array\[string] | Yes\* | — | Direct URLs to PDF invoices or receipts. |
| `pdfUrl` | string | Yes\* | — | Single PDF URL (convenience alternative to `pdfUrls`). |
| `includeRawText` | boolean | No | `false` | Include the full extracted text in the output (useful for debugging). |

\*Provide either `pdfUrls` (array) or `pdfUrl` (single string).

#### Input example

```json
{
  "pdfUrls": [
    "https://example.com/inv-2024-001.pdf",
    "https://example.com/inv-2024-002.pdf",
    "https://example.com/receipt-march.pdf"
  ],
  "includeRawText": false
}
```

### Output

Each result contains:

| Field | Type | Description |
|-------|------|-------------|
| `vendor` | string | Vendor/supplier name (first line or detected from "From"/"Seller" patterns) |
| `invoiceNumber` | string | Invoice or bill number |
| `date` | string | Invoice date (ISO or common formats) |
| `subtotal` | string | Net amount before tax |
| `total` | string | Total amount due |
| `tax` | string | Tax/VAT/GST amount |
| `currency` | string | Detected currency (USD, EUR, GBP, or explicit code) |
| `lineItems` | array | Structured line items with description, raw cells, and amount |
| `confidence` | number | Extraction confidence 0.0–1.0 (based on key fields found) |
| `pages` | integer | Number of PDF pages |
| `sourceUrl` | string | Original PDF URL |
| `characterCount` | integer | Total extracted characters |
| `rawText` | string | Full extracted text (only if `includeRawText: true`) |

#### Output example

```json
{
  "vendor": "Acme Supplies Inc.",
  "invoiceNumber": "INV-2024-001",
  "date": "2024-03-15",
  "subtotal": "1,250.00",
  "total": "1,375.00",
  "tax": "125.00",
  "currency": "USD",
  "lineItems": [
    {
      "description": "Widget A — 10 units",
      "raw": ["Widget A", "10", "50.00", "500.00"],
      "amount": "$500.00"
    },
    {
      "description": "Widget B — 5 units",
      "raw": ["Widget B", "5", "150.00", "750.00"],
      "amount": "$750.00"
    }
  ],
  "confidence": 1.0,
  "pages": 1,
  "sourceUrl": "https://example.com/inv-2024-001.pdf",
  "characterCount": 842
}
```

### Usage

#### Via Apify CLI

```bash
apify call sootesting/pdf-invoice-extractor --input '{
  "pdfUrls": ["https://example.com/invoice.pdf"]
}'
```

#### Via cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/sootesting~pdf-invoice-extractor/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"pdfUrls": ["https://example.com/invoice.pdf"]}'
```

#### Via Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")
run = client.actor("sootesting/pdf-invoice-extractor").call(run_input={
    "pdfUrls": ["https://example.com/invoice.pdf"]
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

### Pricing

| Event | Price | Description |
|-------|-------|-------------|
| Actor start | $0.05 | Charged once per run (1 GB memory) |
| Per result | $0.001 | Charged per successfully extracted document |

**Example:** Processing 100 invoices costs $0.05 + $0.10 = **$0.15 total**.

### Limitations

- Requires **publicly accessible** PDF URLs (no authentication-protected links)
- Works best with **text-based PDFs** (not scanned images — for scanned documents, use an OCR-based extractor)
- Very complex multi-page tables may have incomplete line item extraction
- Confidence score < 0.5 suggests manual review recommended

### Related

- [Invoice & Receipt Data Extractor](https://apify.com/formnexa/invoice-receipt-data-extractor) — OCR-based, supports images
- [Receipt & Invoice OCR](https://apify.com/eastwoodapps/receipt-invoice-extractor) — PDF + image to JSON/CSV
- [PDF Table Extractor](https://apify.com/ely_source/pdf-table-extractor) — table-focused extraction

***

*Built with pdfplumber for reliable text extraction. No external AI APIs, no per-token costs.*

# Actor input Schema

## `pdfUrls` (type: `array`):

Direct URLs to PDF invoices or receipts to parse. All URLs must be publicly accessible.

## `pdfUrl` (type: `string`):

Convenience alternative to pdfUrls — provide a single PDF URL.

## `includeRawText` (type: `boolean`):

Include the full extracted text in output (useful for debugging).

## Actor input object example

```json
{
  "pdfUrls": [
    "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
  ],
  "includeRawText": false
}
```

# Actor output Schema

## `vendor` (type: `string`):

No description

## `invoiceNumber` (type: `string`):

No description

## `date` (type: `string`):

No description

## `subtotal` (type: `string`):

No description

## `total` (type: `string`):

No description

## `tax` (type: `string`):

No description

## `currency` (type: `string`):

No description

## `lineItems` (type: `string`):

No description

## `confidence` (type: `string`):

No description

## `pages` (type: `string`):

No description

## `sourceUrl` (type: `string`):

No description

## `characterCount` (type: `string`):

No description

## `rawText` (type: `string`):

No description

## `error` (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 = {
    "pdfUrls": [
        "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
    ],
    "includeRawText": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("sootesting/pdf-invoice-extractor").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 = {
    "pdfUrls": ["https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"],
    "includeRawText": False,
}

# Run the Actor and wait for it to finish
run = client.actor("sootesting/pdf-invoice-extractor").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 '{
  "pdfUrls": [
    "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
  ],
  "includeRawText": false
}' |
apify call sootesting/pdf-invoice-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sootesting/pdf-invoice-extractor"
        }
    }
}

```

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/6qpx5fHBsgRo2nMjU/builds/3Dw7bit1IGCK6sPLt/openapi.json
