statementproof
Bank statement PDF → CSV extraction that tells you when it got it wrong.
Most converters hand you output with no way to know if it is correct. A bank statement is one of the few documents carrying its own checksum — the balances.
What it does differently
1. Geometry, not regex. The most-cited converter failure is "columns shift,
debit and credit values land in the wrong places." That happens because
extract_text() flattens a 2-D layout and discards x-position — the only signal that
distinguishes a debit column from a credit column. This reads word coordinates and
clusters money columns by their right edges.
2. Column roles from arithmetic, not headers. Which column is the running balance is decided by behaviour, not by header text — header text differs across banks and is often missing on continuation pages.
3. Sign from the balance chain. If the balance went down, it was a debit, regardless of whether a minus glyph survived extraction.
4. It refuses to bluff. With nothing to check against, output is UNVERIFIED —
never a silent pass.
Verdicts
| verdict | meaning |
|---|---|
VERIFIED |
transactions reproduce the statement's own balances |
FAILED |
they do not — with the offending row named |
UNVERIFIED |
statement carries no balances to check against |
What it CANNOT catch — read this
The check is arithmetic consistency, not correctness. It cannot see errors that do not disturb the arithmetic:
- junk rows with a
0.00amount (page headers picked up as transactions) - wrong dates
- garbled or truncated descriptions
- two errors that cancel out
"Provably arithmetically consistent" is the honest claim. "Provably correct" is not, and is not made here.
Free test mode — try it on your own statement
python -m statementproof YOUR_STATEMENT.pdf # validate, print a report
python -m statementproof YOUR_STATEMENT.pdf --csv out.csv
python -m statementproof YOUR_STATEMENT.pdf --diagnostic # shareable layout report
It runs entirely on your machine. Nothing is uploaded, nothing is stored, no file is
written unless you name one with --csv.
That is not a policy, it is a property of the code, and it is tested:
tests/test_privacy.py parses every module's AST and fails the build if any
networking library is imported anywhere in the package.
The --diagnostic flag, and why it exists
The single thing that would most improve this tool is a library of real statement
layouts. A layout can be described without describing anyone's money, so
--diagnostic prints exactly that: column positions, column density, date-token
shapes (DD/DD, not 10/02), and where extraction broke.
It contains no amounts, no balances, no descriptions, no dates, no account numbers, no names, and not even the filename. It prints to your screen so you can read the whole thing before deciding whether to share it. The tool never sends it anywhere — there is no code that could.
Those exclusions are asserted by tests against a known statement, not just intended.
Status
Early, and scoped to text-layer PDFs only — statements downloaded from a bank portal. Scans and photographs are not supported; the tool detects them and says so rather than producing garbage.
7/7 layouts extracted exactly, 0 false assurances. Six are synthetic; the seventh
is reproduced from a real bank's published specimen and is the useful one — it found
three bugs the synthetic set never could, including MM/DD dates with no year, which
alone produced 0/21 extracted while the synthetic suite still reported 6/6.
⚠️ Passing a test suite written by the author of the code under test is worth very little. Six invented layouts passed while a real bank's date format extracted nothing. No real customer file has been processed yet — which is what the free test mode above is for.
python statementproof/tests/make_statements.py # build synthetic corpus
python statementproof/tests/make_real_derived.py # build real-bank-derived layout
python statementproof/tests/score.py # score extraction
python statementproof/tests/test_failure_modes.py # validator behaviour
python statementproof/tests/test_privacy.py # privacy promises
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file statementproof-0.1.0.tar.gz.
File metadata
- Download URL: statementproof-0.1.0.tar.gz
- Upload date:
- Size: 17.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f575dff6bb412ffa9ea00bb3d5aacf6f108aea7fcda826b1aba9e1617f2c6190
|
|
| MD5 |
e8c58c11d44e0ed969e32252a17f18eb
|
|
| BLAKE2b-256 |
8c59719fadb2d70690cb87da643ee4f35c8fb75492a6030565365ded40689a32
|
File details
Details for the file statementproof-0.1.0-py3-none-any.whl.
File metadata
- Download URL: statementproof-0.1.0-py3-none-any.whl
- Upload date:
- Size: 18.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
afdc7db54f66c54ff78cb889ec9b13dbf4a4519163c31378b6e1e5a116bcd347
|
|
| MD5 |
87170dbb0b05f5f7073499fb807e0f70
|
|
| BLAKE2b-256 |
e497de0d2105c52ec87054441e9b56930e6a02a87e9493ff361e6acfd5e1e320
|