How StatementLock handles your data — the honest, technical version
Hi, I'm the developer of StatementLock — a retired programmer building this solo. This post exists because "privacy-first" is a claim every finance app makes, and you shouldn't have to take my word for it. Here is exactly what happens to your data, including the parts that involve a third party, so you can judge for yourself.
## The short version
- Your PDF statements are parsed
**in your browser, on your machine**
. The PDF files themselves are never uploaded to my servers — I don't have servers that store statements.
- Your transaction data lives in a
**local folder on your computer that you choose**
. You can open it, back it up, or delete it anytime. I can't see it.
-
**No bank logins. Ever.**
StatementLock never asks for your bank credentials and has no connection to your bank (no Plaid, no screen scraping). You download statements from your bank yourself and drop the PDFs in.
- For AI categorization and analysis,
**de-identified text**
from your statement is sent to the AI API (Anthropic's Claude). Details on exactly what that means below, because this is the part that deserves scrutiny.
- The only things stored on my side are
**account and billing records**
: your login (via Clerk) and your subscription status (Stripe payment processing, with billing state in a database). No transaction data, no statement contents.
## What "de-identified" means, specifically
Before any text leaves your machine, a sanitization step runs
**in your browser**
that removes or masks:
- Account numbers (and separately, the account label sent to the AI only ever contains the
**last 4 digits**
, e.g. "Checking •••4321" — the full number is never transmitted)
- Social Security–shaped numbers and routing numbers
- ZIP codes and PO boxes
- Phone numbers and email addresses
- Names in person-to-person payment descriptions (Zelle, Venmo, Cash App, Apple Cash) — replaced with anonymous tokens like [PERSON_1]
- Passenger names in airline transaction lines (the "Passenger Name: SURNAME/FIRSTNAME" fields airlines print on every ticket charge)
- Names in "account of / account holder" phrases in bank transfer descriptions, and the name fragment the IRS embeds in tax-refund deposit lines
- Statement lines matching the account-holder name format
**What IS sent**
, because analysis is impossible without it: merchant names, transaction dates, dollar amounts, and transaction description lines (post-sanitization), plus the statement type. The same sanitization runs on report generation, which includes your category totals and any notes you've added. That's why the app asks you not to type names or account numbers into free-text fields — they'd be sent as part of your report request (sanitization catches the common patterns, but don't rely on it for text you control).
**Known residual gaps, stated plainly:**
no pattern-based sanitizer is perfect. Street addresses appearing inside a transaction description are not currently stripped (an earlier version of that rule also deleted legitimate merchant names). Names in PayPal transaction lines are not tokenized, because PayPal's format makes a person ("PAYPAL *JANE DOE") indistinguishable from a merchant ("PAYPAL *STEAMGAMES") — stripping them would have corrupted merchant names on ordinary purchases. And a name in an unusual format the rules haven't seen can still slip through. If a rare identifying fragment survives, it's sent to the AI API and not stored by me. Per Anthropic's commercial API terms, the data is not used for training, and API conversation content is not retained by default. I list these gaps because you deserve the real picture, not the marketing one — I audit my own product's network traffic with the same DevTools test I invite you to run, and the rules get tighter every time I find something.
**What never involves the AI at all:**
the no-signup demo at statementlock.com/demo makes zero API calls — it's entirely sample data rendered locally.
## Honest limitations
-
**Chrome (or Chromium-based browser) is required.**
The local-folder storage uses the File System Access API, which Safari and Firefox don't fully support. That's a real trade-off I made to keep your data local instead of on a server.
-
**Issuer detection isn't perfect yet.**
Most major US banks and card issuers parse cleanly, but some (Navy Federal, for example) can be mislabeled or come up unrecognized. I'm actively expanding coverage, and the app is being updated to say "Unrecognized" honestly and let you set the issuer yourself rather than guessing wrong. If your statement parses badly, please post in the compatibility thread — every report makes it better.
-
**It's a subscription**
($5.99/mo or $47.88/yr) because every analysis costs me real AI API money. There's a 30-day free trial with no credit card required (10 analyses, 2 reports), and a no-signup demo at statementlock.com/demo if you just want to see what it does.
## Questions I expect, answered up front
**"If it's local-first, why does it need the internet at all?"**
Two reasons: the AI API call for categorization/analysis, and login/billing checks. The heavy lifting — PDF parsing, storage, rendering your dashboard — is local.
**"Why not fully local AI?"**
Local models that run in a browser aren't yet good enough at reliably extracting and categorizing transactions across hundreds of different statement formats. When they are, this architecture is well positioned to switch.
**"Why should I trust you?"**
You shouldn't have to. Open your browser's DevTools Network tab while using the app and watch what actually gets transmitted. I built it so that inspection tells the story.
**"What happens to the text after the AI analyzes it?"**
Each analysis is a single, stateless request: the sanitized statement text goes to the AI API in one call, the results come back, and the request ends. There's no session and no memory between requests — the AI that reads this month's statement has no knowledge of last month's, and nothing accumulates there as you use the app. My server keeps none of it (it counts your usage for billing and passes the text through; it has no database for statement content). As for Anthropic's side: their commercial API terms state that inputs and outputs are not used for training and not retained by default, with a narrow exception for content flagged for safety review. But here's the honest part — I can't see inside Anthropic's infrastructure to verify deletion timing, and neither can any app built on any AI API. So I didn't design the privacy model around trusting that. I designed it assuming the AI provider sees whatever it's sent — which is exactly why the de-identification happens on your machine, before anything is sent. The text that leaves your computer is anonymous whether it's deleted in a millisecond or not.
**"You're one person — what happens to my data if you get hit by a bus?"**
The honest answer is the architecture itself: your transaction data lives in a folder on your computer, in formats you can open, with or without StatementLock. There is no server that goes dark and takes your financial history with it. The app is how I make a living, so I intend to keep it running for a long time — but your data never depends on that.
**"Is it open source?"**
Not currently — it's how I make a living as a one-person operation. I understand that matters to some of you, and the DevTools test above is my answer in the meantime.
Ask me anything below. Critical questions welcome — they make the product and this post better.
Posted Jul 8, 2026, 11:58 AM UTC
10