Home › How we check accuracy

How we check accuracy

CSVLedger checks every conversion against the statement itself: opening balance + credits − debits must equal the printed closing balance to the cent, and printed running balances are verified row by row. In October 2026 tests, 220 of 220 rows on 6 synthetic layouts and 94 of 94 rows on 5 public sample statements were extracted correctly; real statements from most named banks are not yet tested.

Updated October 29, 2026

"99% accurate" means little if you do not know which 1% is wrong. CSVLedger instead checks each conversion against the statement's own numbers and shows you the result.

The balance equation

A bank statement is self-checking: it prints where the balance started, where it ended, and every movement in between. If the extracted transactions are complete and have the right signs, they must add up exactly:

opening balance + Σ credits − Σ debits = closing balance

A missing row, an extra row (for example a subtotal read as a transaction), or a wrong sign all break the equation. The difference is shown, so a 120.00 difference usually points directly at a 120.00 transaction — or at a 60.00 one with the wrong sign.

The running-balance check

Many statements print a balance after each transaction. For every such row CSVLedger verifies that previous balance + amount = printed balance. This locates errors precisely and also lets the parser infer the direction of amounts when a statement does not label them. On statements that print only one balance per day, the check is applied at the end of each day.

Other checks

Our test results, with their limits

Test setWhat it isResult
6 synthetic layoutsStatements we generated to imitate common US layouts: separate debit/credit columns, signed amounts, section-based statements, card statements, day-only balances, a period crossing New Year. 220 transactions in total.220/220 rows correct; 6/6 reconciled
5 public sample statements with answer keysFreely licensed sample statements published by third parties (including an Indian-rupee statement with DD/MM/YYYY dates and multi-line descriptions). 94 transactions.94/94 rows correct (date, amount, description start); 5/5 reconciled
1 public sample without answer keyA sample statement published by a document-AI vendor.29 rows extracted; reconciled to the cent
2 scanned samplesImage-only PDFs.Correctly reported as scanned (no output)

The synthetic statements were made by us, so they are easier than real-world files. We have not yet tested real statements from Chase, Bank of America, Wells Fargo or other named banks, because real statements are private documents. That is exactly why every conversion reports its own reconciliation status.

Frequently asked questions

Does "Reconciled" guarantee every row is right?

It guarantees the rows add up to the bank's closing balance. Two errors could in theory cancel each other out (for example two amounts swapped between rows with the same sign), and descriptions are not covered by the arithmetic. On statements with a running balance, the per-row check makes that very unlikely.

What should I do if a statement does not reconcile?

Look at the red rows first, then at the difference amount. You can edit dates, descriptions and amounts in the table and the check runs again. If the layout is badly misread, the format is not supported yet.

Why not publish an accuracy percentage?

A percentage depends entirely on which statements were tested. We publish the actual test sets and counts instead, and every individual conversion is checked.

Is my bank statement uploaded to a server?

No. The PDF is opened and converted by JavaScript running in your browser tab (using Mozilla's open-source pdf.js library). The file is not sent to CSVLedger or anyone else. You can confirm this in your browser's developer tools: the Network tab shows no request containing your file.