Bank Statement PDF to Excel & CSV - Balance Reconciled
Pricing
Pay per event
Bank Statement PDF to Excel & CSV - Balance Reconciled
Converts bank and credit-card statement PDFs into a clean transaction CSV, then checks that opening balance + transactions = closing balance. A statement that does not reconcile is rejected and not charged for, instead of returning a plausible CSV with a row missing.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Austin Cooley
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
9 days ago
Last modified
Categories
Share
Bank Statement to CSV — reconciled, not just parsed
Turns bank and credit-card statement PDFs into a clean transaction CSV, and checks the arithmetic before handing it over.
The problem with every other statement converter
Producing a CSV from a statement is easy. Producing a complete one is not.
The failure that costs somebody a day is not a garbled row — you can see a garbled row. It is the converter that returns 42 of the 43 transactions. Correctly formatted. Sensible dates. Sensible amounts. Nothing about the file looks wrong. The row that went missing was the one that straddled a page break, or wrapped onto a second line, or sat in a column the parser guessed at.
Nobody notices until the account does not balance, and by then the CSV has been imported, categorised and half-reconciled by hand.
What this does instead
Parse first, then verify:
opening balance + sum of transactions = closing balance
and, wherever the statement prints a running balance, that every row's balance follows from the row above it. When the chain breaks, you get the row number, the description, and the exact size of the gap:
row 5 ("ATM WITHDRAWAL 500 CONGRESS AVE"): previous balance 21,110.24 −200.00 should give 20,910.24 but the statement shows 19,910.24 — a gap of −1,000.00, which usually means a transaction on this line was not captured.
A document that does not reconcile is not charged for, and its rows are kept out of the dataset unless you explicitly ask for them. Unverified data should not be sitting in the same table as verified data, where it will eventually be used as though it were.
The opening and closing balances are only ever taken from figures the bank printed. Filling a missing closing balance in from the last row we happened to read would turn the equation into an identity that passes no matter how much of the table was missed.
It works out each statement's layout rather than assuming one
Every bank prints a different table, so nothing here is hardcoded to one of them. The Actor builds several candidate readings of the page — from the column header if there is one, otherwise from where the numbers line up — and keeps the one whose figures reconcile. Reconciliation is not a report at the end; it is what selects the answer.
Handled:
| Multi-page statements | Tables that continue across pages, with the header repeated or not |
| Wrapped descriptions | A description spilling onto a second line is joined back together |
| Debit / credit columns | Separate "Paid out / Paid in", "Debits / Credits", "Withdrawals / Deposits" |
| Single amount columns | Sign taken from parentheses, minus signs, DR/CR markers, section banners, or the balance column |
(1,234.56) | Parenthesised negatives |
| Thousands separators | 12,345,678.90, and European 1.234,56 |
MM/DD/YYYY and DD MMM YYYY | Plus DD/MM/YYYY, MMM DD, YYYY, ISO, and dates with no year at all |
| Credit cards | Where a purchase increases the balance owed — the direction is worked out from the statement, not assumed |
| Other tables | Check listings, daily balance summaries and second accounts are kept out of the transactions |
| Password-protected PDFs | The kind a bank emails you |
When the columns cannot be identified with confidence, the document is rejected with a reason rather than guessed at.
What you get
- Dataset — one row per transaction: date, description, signed amount,
balance, debit/credit, page, and the per-row
runningCheck. Exportable as CSV, Excel, JSON straight from Apify. - CSV files — one per statement, plus a combined
all-transactions.csv, in the run's storage. summary.json— per document: reconciliation method, opening, closing, sum, discrepancy, the row where the chain broke, and which column layout was detected.
Amounts are signed, with negative meaning money leaving the account. Dates
are normalised to YYYY-MM-DD.
Pricing
| Event | Price |
|---|---|
| Actor start | $0.01 |
| Statement parsed | $0.02 — only for a document that parses and reconciles |
| Transaction extracted | $0.002 per row — reconciled documents only |
A statement that fails to reconcile costs you nothing beyond the run start. So does one that cannot be parsed, or that turns out to be a scan with no text layer. The verification happens before anything becomes billable, which means the work of proving the output is complete is done at our expense, not yours.
What it is not
It does not do OCR. A scanned statement has no text to position, and the Actor will say so rather than return an empty CSV — run it through Searchable PDF OCR first, then through this.
It does not categorise transactions, guess merchants, or enrich anything. It gets the numbers out intact, and tells you when it could not.
It cannot reconcile a statement that does not print any balances at all. If there is no opening balance, no closing balance and no balance column, there is nothing to check against, and the document is reported as unverifiable and not charged for.
Redacting before you share
If these statements are going anywhere else afterwards, run them through PDF PII Redactor first — account numbers and card numbers are removed from the file rather than covered over.


