How Merchant Recognition Works Without Knowing Who You Are
Open a bank statement and you see lines like these:
AMZN MKTP US*4J2L9
TST*SUNRISECAFE
TAMPA EMBASSY SUITES TAMPA
Those strings are what most banks still export. Processor prefixes, city names wrapped around the brand, and random transaction codes sit in the same field as the place you actually paid. As a human (which you most likely are), you can often guess what these mean. Software, on the other hand, needs to be taught how to guess correctly.
What the bank actually sends
Payee fields were originally built for clearing systems and automated merchant processors, not for humans or even personal finance software. In order to parse these confusing strings, we need a purpose-built system that can try a lot of different patterns to match them.
The naive approach is to store the raw string and ask you to categorize it forever. That works, but locks you in to a specific vendor's software. After years of manually fixing imports, you would be reluctant to start over with new software. The better approach is to clean the text, pull out the durable name, and match it against a known catalog.
Normalization and the merchant spine
Big Picture Money first normalizes the bank text: it lowercases, strips noise tokens, and removes the processor and city wrappers that change from row to row. From that cleaned string it extracts a merchant spine (the durable core name hiding inside the junk).

These "spines" follow a pattern, and there are hundreds of possible patterns. Spines are tried from most specific to fallback. Candidates that match are scored by how closely they match; some of these patterns are more specific than other.
| Bank text | Extracted spine |
|---|---|
TAMPA EMBASSY SUITES TAMPA | EMBASSY SUITES |
CHICAGO STARBUCKS CHICAGO | STARBUCKS |
SQ *JOES PIZZA | JOES PIZZA |
WF *WAYFAIR4465805275 | WAYFAIR |
More examples live in Merchant recognition.
Default recognition on your machine
That spine is matched against a local, read-only merchants database (merchants.db) that ships with the app. A hit returns a display name and a default category. New versions and updates of Big Picture Money ship new versions of the merchants.db so you always have the latest list of merchants available.
Merchant lookup is only one layer in a longer stack. Your rules and categorization patterns are also used when they are present. Built-in transaction-type patterns, optional on-device helpers, and MCC codes (merchant category codes from the bank file) all also play a role in this recognition. The full order is in Categorization precedence.
Uncommon local payees often still need a one-time manual category. That choice becomes a learned pattern on your device for next time.
All categorization happens locally on your machine
With the catalog on disk, cleaning, spine extraction, and catalog match do not call our servers. You can import files, review suggestions, and override categories with no network. If you choose to, you can opt-in to using your categorization training data to help improve the categorization process for everyone -- but this is purely opt-in only.
Optional crowd contribution and privacy
Under Settings → General → Help improve categorization (or during first-run setup) you can opt in so anonymous categorizations help improve future merchant-database updates.
Each uploaded entry is allowed to contain only these fields:
| Field | Purpose |
|---|---|
| Hashes of identifying fields | One-way digests of the payee, description, normalized payee, and email or domain when available |
| Category name | The category you chose, as readable text (the only readable field in the upload) |
| Category id | Canonical id when your choice maps to a built-in category (for example travel.lodging) |
| Weight | How many times you reinforced this pattern locally |
| Normalization version | Version of the rules used for the normalized-payee hash |
| Client version | App version (batch metadata) |
Upload requests include an Authorization header so the service can rate-limit abuse. The request body does not include your name, email, device identifier, or account identifiers. The service does not store those identity fields with any uploaded pattern.
Why that cannot identify a person
A hash here is a one-way obfuscation of some data. It cannot be reversed, but it can be repeated (the same block of text, run against the same hash algoithm, always produces the same output.) The original text cannot be recovered. Your device hashes the identifying fields before anything is sent. We never receive the raw text for payee, description, memo, or email text.
The upload also omits amounts, dates, currencies, account names or numbers, transaction identifiers, and user identity in the payload body. The category name itself is the only plain text sent (since learning these categories is the whole point.) It is not a piece of information that can be used to personally identify you (unless you name your categoies 'my name is Patrick and I live at 1313 Mockingbird Lane.'...which is a terrible category name.) See Crowd contribution privacy for the canonical field list and retention notes.
What those signals become later
Over time, consensus from opted-in users feeds the offline build that produces the next merchants.db. That catalog ships to everyone. Contributors improve defaults without handing us readable bank text. A later essay will cover how those sources become one pinned catalog.
For day-to-day product detail, see Merchant recognition and Crowd contribution privacy. Buy Now if you want to try recognition with your own history.