Why Bank Transaction Categorization Never Quite Fits
Published on 2026-08-24 · 4 min read · Coinest Team
Open a banking app and every line already has a little icon next to it: a shopping bag, a fork and knife, a bus. It reads like a fact. It isn't. Bank transaction categorization is the bank's own best guess, built by matching whatever text a payment carried against an internal lookup table. It's wrong often enough that anyone who reconciles a budget notices the pattern within a month.
- CAMT.053, the ISO 20022 format SEPA banks are migrating to from the older MT940, carries free-text remittance fields, not a standardized list of spending categories
- A category label is attached afterward, by matching that free text against a bank's own lookup table: an inference, not something printed on the statement
- The same merchant can land in different categories depending on how a payment was routed, which is why two banks, or your bank and a budgeting app, disagree
- No SEPA or ISO authority defines "this string equals Groceries," so categorization stays rule-based and probabilistic, never authoritative
- Sorting spending into household versus personal scope means interpreting that same raw text a second time, not copying a label the bank already settled
What a bank statement actually contains
CAMT.053 is the ISO 20022 bank-to-customer statement standard SEPA banks have been migrating toward, replacing the older MT940 format many still export for legacy integrations. Both exist to move money and leave an audit trail, not to answer "what did I spend on takeaway this month." Each transaction record carries free-text remittance or purpose fields, filled in by the payer, the merchant's payment processor, or the merchant's own bank. Neither standard defines "Groceries" or "Entertainment" as a field. That taxonomy gets bolted on afterward, by whoever reads the statement.
SEPA's push toward ISO 20022 didn't make MT940 vanish overnight. Plenty of banks, especially for business accounts, still export MT940 alongside CAMT.053. If a category looks different after switching how you pull statements, the format is worth checking.
How categorization actually happens
A category gets assigned by cleaning up that remittance text and checking it against a lookup table of merchant strings and keyword patterns. A clean match produces a confident category; a generic processor reference or truncated store code matches nothing, so the matcher falls back to a coarse bucket or guesses wrong. None of this is standardized. Every bank, and every finance app built on bank data, keeps its own table, and the tables disagree.
Say a payment carries remittance text that just names a payment processor rather than the actual merchant, common with checkouts routed through a third party. One system might file that as "Shopping." Another might not recognize the string and drop it into "Miscellaneous."
| Remittance text (illustrative) | One system might file it as | Another might file it as |
|---|---|---|
| "ALBERT HEIJN 1234 AMSTERDAM" | Groceries | Groceries |
| "MOLLIE*STUDIO XYZ" (a processor name, not the merchant) | Shopping | Miscellaneous |
| "AMZNMktplace NL" | Shopping | Subscriptions, if flagged as recurring |
| "SEPA OVERBOEKING factuur 4471" | Miscellaneous | Uncategorized |
The exact labels don't matter — near-identical text can land in different buckets depending on which table is matching, and how aggressively it guesses when nothing matches cleanly.
Why the same merchant moves around
A merchant's remittance text isn't fixed. It changes when a merchant switches payment processors, when a purchase happens online instead of in-store, or when one card network abbreviates a name differently. A subscription that matched cleanly for months can stop matching after the merchant changes how the charge is worded, even though nothing about the spending changed. Some banks let a user override a category manually, fixing that one transaction without teaching the table anything, so the same merchant reappears miscategorized next month.
Most banking apps let you tap a transaction to see the raw remittance text behind the category icon. When a category looks wrong, that string usually explains why: often a processor name or an abbreviated reference, not a bug.
What this means for household versus personal scope
A category is already an inference built on messy text, so sorting that transaction into household or personal spending is a second round of interpretation, not reading a field that already says which it is. A grocery run tagged "Groceries" still has to be judged as shared or one person's own, using signals the statement carries but doesn't spell out: which account it came from, how often that merchant appears, what pattern it already fits.
That's real work, not relabeling. Coinest runs that second pass on the same raw data, sorting transactions into household, personal, or shared scope with a visible badge instead of treating the bank's guess as final. Try it on a real statement at Coinest.