All entries
Chapter VIII
Journal · 16 Oct 2026 · 10 min read

MT940 vs camt.053: Bank Statement Parsing Guide

MT940 vs camt.053 for reconciliation: the :61: line, :86: dialects, v02 vs v08 schema changes, batch bookings, BAI2 and the real Swift timeline to 2028.

A SEPA payment carries a 35-character end-to-end reference. The MT940 statement line that reports it has room for 16. Most reconciliation bugs I have chased on bank statements come from that gap, or from what each bank decided to do about it.

The pages that rank for "MT940 vs camt.053" mostly list the tags, say XML is richer, and repeat the claim that Swift killed MT940 in November 2025. It didn't. This guide covers what you hit when you actually parse both: the exact :61: grammar, the :86: dialects, the schema change between camt.053 versions that breaks naive parsers, batch bookings, and which open-source parsers are still maintained.

What Is the Difference Between MT940 and camt.053?

Both are end-of-day bank statements. MT940 is a Swift FIN message: tagged lines of text with fixed length limits. camt.053 is the ISO 20022 XML equivalent, BankToCustomerStatement. Each has an intraday sibling and a notification sibling:

PurposeSwift MTISO 20022US equivalent
End-of-day statementMT940camt.053BAI2 (prior day)
Intraday reportMT942camt.052BAI2 (current day)
Debit/credit adviceMT900 / MT910camt.054none standard
Bank-to-bank (nostro) statementMT950camt.053none standard

The practical difference is granularity. An MT940 statement line describes a booking. A camt.053 entry describes a booking and can list every underlying transaction inside it, each with its own references, parties and remittance text. If your bank books 312 direct debit collections as one credit, MT940 gives you one line. camt.053 can give you one entry with 312 transaction details.

Is MT940 Being Discontinued? The Swift Timeline in 2026

Here is what is true as of October 2026, based on J.P. Morgan's ISO 20022 FAQ and RedCompass Labs' deadline summary (Swift's own roadmap documents sit behind a login):

  • November 2025: coexistence ended for cross-border payment instructions in CBPR+ (MT103, MT202). Statements were not part of that cut-off.
  • November 2026: J.P. Morgan lists end of coexistence for MT101 on FIN. Multi-instruction MT101s are rejected; single ones are converted to pain.001.
  • November 2027: Swift users must be able to receive camt.052, camt.053 and camt.054.
  • November 2028 (SR 2028): planned end of coexistence for MT9xx statements on FIN. Swift will not translate MT9xx into camt for you.
Two things the scary headlines skip. First, Swift's corporate FAQ says SCORE corporates can keep sending and receiving MT940 and MT942 after November 2025. Second, most corporates never receive MT940 over FIN at all. They get it as a file over EBICS, SFTP or a host-to-host link, and no Swift deadline covers that. Any end date there is set bank by bank or by a national community. Germany is the clearest example: the Deutsche Kreditwirtschaft moved its standard camt version from v02 to v08 in November 2025, and some Sparkassen did a hard cut-over that week, while other German banks kept MT940 running. My position: MT940 files will still be produced by UK and EU banks well after 2028, because the formats corporates receive are a product decision, not a network rule. Build new integrations on camt.053 v08 now, because it carries data MT940 cannot. Do not delete your MT940 parser on the strength of a Swift date.

MT940 Format: How to Read the :61: Statement Line

An MT940 message is a sequence of tags:

TagContentFormat
:20:Transaction reference16x
:25:Account identification35x
:28C:Statement number / sequence5n[/5n]
:60F: or :60M:Opening balance (first / intermediate)1!a6!n3!a15d
:61:Statement line, repeatingsee below
:86:Information to account owner6*65x
:62F: or :62M:Closing balance (final / intermediate)1!a6!n3!a15d
:64:Closing available balance1!a6!n3!a15d
:65:Forward available balance1!a6!n3!a15d

The :61: line is where people write bad regexes. Its grammar is 6!n[4!n]2a[1!a]15d1!a3!c16x[//16x][34x], which unpacks to:

1. Value date, YYMMDD. 2. Entry date, MMDD, optional. If absent, assume the value date. Watch the year boundary: a value date of 261231 with entry date 0102 booked in January. 3. Debit/credit mark: C, D, RC (reversal of credit) or RD (reversal of debit). Some banks also send EC/ED for expected items. 4. Funds code, one letter, optional. ING defines it as the third letter of the currency code, so a USD account can produce a D straight after a C. A regex that treats [CD]{1,2} greedily will eat it. 5. Amount, up to 15 characters including a comma as the decimal separator. No sign; the sign is the mark. 6. Transaction type: N or F plus three characters, e.g. NTRF, NMSC, NCHG. 7. Customer reference, 16x, mandatory. NONREF when there is none. 8. Bank reference, // plus up to 16x. 9. Supplementary details, up to 34x on the next line.

Bank specifications commonly cite a 2,000-character limit per FIN MT940. Long statements are split across messages: the first opens with :60F:, the middle ones use :60M:/:62M:, and only the last closes with :62F:. Each :60M: must equal the previous message's :62M:. If you only check :60F: against yesterday's :62F:, a missing middle page goes unnoticed.

The :86: Field: German, Dutch and Other Dialects

:86: is six lines of 65 characters, 390 in total, and its content is whatever the bank decides. Two dialects cover most of Europe. Dutch style (ING, Rabobank, ABN AMRO): slash-delimited codes. ING puts the literal text EREF in the :61: customer reference and moves the real 35-character end-to-end ID into :86::
/EREF/INV-2026-0418-ACME/IREF/.../CNTP/NL91ABNA0417164300/ABNANL2A/ACME BV//REMI/USTD//Invoice 2026-0418/

Returns arrive as /RTRN/AC04/.

German DK style: a three-digit Geschäftsvorfallcode (GVC), then ?-numbered subfields of 27 characters: ?00 booking text, ?20 to ?29 and ?60 to ?63 for purpose text, ?30 BIC, ?31 IBAN, ?32/?33 name, ?34 text key. Inside the purpose text sit SEPA keywords: EREF+, KREF+, MREF+, SVWZ+ (the remittance line), ABWA+.

The 27-character chunks break words and references mid-string, so you must concatenate ?20 to ?29 before searching for EREF+. I have seen invoice numbers split across ?21 and ?22 fail a matcher that looked at subfields one at a time.

camt.053 XML Structure: Entries and Transaction Details

The tree, trimmed to what reconciliation uses:

BkToCstmrStmt
  GrpHdr/MsgId
  Stmt
    Id, ElctrncSeqNb, LglSeqNb, StmtPgntn(PgNb, LastPgInd)
    Acct
    Bal            (OPBD, CLBD mandatory; CLAV, ITBD, ITAV optional)
    Ntry           (one booking)
      Amt, CdtDbtInd, Sts, BookgDt, ValDt, AcctSvcrRef, BkTxCd
      NtryDtls
        Btch/NbOfTxs
        TxDtls     (0..n underlying transactions)
          Refs (MsgId, InstrId, EndToEndId, UETR)
          RltdPties, RmtInf (Ustrd, Strd), RtrInf

Limits that matter, checked against the published XSDs: EndToEndId, AcctSvcrRef and NtryRef are Max35Text. Ustrd is 140 characters per occurrence but can repeat. AddtlNtryInf is 500. Amounts are xs:decimal with up to five fraction digits, always non-negative; direction lives only in CdtDbtInd (CRDT/DBIT). If you store amounts in minor units, the ISO 4217 minor units guide covers the currency exponent trap.

The Bank Transaction Code is a three-level tree: Domn/Cd (e.g. PMNT), Fmly/Cd (RCDT, received credit transfer) and SubFmlyCd (ESCT, SEPA credit transfer). It is far more useful for routing than MT940's four-character NTRF.

camt.053.001.02 vs camt.053.001.08: What Breaks Your Parser

Many banks have moved from version 02 to 08 (Deutsche Bank, NatWest Bankline and the Bank of England's CHAPS reporting all use 08; Nordea's guide was still on 02 in late 2023). The changes look cosmetic and are not:

Elementv02v08
Entry statusBOOK (enum)BOOK (choice of Cd or Prtry)
UETRabsentRefs/UETR
Party wrapper
Return info typeReturnReasonInformation10PaymentReturnReason5

A parser that reads Sts as text gets an empty string on v08 and quietly treats every entry as unknown status. Check the namespace (urn:iso:std:iso:20022:tech:xsd:camt.053.001.08) and dispatch on it. Newer versions exist too; Circle's Mint statements use camt.053.001.13. The ISO 20022 pain.001 vs pacs.008 guide explains how the version suffixes work.

The Same Payment in MT940 and camt.053

A €1,250 SEPA credit, ING-style MT940:

:61:2610151015C1250,00NTRFEREF//2610150012345
:86:/EREF/INV-2026-0418-ACME/REMI/USTD//Invoice 2026-0418/NAME/ACME BV

The same booking in camt.053.001.08:


  2610150012345
  1250.00
  CRDT
  BOOK
  
2026-10-15
2026-10-15
2610150012345 PMNTRCDTESCT INV-2026-0418-ACME ACME BV Invoice 2026-0418

In MT940 the end-to-end ID survives only because ING chose to put it in :86:. Another bank might truncate it to 16 characters in the :61: reference, or drop it. In camt.053 it has a typed field.

MT940 vs camt.053 vs BAI2: Comparison

MT940camt.053 (v08)BAI2
SyntaxTagged text, 65-char linesXML, schema-validatedComma-delimited records ending /
Main regionEurope, global corporatesEU, UK, CBPR+US
Reference length16x in :61:, rest in :86:35 per typed fieldBank and customer ref in record 16
RemittanceWithin 390-char :86:140 per Ustrd, repeatable, plus structured StrdRecord 88 continuation, free text
Batch detailNoYes, TxDtls per itemNo
Transaction codes4 chars (NTRF)Domain/Family/Sub-family3-digit type codes
Amount formatComma decimal, no signDecimal point, sign in CdtDbtIndImplied decimals, no point
Return reasonsBank-specific textISO code in RtrInf/Rsn/CdBank-specific

NatWest's Bankline offers all three, and its translation guide maps them field by field. If you integrate a UK bank and a US bank, expect to run all three parsers.

Where Bank Statement Reconciliation Fails

Batch bookings. One :61: line for 312 collections means you reconcile against a total and need a second file (often camt.054) for the items. In camt.053 the TxDtls amounts must sum to the Ntry amount; assert it. Fees moved inside transactions. KPMG's write-up of German migrations notes banks that reported charges as separate MT940 lines began netting them inside one camt transaction. Rules matched on the old fee lines stopped firing. Returns. A returned SEPA payment shows up as a new credit with a reason code: AC04 account closed, AM04 insufficient funds, MD06 refund requested by the payer. In camt.053 you get the code and usually the original end-to-end ID; in MT940 you get whatever the bank writes. The SEPA Direct Debit Core vs B2B guide covers the refund windows behind MD06. Duplicates and gaps. Banks resend statements. Key each entry on AcctSvcrRef or NtryRef scoped to the account, and track ElctrncSeqNb for gaps the way you would :28C:. Balances have no dedupe key, so recompute rather than trust. Pagination. StmtPgntn/LastPgInd tells you when a camt statement is complete. Don't book a day as closed until you have seen true. This matters if you run regulated reconciliations; the CASS 15 reconciliation guide explains why.

Which Open-Source MT940 and camt.053 Parsers Are Maintained?

Checked on GitHub on 16 October 2026:

LibraryLanguageFormatsStatus
wolph/mt940PythonMT940v5.1.1, September 2026
prowide-core / prowide-iso20022JavaMT and MXActive, October 2026
genkgo/camtPHPcamt.052/053/054 v02 to v082.10.3, August 2025
railslove/cmxlRubyMT940Updated May 2026
svenstaro/mt940-rsRustMT940Updated September 2026
fruitl00p/php-mt940PHPMT940Stale since 2024
webschik/mt940-jsJavaScriptMT940Archived

None of the MT940 libraries understands every :86: dialect. Budget for a per-bank :86: adapter on top of whichever you pick.

What This Means for Teams Reconciling Bank Statements in the UK and EU

1. Ask each bank for camt.053.001.08 now. It gives you end-to-end IDs, batch detail and ISO return codes. Get a sample file before you sign anything; bank variants differ. 2. Dispatch on namespace, not file extension. Support v02 and v08 side by side, and treat Sts as a choice. 3. Keep the MT940 parser. Banks will keep producing it after 2028 on non-FIN channels. Add one :86: adapter per bank and test it with real files containing returns and batch bookings. 4. Key on the bank reference plus account, then match on the end-to-end ID. Never match on amount and date alone; same-amount payments on the same day are common in payroll and collections. 5. Validate balances every file: opening balance equals yesterday's closing, entries sum to the movement, and intermediate pages chain. Alert on any break before matching starts.

I am Tom Wang, and the integrations I have seen go wrong rarely failed on XML versus text. They failed because someone assumed the reference they sent would come back intact. Check what each bank actually returns before writing a single matching rule. The Stripe vs Adyen reconciliation guide covers the PSP side of the same problem.