A local-first PDF, OFX, QFX, MT940 and CAMT.053 parser that runs entirely in the browser via WebAssembly. No uploads, no API key, no per-document fee, no vendor lock-in.
Drop into any frontend. Same call signature in Node, Electron, and Tauri.
<script src="https://convertbank.online/parser.wasm.js"></script>
<script>
const file = document.querySelector('input[type=file]').files[0];
const { transactions } = await convertbank.parse(file);
// transactions: [{ date, amount, description, balance, raw }, ...]
</script>import { parse } from "@convertbank/parser";
const buf = await file.arrayBuffer();
const { transactions, format } = await parse(buf, {
format: "auto", // "pdf" | "ofx" | "qfx" | "mt940" | "camt053" | "bai2" | "csv"
locale: "en-GB", // affects date parsing (DD/MM vs MM/DD)
ocrFallback: true, // scanned PDFs only
});
// format === "pdf" | "ofx" | ...
// transactions[0] === { date, amount, description, balance, raw }// In an Electron / Tauri / Capacitor app: same import, same API.
// Bank statements stay on the user's filesystem — no cloud round-trip.
import { parse } from "@convertbank/parser";
import { readFile } from "node:fs/promises";
const buf = await readFile("/Users/alice/Downloads/chase-jan.pdf");
const { transactions } = await parse(buf);Most "Bank Statement Parser API" vendors are hosted endpoints. Your app POSTs a customer's PDF, the vendor's server runs OCR, and you get JSON back. That model has three durable problems: every customer file becomes a sub-processor relationship under GDPR, every outage at the vendor breaks your product, and every parsed document costs $0.05 – $0.50.
The local-first model flips this. The same parsing logic — PDF text extraction, OCR for scanned statements, XML schema validation for CAMT.053, fixed-format decoding for MT940 — is compiled to WebAssembly and shipped inside your frontend. The customer's browser does the work. The bank statement never reaches your server, the vendor's server, or any third party. There is no per-document cost, no rate limit, and no compliance review of an external data processor because there is no external data processor.
The tradeoff is bundle size — typically 2–3 MB of gzipped WASM, loaded lazily on the page that needs it. For a fintech, accounting, or bookkeeping product where the parsing page is a deliberate user action, that's a sensible cost. For a high-frequency consumer app where every kilobyte matters, the hosted route may still win.
| Format | Used by | Notes |
|---|---|---|
| Almost every retail bank | Text-layer extraction, OCR fallback for scans. | |
| OFX / QFX | US retail banks, Quicken | XML-ish; QFX adds an Intuit ID. |
| QBO | QuickBooks Web Connect | OFX wrapped with Intuit identifiers. |
| MT940 | SWIFT corporate banking | Fixed-tag :20: :25: :60F: :61: :86: format. |
| CAMT.053 | SEPA / ISO 20022 | XML schema-validated against camt.053.001.x. |
| BAI2 | US corporate / treasury | Fixed-record cash-management standard. |
| PayPal CSV | PayPal Reports → Activity | Locale-aware date and amount parsing. |
No — and that is the point. Hosted parsers send your customers' bank statements to a third-party server, which creates compliance and breach risk. The convertbank parser is shipped as a browser library powered by WebAssembly. Your users' PDFs never leave their device, so you avoid the data-processor classification under GDPR, SOC 2, and PCI scope creep entirely.
PDF (text and scanned with OCR fallback), OFX, QFX, QBO, MT940, CAMT.053 XML, BAI2, and PayPal CSV. Output is a normalized JSON array of transactions with date, amount, description, balance, and original raw line — so you can build CSV, QBO, or your own format on top.
PDF parsing, OCR, and XML schema validation are CPU-heavy. WebAssembly runs at near-native speed inside the browser sandbox, which means a 12-month statement parses in under a second on a mid-range laptop. It also means no Node.js server, no Lambda cold starts, and no per-call billing.
Drop the script tag or NPM package into your frontend, call parse(file) with a File or ArrayBuffer, and get back a typed array of transactions. There is no API key, no rate limit, and no network call. The same code path runs in Chrome, Safari, Firefox, and Electron apps.
Hosted parsers charge per-document, require you to upload customer data, and add 200–800 ms of network latency per call. A local-first library is free at the marginal level, keeps data on the user's machine, and removes a whole class of vendor dependencies from your stack. The tradeoff is that you ship slightly more JS — typically 2–3 MB gzipped of WASM.
Yes. The parser powers convertbank.online, which processes thousands of statements per month. The same WASM module is reusable in any frontend — React, Vue, Svelte, vanilla JS, or a Tauri / Electron desktop app where local-first is a hard requirement.
The WASM library powers convertbank.online today. The standalone package ships next — request access and we'll send the install instructions.
Request access