Runs 100% in your browser: your file is never uploaded
See what's quietly costing your business money, for free
Upload a transaction export (CSV, Excel, or a PDF bank/card statement) and get an instant
breakdown of recurring subscriptions, duplicate tools, fee increases, and unusual charges.
The analysis happens entirely on your own device. Nothing is sent anywhere.
Prefer to have this sent to you instead of downloading it? You can email yourself the summary:
How this actually works, in detail
1
Your file never leaves your device. When you choose a file, your
browser reads it locally using standard web APIs (the same ones for a CSV, an Excel file, or a PDF).
The file's contents are handed directly to a program running inside this same browser tab. They are
never attached to a network request, never uploaded to a server, and this page has no backend to
receive them even if it wanted to.
2
The analysis itself is real Python code, run inside your browser.
This page uses a project called
Pyodide,
which compiles the Python interpreter to WebAssembly so it can run client-side. Excel files are read
with a library called SheetJS, and PDFs are read with Mozilla's pdf.js, both also running entirely in
your browser. The same expense-analysis logic that would normally run on a server runs instead on
your CPU, inside your browser tab, with no network access to your data at any point.
3
You can verify this yourself. Open your browser's developer tools
(F12 or Cmd+Opt+I) and watch the Network tab while you upload a file. No request containing your
file's data will appear. You can even disconnect from the internet entirely after this page has
finished loading, then upload your file: it will still work, which is only possible if nothing is
being sent out.
4
Nothing is stored, anywhere. There's no database, no account, no
login, and no cookies tracking this session. If you refresh or close this tab, the results and your
file are gone. There is nothing left over on any server because no server ever saw them.
5
There are two exceptions, both clearly bounded. Clicking "Generate
My Report" sends the aggregated findings already shown on-screen (vendor names, categories, dollar
totals, never your raw transaction rows) through a small server we control, to write up the explanations
in plainer, less templated language. If that step doesn't succeed for any reason, the report falls back
to the version already computed locally, so you always get a report either way. Separately, if a file's
columns genuinely can't be identified by name or by their values, an optional "let the system take a
closer look" step sends a small real sample (the header row plus 3 example rows) to figure out which
column is which, since that specific task needs to see a few real values to work at all. Neither
exception ever receives your full file, and "Email me this summary" stays entirely under your
control too, it's just a pre-filled email you choose to send.
I'm technical: show me the actual mechanics
The analysis code is a plain, readable Python file (engine.py) loaded alongside this
page. It mirrors the open logic of a CLI tool: it parses the transaction data, normalizes vendor
names, categorizes spend, and runs a handful of rule-based detectors (recurring-charge detection via
interval consistency, fee-creep via early/late period averages, duplicate-service detection by
category overlap, and z-score anomaly detection). None of this code performs any network I/O.
there are no fetch, XMLHttpRequest, or Python socket/requests calls
anywhere in it. Pyodide, pdf.js, and SheetJS each only make network requests once, on initial page
load, to fetch their own runtime/library files, never your data. For Excel files, SheetJS converts
the workbook to a CSV-like table directly. PDFs have no real rows or columns, just text positioned
on a page, so pdf.js extracts each text fragment's position and the page reconstructs a table by
grouping fragments into rows and columns based on their coordinates, then hands that to the same
Python pipeline as a normal CSV upload. This works well for typical text-based bank/card statement
PDFs; it can't read a scanned image with no underlying text layer, since there's nothing to extract.