Bank Statement PDF to Excel & CSV
Pricing
from $10.50 / 1,000 statements
Bank Statement PDF to Excel & CSV
Turn bank statement PDFs into rows: date, description, debit, credit, amount and running balance, plus opening and closing balance and a balance check. One Excel file and CSVs per run. Billed per statement delivered.
Pricing
from $10.50 / 1,000 statements
Rating
0.0
(0)
Developer
Brandon Ob
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Security
Limited permissionsShare
Bank Statement PDF to Excel & CSV: turn statement PDFs into transactions
This bank statement converter turns bank statement PDFs into rows: every transaction with its date, description, debit, credit, signed amount and running balance, plus the statement's opening and closing balance. You also get one Excel file for the whole run (a Statements sheet and a Transactions sheet) and two CSV files. Each statement carries a balance check: the Actor adds every transaction to the opening balance and tells you whether the result matches the printed running balances. You are charged per statement delivered, never for a PDF that failed or had no transactions.
What does Bank Statement PDF to Excel & CSV do?
- Extracts every transaction: date, description, extra detail lines, debit, credit, signed amount and running balance.
- Extracts statement details: bank, account number (as printed, usually masked), currency, period start and end, opening and closing balance, total credits, total debits and transaction count.
- Checks the balance:
okwhen the transactions add up to the printed running balances,mismatchwhen they do not,unverifiedwhen the statement has no running balance. - Reads tables with column headings (Date / Description / Debit or Withdrawal / Credit or Deposit / Balance, or Amount) and plain text lines that start with a date and end with an amount and a balance.
- Returns dates as
YYYY-MM-DD, working out day-first or month-first from the whole statement, or using the order you set. - Writes
statements.xlsx,statements.csvandtransactions.csvfor the whole run, and opens password-protected PDFs when you give the password.
Use cases
- Bookkeepers and accountants: turn a client's monthly statements into a transaction list for categorization and reconciliation.
- Small business owners: build a cash-flow spreadsheet from several accounts without retyping.
- Lenders and underwriters: review income, rent and recurring payments across months of statements, with a balance check that flags reading errors.
- Personal finance: export a year of statements into a budget spreadsheet.
- Automation builders: add a "statement to transactions" step after a document upload, then send the rows to Google Sheets or an accounting tool.
How to use it
- Open the Actor in Apify Console and add bank statement PDF links, one per line. Each file must open in a browser without a login.
- Optional: set Date order if your dates look like 03/04/2026 and you know whether they are day-first or month-first.
- Click Start.
- Open the Statements view, download the dataset, use the
excelUrlworkbook, or usetransactions.csvfor one row per transaction. - To process new statements regularly, save your input as a task and schedule it, or call the Actor from the API.
Input
| Field | What it does |
|---|---|
pdfUrls | Direct links to bank statement PDFs, one per line. |
dateOrder | auto (default), dmy (day first) or mdy (month first) for dates like 03/04/2026. |
pdfPassword | Optional, for password-protected files. |
maxItems | Stop after this many statements (default 100). |
Example input:
{"pdfUrls": ["https://raw.githubusercontent.com/AyonPal/bank-statement-pdf-parser/main/samples/pdfs/astra-premier-checking-jan-2026.pdf"],"dateOrder": "auto","maxItems": 100}
Output
One dataset item per statement. Example based on the default run (a synthetic statement from a public test set); the transaction rows are real output, the statement-level values are illustrative and the list is shortened:
{"bank": "Astra Bank","accountNumber": "XXXX XXXX 4821","currency": "INR","periodStart": "2026-01-01","periodEnd": "2026-01-31","openingBalance": 84913.55,"closingBalance": 61230.10,"totalCredits": 120000.00,"totalDebits": 143683.45,"transactionCount": 24,"balanceCheck": "ok","transactions": [{"date": "2026-01-03", "description": "NEFT SALARY CREDIT JAN 2026", "details": "", "debit": null, "credit": 120000.00, "amount": 120000.00, "balance": 204913.55},{"date": "2026-01-04", "description": "UPI/DR/FRESHMART INDIRANAGAR", "details": "", "debit": 2164.75, "credit": null, "amount": -2164.75, "balance": 202748.80},{"date": "2026-01-05", "description": "ACH/DR/HOME RENT JANUARY", "details": "", "debit": 38000.00, "credit": null, "amount": -38000.00, "balance": 164748.80}],"pdfUrl": "https://raw.githubusercontent.com/AyonPal/bank-statement-pdf-parser/main/samples/pdfs/astra-premier-checking-jan-2026.pdf","pages": 2,"extractedAt": "2026-10-27T13:42:35+00:00","excelUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/statements.xlsx"}
The key-value store also holds statements.csv, transactions.csv and a SUMMARY record that lists PDFs that could not be read or had no transactions. The dataset can be downloaded as JSON, CSV, Excel, XML or HTML, or read through the API.
Pricing
Pay per event: $15.00 per 1,000 statements delivered, plus a $0.00005 charge per Actor start. A statement can have any number of pages and transactions. PDFs that fail or have no transactions are not charged. You can set a maximum cost per run.
Discounts apply automatically on paid Apify plans: 10% off on Starter, 20% on Scale and 30% on Business.
Example: 12 monthly statements for one account cost about $0.18.
Integrations and API
Run it and get the statements back in one call:
curl -X POST "https://api.apify.com/v2/acts/adhistory~bank-statement-to-excel/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \-H "Content-Type: application/json" \-d '{"pdfUrls": ["https://example.com/statement-jan.pdf"], "dateOrder": "auto"}'
Python, with the apify-client package:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_API_TOKEN>")run = client.actor("adhistory/bank-statement-to-excel").call(run_input={"pdfUrls": ["https://example.com/statement-jan.pdf"],})for st in client.dataset(run["defaultDatasetId"]).iterate_items():print(st["periodStart"], st["periodEnd"], st["closingBalance"], st["balanceCheck"])
Like every Apify Actor, it also works with Make, Zapier and n8n, with webhooks and schedules, and as a tool for AI agents through the Apify MCP server.
FAQ
Does it read scanned statements? No. It needs PDFs that contain real text, which is what banks let you download. A scanned statement (a picture of paper) fails with a clear message; there is no OCR.
Which banks are supported? Any bank whose statement is a table with column headings, or plain text lines that start with a date and end with an amount and a balance. A layout that is neither can come back with no transactions or with merged rows, so check your first run.
How does it tell debits from credits? From the column an amount sits in. In plain text lines, from the change in running balance, or from a minus sign, brackets or CR/DR next to the amount. A statement with no running balance and no sign marks is read as written.
The balance check says mismatch. What now? A row was probably read wrongly or skipped. Compare openingBalance, totalCredits, totalDebits and closingBalance with the PDF to see where it goes off, and open an issue with the bank name.
Is my statement stored anywhere? Only in your own run's storage on Apify; nothing is kept beyond your run. Do not submit statements you have no right to process.
Are there file limits? Up to 50 MB per PDF, from public links.
Related tools
- Invoice PDF to Excel & CSV: invoice numbers, totals and line items.
- Payslip PDF to Excel & CSV: gross pay, tax, deductions and net pay.
- PDF Table to Excel & CSV: every table from any text-based PDF.
- Google Sheets Export & Import: send transactions straight into a Google Sheet.
Found a bug or need a feature? Open an issue on the Issues tab — I usually reply within a day.