A deep dive into structural variations across Jio Payments Bank, HDFC, SBI, ICICI, and Chase statements, and how parsers normalize them.
Why One Parser Cannot Read All Banks
Jio Payments Bank 2025 statements use a compact single-page header with a 4-column table (Date | Narration | Debit | Credit) and a footer holding closing balance. HDFC classic statements spread across 3–8 pages, with separate sheets for joint holders, interest, and service charges, plus a running balance column that some branches omit. SBI corporate statements add a branch stamp image that breaks text extraction and a vertical header that confuses period parsers. Even the word "Balance" appears as "BAL." "Avl Bal" or "Closing".
Because of this, a single regex for amount fails. StatementIQ's Python layer first runs header extraction restricted to page-1 top 30 lines to capture bank name, holder, IFSC, period, opening/closing — never mistaking a transaction beneficiary for holder — then scans pages for tables using pdfplumber line topology.
Table: Layout Variations Across 5 Major Banks
| Bank | Pages | Money Columns | Balance Column? | Password |
|---|---|---|---|---|
| Jio Payments Bank | 1–2 | Debit / Credit separate | No | Phone + DOB |
| HDFC Bank | 3–8 | Withdrawal / Deposit | Yes (some) | Customer ID |
| SBI | 2–12 | Debit / Credit / Balance | Yes | a/c last 6 + DOB |
| ICICI | 2–5 | Amount + Dr/Cr flag | Yes | DOB |
| Chase | 1–6 | Amount + prefix | No | None |
How StatementIQ Normalizes Them
After table rows are captured, each amount is confirmed against the running balance delta when present: if row n's printed balance − row n-1's balance != amount, the row is flagged unverified and counted in unverifiedRows. The reconciler then checks opening + Σcredits − Σdebits == closing. Only when both gates pass does the statement become complete; otherwise needs_review with a "Confirm & finalize" button that requires explicit user action.
Currency is inferred from bank name (detectStatementCurrency) — INR for Jio/HDFC/SBI/ICICI, USD for Chase/Barclays, GBP for Barclays/HSBC — and stored on the statement to avoid heuristic drift later. Check the full matrix at Features → Supported Banks.
When Layout Still Fails — Human Review
No heuristic covers every corporate stamp or watermark. If header detection finds no period or balances, enrichment falls back to an LLM with a strict system prompt and a zod schema that caps bankName to 120 chars and strips <>. The LLM never sees the full table — only page-1 text (3,000 chars) with delimiters to prevent prompt injection. If that still fails, the PDF is stored with status: error and your team can correct metadata manually.