# PDF Data Extractor: Invoices, W-9s & Bank Statements (`falcon-sol/pdf-data-extractor`) Actor

Turn digital PDFs into JSON: invoices, receipts, POs, W-9s & bank statements. Bank mode: every transaction categorized, pass/fail reconciliation, true revenue, MCA stacking with missed/bounced payments, tamper flags. $0.03/doc, $0.25/statement. Scans free.

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

## Pricing

from $29.00 / 1,000 documents

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

## 📄 PDF Data Extractor: Invoices, W-9s & Bank Statements

**Drop in a PDF URL, get clean JSON back.** Invoices, receipts, purchase orders, W-9s and bank statements, with no templates to build and no OCR guesswork. Bank-statement mode goes further: every transaction categorized, a pass/fail reconciliation, true revenue, and MCA positions with missed and bounced payments, all for **$0.24 per statement**.

### 🎯 Who it's for

- **MCA, small-business and alternative lenders** who need underwriting numbers from bank statements in seconds instead of hand-keying them
- **Loan brokers and ISOs** pre-screening deals before sending them to funders
- **Bookkeepers, AP teams and accountants** turning invoices, receipts and W-9s into rows
- **Developers and AI agents** that need a cheap PDF-to-JSON step behind an API

### 🚀 Why this beats the alternatives

- ✅ **Reconciliation you can trust.** A statement passes only when the printed summary totals *and* every running balance row match the extracted transactions. A mismatch tells you right away that the extraction or the document is off.
- 💰 **True revenue, computed for you.** Internal transfers, loan and MCA funding, cash advances, line-of-credit draws and reversed loan payments are stripped out.
- 🏦 **MCA stacking detection.** Positions are found from a named-lender list *and* from recurring equal debits (four or more), with monthly debt service, holdback, missed weekday pulls and bounced payments.
- 🗂️ **102 transaction categories** in groups such as revenue, payroll, financing in and out, and NSF fees.
- 🕵️ **Tamper flags.** Editing-software metadata, a file modified long after it was created, unusual font counts and many round-dollar deposits are flagged.
- 🧾 **Invoice math checks.** Quantity × unit price, line items vs. subtotal, and subtotal − discount + tax vs. total each come back `pass`, `fail` or `incomplete`.
- 🆓 **Pay only for results.** Failed downloads, non-PDFs, blank W-9s and scanned image-only PDFs cost nothing. Preview mode is free.
- ⚡ **Fast and text-layer native.** It reads the PDF's embedded text directly, with no OCR step to drift on fonts or image quality.

### ⚡ Quick start

1. Paste one or more public PDF URLs into **PDF URLs** (two samples are prefilled).
2. Pick a **Mode**: `extract` for any document, `bank_statement` for underwriting, or `preview` to test for free.
3. Click **Start**. Download the results as JSON, CSV or Excel, or pull them over the API.

```json
{ "mode": "bank_statement", "pdfUrls": ["https://falcondocs.vercel.app/samples/bank-statement.pdf"] }
```

### 📊 Sample output (real run on the prefilled sample statement)

This came from running the actor locally on the sample bank statement above. It is a fictional test document. The excerpt shows the `summary` and the first two of 64 transactions:

```json
{
  "document_type": "bank_statement",
  "reconciliation_status": "pass",
  "summary": {
    "bank_name": "Lakeshore Community Bank",
    "account_holder": "GOODWIN-JIMENEZ",
    "account_last4": "4413",
    "period_start": "2026-02-01",
    "period_end": "2026-02-28",
    "opening_balance": 18000.29,
    "closing_balance": 41549.07,
    "total_deposits": 52591.42,
    "total_withdrawals": 29042.64,
    "transaction_count": 64,
    "true_revenue": 52591.42,
    "average_daily_balance": 33719.34,
    "lowest_daily_balance": 18000.29,
    "negative_balance_days": 0,
    "nsf_count": 0,
    "reconciliation_status": "pass",
    "mca_position_count": 2,
    "mca_missed_payments": 0,
    "mca_bounced_payments": 0,
    "monthly_debt_service": 19272,
    "mca_holdback": 0.37,
    "tamper_flags": [],
    "integrity_flags": []
  },
  "transactions": [
    { "date": "2026-02-02", "description": "SQUARE INC DEPOSIT", "amount": 2873.36, "balance": 20873.65,
      "category": "card_batch_deposit", "category_group": "revenue", "true_revenue": true },
    { "date": "2026-02-02", "description": "ACH DEBIT CREDIBLY", "amount": -249, "balance": 20624.65,
      "category": "mca_payment", "category_group": "financing_out", "true_revenue": false, "funder": "Credibly" }
  ]
}
```

### 💵 Pricing, in plain English

| Mode | What you get | Price |
|---|---|---|
| `extract` | Any digital document, type auto-detected, structured fields | **$0.029 per document** (a bank statement gets the full analysis and is billed as a $0.24 statement) |
| `bank_statement` | All transactions + underwriting summary | **$0.24 per statement** (non-statements in the same batch are billed as $0.029 documents) |
| `preview` | Page 1 only | **Free** |

You're charged only for successful extractions. 100 bank statements cost $25, and 1,000 invoices cost $30. Platform usage is included in the per-event price.

### 💡 Use cases

- MCA and business-loan underwriting: ADB, NSF count, true revenue, existing positions and holdback in one pass
- Spotting stacked MCAs and missed or bounced payments before funding
- Flagging edited or doctored statements for manual review
- Accounts payable automation: invoice, PO and receipt fields (vendor, buyer, ship-to, numbers, dates, totals) plus line items into your ERP or spreadsheet
- Vendor onboarding: pulling W-9 name, business name, tax classification, address and EIN (or SSN last 4) from fillable or flattened digital W-9s
- Feeding structured financial data to AI agents through the Apify API or MCP server

### 🔍 What's in a bank-statement result

- Bank, account holder (read from the page-1 header only, null when it isn't one clear name), last 4 digits, statement period
- Opening and closing balances, deposit and withdrawal totals
- **True revenue** with a breakdown of what was excluded
- Average daily balance, lowest balance, negative-balance days
- NSF, overdraft and returned-item count and fees
- **`reconciliation_status`**: `pass`, `fail` or `incomplete`. It is two checks: (1) the printed summary totals match the extracted transactions, and (2) each printed running balance equals the previous balance plus that row. Statements with no running balance are `incomplete` and can't pass.
- MCA position count, missed and bounced payments, monthly debt service, holdback
- Tamper flags, plus integrity flags when reconciliation fails

For daily weekday MCA pulls, weekends don't count as missed days, but a skipped business day does. A returned debit within five days counts as a bounced payment and is linked to the nearest matching pull. Bounced amounts are removed from `total_paid` and from true revenue.

Layouts covered by the test fixtures: a single amount column with running balance (including multi-page and wrapped descriptions), split withdrawal/deposit columns, DR/CR, deposit/withdrawal sections, right-aligned columns and amount-only statements.

### 🆚 How it compares with Ocrolus, MoneyThumb and Heron

Those platforms OCR scanned documents, and Ocrolus also compares a PDF with aggregator data. This actor doesn't do either. On **digital** statements it returns the underwriting figures those tools are typically used for, pay-as-you-go with no contract.

| | Ocrolus | MoneyThumb | Heron | This actor (digital PDFs) |
|---|---|---|---|---|
| Summary reconciliation | PDF vs. bank data | Totals vs. start/end balance | Start ± amounts = end | Pass/fail on printed summary totals |
| Running balance | Analytics on rows | Reconciled balance chain | High-level check | Per-row pass/fail |
| True revenue | Revenue analytics | Strips non-true credits | Inflows minus transfers and financing | Credits minus transfers, loan/MCA proceeds and reversals |
| MCA | Lender lists | MCA deposits and repeats | Positions, holdback, missed | Lender list + unnamed recurring positions, missed and bounced |
| Scans | OCR | OCR | OCR | Unsupported, and not charged |

### ❓ FAQ

**Does it work on scanned or photographed PDFs?**
No. It reads the PDF's text layer and doesn't run OCR. Scanned files are skipped and you aren't charged. If you can select text in the PDF, it will work.

**Do I need to build a template for each bank?**
No. Layouts are detected automatically.

**How do I know an extraction is right?**
Check `reconciliation_status`. `pass` means every number ties out against the statement's own printed totals and balances. Invoices get the same kind of `checks` object.

**Can I call it from code or an AI agent?**
Yes. Use the Apify API, the JavaScript/Python clients, Zapier/Make or the Apify MCP server. Each PDF becomes one dataset item.

**Is my data stored?**
Results go to your own Apify dataset under your account's retention settings.

**Is this credit, legal or tax advice?**
No. It's automated extraction, so verify the output before relying on it.

***

*Keywords: PDF to JSON, bank statement parser, bank statement analyzer, MCA underwriting, true revenue calculator, invoice OCR alternative, invoice data extraction, receipt parser, W-9 extractor, purchase order extraction, transaction categorization, average daily balance, NSF detection, statement reconciliation.*

***

**Built by [falcon.sol](https://x.com/ygfalcon)**: anon dev shipping pay-per-call data tools and x402 APIs for builders and agents. [X](https://x.com/ygfalcon) · [GitHub](https://github.com/ygfalcon) · [Apify](https://apify.com/falcon-sol)

# Actor input Schema

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

Public links to digital (text-based) PDFs, one per line: invoices, receipts, purchase orders, W-9s or bank statements. Two free samples are prefilled. Scanned image-only PDFs are skipped and never charged.

## `mode` (type: `string`):

Extract: any document, type auto-detected ($0.029; bank statements are billed $0.24). Bank statement: every transaction, pass/fail reconciliation, true revenue, ADB, NSF and MCA positions ($0.24). Preview: page 1 only, free, good for testing.

## `documentType` (type: `string`):

Used in Extract mode. Leave on Auto-detect unless you want to force a document type.

## Actor input object example

```json
{
  "pdfUrls": [
    "https://falcondocs.vercel.app/samples/bank-statement.pdf",
    "https://falcondocs.vercel.app/samples/invoice.pdf"
  ],
  "mode": "extract",
  "documentType": "auto"
}
```

# Actor output Schema

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

One row per PDF. Bank statements include transactions, a summary block, pass/fail reconciliation, true revenue, and MCA positions.

## `summary` (type: `string`):

SUMMARY record with counts of requested, succeeded, failed and charged documents.

# 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://falcondocs.vercel.app/samples/bank-statement.pdf",
        "https://falcondocs.vercel.app/samples/invoice.pdf"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("falcon-sol/pdf-data-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://falcondocs.vercel.app/samples/bank-statement.pdf",
        "https://falcondocs.vercel.app/samples/invoice.pdf",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("falcon-sol/pdf-data-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://falcondocs.vercel.app/samples/bank-statement.pdf",
    "https://falcondocs.vercel.app/samples/invoice.pdf"
  ]
}' |
apify call falcon-sol/pdf-data-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,falcon-sol/pdf-data-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/y5JkO4lJSrmjjB7RK/builds/uihZYExKjeatu5ZEr/openapi.json
