# Bank Statement PDF to CSV/JSON Converter (`businessquik/bank-statement-extractor`) Actor

Bank statement PDF to clean CSV/JSON with balance-verified accuracy: every statement is reconciled against its own opening and closing balances. No file retention. Built for bookkeepers, lenders, and AI agents.

- **URL**: https://apify.com/businessquik/bank-statement-extractor.md
- **Developed by:** [Carlos Garcia](https://apify.com/businessquik) (community)
- **Categories:** Automation, AI, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $100.00 / 1,000 statement reconcileds

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/platform/actors/running/actors-in-store#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

## Bank Statement PDF to CSV/JSON Converter

Turn bank statement PDFs into clean, reconciled transaction data — dates, descriptions, signed amounts, and running balances — ready for QuickBooks, Xero, Excel, or your data pipeline.

### Why this one

**Balance-validated extraction.** Most PDF extractors hand you rows and hope. This Actor recomputes the running balance across every transaction and checks it against the statement's own opening and closing balances:

- `RECONCILED` — opening + all transactions = closing. The extraction is provably complete and correct.
- `EXTRACTED_WITH_MISMATCHES` — rows extracted, but the math doesn't close; `mismatchRows` tells you exactly which rows to review.
- `EXTRACTED_UNVERIFIED` — the statement doesn't print balances, so no check was possible.

You only pay the reconciliation fee when the check passes.

**Your files are never stored.** Statements are processed in memory and discarded. The only output is the transaction dataset in your own account. No file retention, no third-party calls.

### Input

| Field | Description |
|---|---|
| `pdfUrls` | Direct links to one or more statement PDFs (signed S3/Drive/Dropbox links work) |
| `pdfBase64` | Alternative: a single PDF inline as base64 — convenient from agents/API |
| `outputFormat` | `csv-ready` (one row per transaction, default) or `json` (nested per statement) |
| `dateFormat` | `iso`, `us`, or `eu` |
| `strictReconciliation` | Mark non-reconciling statements as failed instead of returning best-effort rows |

### Output (csv-ready)

```json
{
  "source": "https://.../statement-jan.pdf",
  "status": "RECONCILED",
  "date": "2026-01-14",
  "description": "ACH DEPOSIT PAYROLL ACME LLC",
  "amount": 2450.00,
  "balance": 5121.37,
  "page": 2
}
```

Export to CSV/Excel directly from the dataset tab, or pull via API.

### Who this is for

- **Bookkeepers & accountants** — client statement backlogs into your ledger without retyping
- **Lenders & underwriters** — cash-flow analysis from applicant statements
- **AI agents** (via MCP) — a callable tool that returns structured, verified transactions
- **Anyone migrating banks** or reconstructing records for taxes

### Notes & limits

- Works on **text-based PDFs** (the kind your bank generates). Scanned/photographed statements need OCR — not yet supported; on the roadmap.
- Layouts vary by bank. The parser handles the common single-column transaction formats (date … description … amount \[balance]). If your bank's layout fails, open an issue with the *layout shape* (never send a real statement) and it gets fixed fast.
- Output is provided as-is, without warranty, and is not accounting, tax, or financial advice. Verify reconciliation status before relying on extracted data.

### Pricing

| Event | Price |
|---|---|
| Run start | $0.02 |
| Per page processed | $0.04 |
| Per statement reconciled | $0.10 (only when the balance check passes) |

A typical 5-page statement: **$0.32** — versus a $30+/month converter subscription or 30 minutes of retyping.

### FAQ

**Is my bank statement stored anywhere?**
No. Files are fetched into memory, parsed, and discarded. The only output is the transaction dataset in your own Apify account, which only you control.

**How do I know the extraction is correct?**
Every statement is reconciled: opening balance + all transactions must equal the closing balance printed on the statement itself. `status: "RECONCILED"` means the math closes — the extraction is provably complete. You only pay the reconciliation fee when this check passes.

**What if my bank's layout isn't supported?**
Open an issue describing the layout shape (columns, date format — never a real statement). Common-layout gaps are usually fixed within days.

**Does it handle scanned statements?**
Not yet — text-based PDFs only (the kind your bank's website generates). OCR is on the roadmap.

**Can I use this from an AI agent?**
Yes — the Actor is callable via MCP (see the API tab), and the `pdfBase64` input means agents can pass files without a hosting step.

**What does a typical statement cost?**
A 5-page statement: $0.02 (run) + $0.20 (pages) + $0.10 (reconciliation) = $0.32. No subscription.

### Changelog

- **2026-08-22** — Demo mode: run with empty input to see the output shape on a bundled synthetic statement.
- **2026-08-20** — Launch: balance-reconciled extraction, EU/US formats, accounting negatives, multi-page statements.

***

### More tools by Businessquik

Verified data tools built on official and public-mandate sources — no logins, no gray areas, no fragile scrapers:

- [Hospital Price File Normalizer — comparable hospital prices from CMS MRFs](https://apify.com/businessquik/hospital-mrf-normalizer)
- [FDA Recall Monitor — new-recalls-only alerts for drugs, devices & food](https://apify.com/businessquik/fda-recall-monitor)
- [Patent Signals — filing velocity, new entrants & expiry intel](https://apify.com/businessquik/patent-signals)
- [US Location Profile — economy, labor & weather in one call](https://apify.com/businessquik/location-profile)

**Support:** open an issue on this Actor's Issues tab — layout/format reports are usually fixed within days. Describe the *shape* of your file or query; never post real bank statements or sensitive data.

# Actor input Schema

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

Direct links to one or more bank statement PDFs (e.g. a signed S3/Drive/Dropbox link). Files are processed in memory and never stored by this Actor.

## `pdfBase64` (type: `string`):

A single PDF supplied inline as a base64 string. Use this when calling from an agent or API without a hosting step.

## `outputFormat` (type: `string`):

Shape of the transaction output pushed to the dataset.

## `dateFormat` (type: `string`):

All dates are normalised to this format.

## `strictReconciliation` (type: `boolean`):

When on, a statement whose transactions don't sum to the closing balance is marked FAILED\_RECONCILIATION instead of returning silently wrong data.

## Actor input object example

```json
{
  "pdfUrls": [],
  "outputFormat": "csv-ready",
  "dateFormat": "iso",
  "strictReconciliation": false
}
```

# 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 = {
    "pdfUrls": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("businessquik/bank-statement-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": [] }

# Run the Actor and wait for it to finish
run = client.actor("businessquik/bank-statement-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": []
}' |
apify call businessquik/bank-statement-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,businessquik/bank-statement-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/8vveA7QHkaQUDNto5/builds/P0ubmmHLPzNCNgrch/openapi.json
