Privacy

How your data is handled, in plain language.

This isn't a legal document written to protect us. It's a plain explanation of exactly what happens to your file, because that's what actually matters when you're deciding whether to trust a tool with your business's financial records.

No file uploads, ever Verifiable in your network tab Works fully offline
Your file
CSV, Excel, or PDF
Your browser
analysis happens here, and stops here
Our server
never touched

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 contents are handed directly to a program running inside that same browser tab. They are never attached to a network request, never uploaded to a server, and this site has no backend to receive them even if it wanted to.

The analysis itself runs on your CPU, not ours.

The tool uses a project called Pyodide, which compiles a real Python interpreter to WebAssembly so it can run inside your browser. Excel files are read with a library called SheetJS, and PDFs are read with Mozilla's pdf.js, both also running entirely client-side. None of this code performs network I/O with your data.

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 the page has loaded, then upload your file: it will still work, which is only possible if nothing is being sent out.

Nothing is stored, anywhere.

There's no database, no account requirement, and no cookies tracking your session. If you refresh or close the tab, the results and your file are gone. There is nothing left over on any server, because no server ever saw them.

There are two narrow, clearly-bounded exceptions.

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 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 step sends a small real sample (the header row plus three 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.

I'm technical: show me the actual mechanics
The analysis code is a plain, readable Python file loaded alongside the 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. PDFs have no real rows or columns, just text positioned on a page, so pdf.js extracts each 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.

Still have questions?

We'd rather explain it clearly than have you take it on faith.

Reach out