Bank statement PDFs are deceptively hard to parse. You'd think it's a
table, but:
- A single transaction "description" frequently wraps across several lines, so you can't just split on newlines.
- Debits and credits flip sign depending on the bank.
- Scanned statements have no text layer at all.
So I didn't try to parse the PDF structure directly. Instead:
- Render each page to an image with mupdf compiled to WASM.
- Send the image to a vision model with a strict JSON schema:
{"bankName": ..., "accountNumber": ..., "summary": [...],
"transactions": [{"date": "...", "description": "...",
"amount": 0}]}
- Ask for negative amounts on debits and positive on credits.
- Stream rows back over SSE so the UI fills in live.
- Reassemble and export (xlsx, CSV, and plain-text OFX/QBO/QIF for QuickBooks and Xero).
The things that actually moved the needle on accuracy:
- Separate prompts: a "header + summary + transactions" prompt for page one, a transactions-only prompt for later pages.
- Telling the model "return only JSON, no markdown".
- Explicit sign conventions instead of relying on the model's guess.
- Generating a deterministic FITID for QBO/OFC so re-imports don't duplicate entries.
It's live and free at statementexcelconverter.com. The parts that
still need work: hand-annotated adjustments (paper statements with
notes), and non-Latin statement layouts.
Happy to share more detail or the prompt structure if useful.
Top comments (0)