Every free finance app wants your statement PDF sitting on its server. LedgerPanda never asks. Drop the PDF in — a Rust/WASM engine parses it on your machine, reconciles it against your bank’s own totals, and stores the rows in a local SQLite database on your own disk. From there one tap of AI Simplify cleans the merchant names — and you decide when it runs. Nothing to upload. Nothing to leak. No API bill.
A local-first statement parser for people who actually read the privacy policy.
The honest asterisk: signing in with Google is required — the import gate stays locked until you do — and it shares a minimal identity: email, name, avatar, nothing more. But your statements, transactions and categories are computed and stored only on your device; no financial data is uploaded. The one other thing that can cross the network is a PDF you choose to send us for layout support — after it has been redacted on your device. That is the whole list.
One click on AI Simplify rewrites the whole batch in place. Cleaning is something you ask for — nothing rewrites your rows on its own. It runs on Chrome’s built-in model (Gemini Nano, Chrome 138+), so wording can vary between Chrome builds; rows it can’t meaningfully shorten are left exactly as they were, and nothing is exported until you say so.
Seven layouts, hand-tuned and validated against real statements. We would rather parse seven banks perfectly than seventy badly — and if yours isn’t here, the feedback loop below gets it added.
No waiting on a server, no “processing, please wait” spinner — it runs on your hardware, so it runs now.
Drop your bank statement here
Date,Description,Amount,Balance,Account 2026-01-04,Google Workspace,-54.00,12346.00,Software & Subscriptions 2026-01-06,Amazon,-129.99,12216.01,Office Operations 2026-01-08,Lumen & Co Design Studio INV-2291,1850.00,14066.01, 2026-01-11,Blue Bottle Coffee,-18.75,14047.26,Travel & Entertainment
Account is your own chart of accounts. A blank field just means that row isn’t categorised yet.
Drag a statement into the extension. No upload dialog, no “syncing” — the file never leaves the tab.
The Rust/WASM engine extracts text, rebuilds the table, infers the date format — then proves it: opening balance plus net has to equal the closing balance, or you get a red flag and the exact difference.
Hit AI Simplify and Chrome’s built-in on-device model rewrites the whole batch in place — AMAZON.COM*1X2Y3Z4 becomes Amazon. Rows it can’t meaningfully shorten are left exactly as they were. No inference API call, no statement text leaving the machine — and nothing runs unless you ask it to.
A six-tier cascade files each transaction into your chart of accounts and stamps the row with which tier decided it. Only the top two tiers land without a review flag; the rest wait for your eyes, and rows nothing was confident about stay visibly unclassified rather than guessed at.
CSV out, with your own chart of accounts attached to every row. Close the tab and nothing of yours remains anywhere else.
Categorisation runs through a six-tier cascade, and every row keeps a badge saying which tier decided it. Nothing is presented as fact that was only a guess.
Only the first two are trusted. A row you have corrected, or one the on-device model already settled, is filed with no review flag. Everything lower — the statistical guess, the built-in lookup, the fallback — is marked for your eyes, and rows nothing could place with confidence stay visibly unclassified rather than being quietly guessed at. 144 vendor mappings give you a running start; the rest it learns from you.
Most parsers hand you a table and hope you never check it. This one checks itself against the numbers your bank printed, and shows you the verdict either way.
Every printed row captured exactly once. Safe to export.
Two rows went missing. You get the exact difference before you confirm anything — no silent gaps, no discovering it next April.
Most tools bolt encryption onto a pipeline that was always going to ship your data somewhere. We deleted the pipeline instead.
PDF text extraction, table reconstruction, date-format inference (ISO and European decimals) and total validation all happen inside a WebAssembly module compiled from Rust, running in a dedicated worker. There is no parsing endpoint — because there is no server in the loop.
Banks write description fields like they are being paid per character. Cleaning is a button, not a background job: hit AI Simplify and Chrome’s built-in language model (Gemini Nano, Chrome 138+) rewrites the batch on your machine — no API key, no per-row cost, no statement text sent anywhere. Descriptions that are already concise are returned untouched rather than mangled. It also fills in categories for rows the rule engine couldn’t call confidently.
Two honest caveats. Chrome downloads the Gemini Nano model once (~2–4 GB) the first time you use it — after that it is fully offline. And the model needs a desktop with 22 GB of free disk plus a GPU above 4 GB VRAM (or 16 GB RAM and 4 CPU cores). On machines that don’t qualify, AI Simplify stays unavailable; parsing, reconciliation, storage and export are unaffected.
Statements and transactions live in a real SQLite database (wa-sqlite) persisted to OPFS inside a worker on your device. No cloud database is ever created for your ledger. Clear it and it is gone everywhere at once — because it only ever existed in one place.
Export a flat CSV — Date, Description, Amount, Balance, Account — with your own account names in the Account column. Bring your own chart of accounts and your own rules; the built-in library is a starting point, not a cage. Your data leaves as a file you can open in a text editor, not as a format you have to log back in to read.
Mercury, Wise, Payoneer, Shopify Balance, Lili, Lloyds, Majority. Each layout is hand-tuned and every generated config is validated by the Rust engine before it is trusted. Depth over breadth is a deliberate constraint, not a limitation we are hiding.
Every confirmation and correction is remembered locally. The more you use it, the sharper it gets on your spending — and that knowledge accumulates on your disk, not in a vendor’s training set.
Categorisation is a six-tier cascade, and the tier that fired is printed right on the row — as a badge you can hover to see exactly which rule reached the verdict. Hit the top tier and it is remembered forever; miss every tier and the row stays visibly unclassified rather than being quietly filed somewhere plausible.
Only the first two tiers arrive without a review flag. Everything lower waits for your eyes, so you always know how much to trust a line item. It is the same principle as reconciliation: a tool that hides its uncertainty is not accurate, it is just quiet.
144 vendor mappings ship in the box. Corrections are blocked from training on fingerprints with no identifying power — POS PURCHASE will never teach it that “POS” means groceries.
A parser that quietly drops three rows is worse than no parser at all — you find out next April. So every parse is checked against the totals your bank printed on the statement: opening balance, closing balance, income and expense. Match, and you get a green Reconciled. Miss, and you get a red Not reconciled plus the exact difference — before you confirm a thing.
All arithmetic runs in integer cents. No floating-point drift, ever.
On-device AI never writes straight into your books. Every AI-suggested category lands flagged for review and waits for your confirmation, row by row — and if the model isn’t confident enough, its answer is thrown away rather than guessed at. The uncertain rows queue up behind a pending-review count you can see at a glance.
Turn on-device AI off entirely in Settings. Parsing, reconciliation, storage and export do not depend on it.
Each CSV you export is logged locally — timestamp, row count and a verification hash of the file contents. If you ever need to show which numbers went into your books and when, the answer is already on your disk, not something you have to request from a vendor.
Export history lives in the same local SQLite database. It is exactly as private as the rest of your ledger.
The long tail of bank formats is real, so we built a one-click feedback channel. And we built it so you never have to trust us: before a statement PDF leaves your browser it is rebuilt from scratch on your device. Every text fragment is classified — account and card numbers, account holder names, customer IDs, SSN, tax ID, IBAN, phone, date of birth, address — and the sensitive ones are simply never written into the new file. A black block labelled REDACTED takes their place, at the same coordinates on the same page.
This matters more than it sounds. A black rectangle drawn over live text is not redaction; the text is still there and any extractor recovers it. Our output has no such text to recover — the sensitive characters are dropped before the file is written, not covered up afterwards. Everything else — dates, descriptions, amounts, balances — is rewritten at its original position and font size, so the file keeps a real text layer and we can replay our own parser on exactly what you sent us. You can preview the redacted file before you send it, and redaction is on by default.
Each surviving fragment is written back at its original page coordinates, font size and rotation, so the file you send extracts the same rows your original would. Across our test bank of statements the extracted line text matches the source character for character, except where the bank used icon-font glyphs that the rebuilt file cannot represent. That is the whole point: your feedback has to be replayable, not merely readable. Rebuilding works on PDFs: a screenshot or other image you attach instead is sent as it is, so read the preview before you confirm.
“We take your privacy seriously” is worth nothing. Here is the complete network surface of this extension.
Everything else — parsing, AI cleaning, categorisation, storage, export — is computed on your machine.
Your statement PDFs. Parsed in-browser by the WASM engine — there is no parsing endpoint, so nothing is uploaded in order to read them. The only way one leaves is if you send a redacted copy for layout support, described below.
Your transactions. Stored in a local SQLite database on your device. No cloud database is provisioned for your ledger.
A minimal Google identity — email, name, avatar. Import is gated on it: until you sign in, the drop zone stays locked. Used for nothing else — we never read your Gmail, contacts, or any other Google service.
A redacted PDF for layout support — rebuilt on your device first, with account numbers, names and addresses dropped rather than covered over, and a preview before upload. What remains is the transaction rows themselves — dates, descriptions, amounts — with nothing in the file that identifies the account holder. That is the minimum we need to reproduce your bank’s layout, and it is exactly what the preview shows you. On-device AI runs entirely locally, so there is no inference API in the picture at all: no prompt, no token, no statement text is transmitted.
We would rather tell you what isn’t ready than let you install it and find out.
Native ledger / .dat journal output, generated locally alongside the CSV path. If you keep a plain-text ledger today, this is the piece you’re waiting for — it just isn’t in the build yet.
Beyond the first seven. Formats arrive through the redacted feedback loop above — send us a statement, we tune the layout and ship it back.
Available now, along with local parsing, on-device AI cleaning, redacted feedback and the seven adapted banks.
Sign in any time before paid plans open and the core features stay free permanently. No credit card, no trial timer — and still no statement upload.
The founders window is open. It closes when paid plans launch — and we announce that 30 days ahead.
The founders window has closed — new accounts need a subscription to import statements.
Claim founders access — coming soon