DEV Community

Cover image for How to extract data from bank statements automatically
Felipe Cardona
Felipe Cardona

Posted on Originally published at anyformat.ai

How to extract data from bank statements automatically

You extract data from bank statements automatically by reading each PDF or scan into a structured schema (account holder, account number, period, opening and closing balance, and one row per transaction) and then checking that the arithmetic closes: opening balance plus credits minus debits must equal the closing balance. The first step is the easy part. The check is what tells you whether to trust the output, because a bank statement is a long table where one dropped row looks exactly like a correct one.

This guide walks through the problem, the main ways people solve it, and a worked example with a fictional statement. Last evaluated: October 2026. For long statements, see how we handle multi-page documents; for finance teams, see anyformat for financial services.

Why bank statements are harder than they look

A bank statement looks like a clean table, and that is the trap. Five things make it hard to extract reliably:

  • Every bank lays it out differently. Column order, date formats, whether debits and credits are separate columns or one signed column, and where the opening balance sits all change from bank to bank, and often between a bank's own products.
  • Transactions run across pages. The table breaks at the page boundary, headers repeat or disappear, and a row can be cut in two.
  • Descriptions wrap onto several lines. A naive parser reads the second line of a description as a new, empty transaction.
  • Scans and photos. Many statements arrive as scans or phone photos, with skew, noise and stamps over the numbers.
  • Several accounts or statements in one file. A single PDF can hold more than one account, or more than one month.

None of this is a reason to avoid automation. It is the reason the output needs a check built in.

What you want out: a schema

Start from the output, not from the tool. For a typical current-account statement:

Field Type Notes
account_holder text As printed
account_number text IBAN or local format, as printed
period_start, period_end date
opening_balance, closing_balance number With currency
transactions[] list One entry per row
transactions[].date date Booking date; keep the value date if both exist
transactions[].description text Joined across wrapped lines
transactions[].debit, .credit number Or one signed amount, pick one convention
transactions[].balance number Running balance, when the statement prints it

A fictional example of the result for one page (all values invented):

{
  "account_holder": "Northwind Trading Ltd",
  "account_number": "ES00 0000 0000 0000 0000 0000",
  "period_start": "2026-09-01",
  "period_end": "2026-09-30",
  "opening_balance": 12480.15,
  "closing_balance": 11902.40,
  "transactions": [
    { "date": "2026-09-02", "description": "Transfer from ACME SA, invoice 1043", "credit": 3200.00, "balance": 15680.15 },
    { "date": "2026-09-03", "description": "Card payment, Office Supplies Co", "debit": 84.90, "balance": 15595.25 },
    { "date": "2026-09-05", "description": "Direct debit, Utilities Ltd, September", "debit": 312.60, "balance": 15282.65 }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Ways to extract bank statement data, compared

Approach Handles different banks Handles scans Catches wrong rows Typical limit
Copy and paste into a spreadsheet Yes, by hand No Only if you check Hours per batch, error-prone
Template or rules per bank One template per layout Poorly No Breaks when a bank changes its PDF
Generic OCR plus a table library Partly Yes No Tables with merged or wrapped cells fail silently; see our table-library test
Prompting a general LLM with the file Yes Yes No Fluent output with no signal for a wrong row; see how to reduce hallucinations
A bank-statement specialist (for example DocuClipper) Yes, built for financial formats Not stated in our comparison Not stated Narrow to financial documents; flat monthly tiers (Starter $20 for 60 pages, Business $111 for 640, Enterprise $360 for 2,000), no on-premise or EU residency in its published docs (as-of 2026-09-14, our Nanonets comparison)
A pretrained document-AI platform (for example Docsumo) Pretrained bank-statement model; custom types need about 20 training samples Not stated in our comparison Not stated; 99%+ on bank statement data is vendor-reported and unaudited Pricing on quote (anyformat vs Docsumo)
A document platform with validation Yes Yes Yes, if you configure the check You define the schema and the rules once

The column that matters is "Catches wrong rows". Every method on this table reads a statement. Few tell you which rows to distrust.

How to extract data from a bank statement with anyformat, step by step

The same statement runs through four steps in an anyformat workflow, built in Studio as a three-operator flow: Parse, Extract and Validate.

The Bank Statement Extraction workflow in anyformat Studio: Parse in Agentic mode, Extract in Agentic mode with 8 fields, and Validate with 6 rules

  1. Parse. The file becomes structured pages and tables, with each block tied to its position on the page and a confidence score on each table. Scans go through OCR first. In this workflow Parse runs in Agentic mode.

The Parse view in anyformat: the source page on the left and the structured table with its confidence on the right

  1. Extract. You describe the schema above in plain language. Header fields come out as single values, and the transactions come out as a list with one entry per row. Extract runs in Agentic mode here, with the 8 fields of the schema. Each field shows its type, whether it is verified, and the review threshold you set. Agentic mode does not support multi-file documents yet.

The Extraction view: each extracted field with its type, a verified status and the review threshold

  1. Validate. Rules check the result against itself: opening balance plus credits minus debits must equal closing balance; each running balance must follow from the previous one; every transaction date must fall inside the statement period; transactions must be in chronological order; a row cannot hold both a debit and a credit; and values under the confidence threshold are flagged for review. The Validation view shows each rule with its result and the values it checked, and you can test an expression before you rely on it.

The Validation view: each rule with its result, pass or warning, and the values it checked

  1. Review what is doubtful. Every extracted value carries a confidence score you can set a threshold on and a link to the place on the page it was read from. Rows under the threshold, or any statement whose balance check fails, go to a person who sees the source next to the value.

What this changes in practice: you do not read every row. You read the rows the check or the confidence flags, and everything else flows through.

Try it on your own statements: the Free tier includes 50,000 credits, enough to run this workflow on a batch of fictional or consented statements without a credit card.

How to convert a bank statement to Excel or CSV

Once the transactions are structured, the Excel or CSV export is the easy part: each transaction becomes a row, with date, description, debit, credit and balance as columns, and the header fields (account holder, account number, period, opening and closing balance) go in a summary sheet or repeat on every row, whichever your accounting tool expects. The step that decides whether the spreadsheet is usable is the one before it: a spreadsheet built from an unchecked extraction hides its errors in plain sight. Run the balance check first, then export only the statements that pass, and send the rest to review.

A balance check, spelled out

If the opening balance is 12,480.15, credits total 3,200.00 and debits total 3,777.75, the closing balance must be 11,902.40. If the extraction returns 11,818.00, one row is wrong or missing and the statement is flagged, instead of the error reaching your ledger. The same logic catches a dropped row, a misread digit and a duplicated line. (The figures are the fictional ones from the JSON above, extended to a full month.)

Statements are personal data

Bank statements carry personal and financial data. Use fictional or consented documents for tests, keep production data inside a deployment you control, and check where each tool processes it. anyformat is ISO 27001:2022 certified, offers EU data residency and can run self-hosted or air-gapped. Zero data retention is an Enterprise option that has to be enabled for your organization, so on the Free and Business plans treat uploaded documents as stored and use fictional statements for tests. More on residency in our GDPR guide.

What it costs

Pricing is credit-based, per page and per operator. At list rates, Parse costs 25 credits per page in Standard mode and 100 in Agentic; Extract costs 35 in Standard and 150 in Agentic; and each AI validation rule costs 5 credits, charged once per extraction and never per page. A credit costs €0.001 on Business and €0.0015 on Free and pay-as-you-go.

10-page statement, 6 AI validation rules Credits Business (€0.001 per credit) Free / pay-as-you-go (€0.0015)
Standard Parse + Standard Extract 630 €0.63 €0.95
Agentic Parse + Agentic Extract 2,530 €2.53 €3.80

The Free tier includes 50,000 one-time credits with no credit card, and Business includes 500,000 credits a month. Standard mode is the right starting point for clean digital statements; Agentic is for scans and layouts that Standard gets wrong.

Limits, stated plainly

  • Handwriting and very low-quality photos are the weak spot of every approach. Set a confidence threshold and let a person review those.
  • Statements with unusual structures (multi-currency accounts on one page, summary pages that repeat totals) need a test on your own files before you trust them.
  • The balance check only works when the statement prints balances. Some formats print only movements; then the check compares totals, not running balances.
  • We have not published an accuracy figure for bank statements. Test fifty of your own statements, measure field-level accuracy and the share that pass with no human touch.

How to choose

If you process a handful of statements a month in one layout, a template or a converter is enough. If layouts vary, scans are common, or an error in a ledger is expensive, choose a tool where a failed check is visible: the question to ask every vendor is "when a balance does not close, what does my team see?". For broader comparisons see the best document parsing APIs and alternatives to Nanonets.

Frequently asked questions

How do I extract data from a bank statement PDF automatically?
Read the file into a schema (header fields plus one row per transaction), then verify that opening balance plus movements equals closing balance. Tools differ mainly in whether they tell you which rows to distrust.

Can I extract data from a scanned bank statement?
Yes, with OCR before extraction. Accuracy drops with skew, noise and photos, so scanned statements need a confidence threshold and a review step.

Can I convert a bank statement to Excel or CSV?
Yes: once the transactions are structured, exporting to CSV or Excel is a formatting step. The hard part is the extraction and the check, not the export.

How do I know the extracted transactions are correct?
Run the balance check. If opening balance plus credits minus debits does not equal the closing balance, a row is wrong or missing. Per-field confidence tells you where to look first.

Is it safe to upload bank statements to an extraction tool?
Check retention, residency and certifications before you upload real data, and test with fictional statements first.

Does it work for statements from different banks?
Template-based tools need one template per layout. Schema-based tools read each layout from your field definitions, but you should still test a sample from each bank you handle.


Start with your hardest documents. Upload the statements that break your current pipeline, define the fields you need, and see the values with their confidence and their evidence on the page. The Free tier includes 50,000 credits with no credit card.

Disclosure: anyformat sells document extraction; the example is fictional and the comparison criteria are stated.


Originally published at anyformat.ai/blog/extract-data-from-bank-statements.

Top comments (0)