Validate an IBAN: the mod-97 check explained

To validate an IBAN, check its country code and length against the SWIFT IBAN Registry, move the first four characters to the end, replace each letter by two digits (A = 10 … Z = 35), and check that the number modulo 97 equals 1 (ISO 13616, with the mod 97-10 algorithm of ISO/IEC 7064). That catches every single-character error and almost every transposition. It does not prove that the account exists or that the bank accepts SEPA transfers: those need the registry’s BBAN pattern and the EPC list of SEPA countries.

The algorithm on DE89 3704 0044 0532 0130 00

1. Remove spaces and upper-case: DE89370400440532013000 (22 characters, the German length).

2. Move the first four to the end: 370400440532013000DE89.

3. Replace letters: D = 13, E = 14 → 3704004405320130001314 89, written together: 370400440532013000131489.

4. Compute that number modulo 97. Do it in chunks so no integer overflows: take the first 9 digits, remainder mod 97, append the next 7 digits, remainder again, until the end. The remainder is 1, so the IBAN is valid.

To generate the check digits for a new account: put 00 in their place, compute the remainder r the same way, then the check digits are 98 − r, padded to two digits.

JavaScript — the whole check in twelve lines
export function ibanValid(input) {
  const iban = input.toUpperCase().replace(/[\s-]/g, "");
  if (!/^[A-Z]{2}[0-9]{2}[A-Z0-9]+$/.test(iban)) return false;
  const rearranged = iban.slice(4) + iban.slice(0, 4);
  let r = 0;
  for (const ch of rearranged) {
    const v = ch >= "A" ? String(ch.charCodeAt(0) - 55) : ch; // A=10 … Z=35
    for (const d of v) r = (r * 10 + Number(d)) % 97;
  }
  return r === 1;
}

What does mod-97 catch, and what does it miss?

It catches every single wrong character and every swap of two adjacent characters (the two errors people make when typing). It does not catch a wrong country, a wrong length with coincidentally valid digits, a letter where the national format wants a digit, a closed account or a bank that left the SEPA scheme. That is why a real validator does four more things: country known, length right for the country, BBAN pattern from the registry, SEPA flag from the EPC list; and why a payment system then still receives rejects (AC01, account number incorrect) from the bank.

Why do the registry and the SEPA list matter?

The SWIFT IBAN Registry (the ISO 13616 registration authority’s file) lists for each country the IBAN length, the BBAN structure in a compact notation (8!n10!n means eight digits then ten digits), and where the bank and branch identifiers sit. The European Payments Council publishes the list of countries in the SEPA schemes; it is not the same as the EU (Switzerland and the UK are in, Türkiye is not) and it changed in October 2025. The API returns sepa and sepaSince so a payments team can warn before sending.

Can you get the BIC from an IBAN?

The IBAN gives the bank identifier inside the BBAN (the German Bankleitzahl, the French code banque), but mapping it to the BIC and the bank’s name needs the SWIFT BIC Directory or IBAN Plus, which are licensed data products, not open data. We prefer to say so and put BIC lookup on the roadmap than to ship a scraped directory that goes stale. The validation itself needs no BIC: since 2016 (Regulation 260/2012) an IBAN alone suffices for SEPA payments.

Questions

Does a valid IBAN mean the account exists?
No. It means the string is well-formed for its country. Account existence is only known to the bank; a payment can still be returned.
Why does the API answer 200 for an invalid IBAN?
Because the question was answered: the IBAN is invalid, and failures[] says why (length, check_digits, bban_pattern, country_unknown, characters). A 4xx is for a malformed request, not for a wrong IBAN.
What about the QR-IBAN and the “IBAN Plus” file?
Swiss QR-IBANs are ordinary IBANs with a reserved bank-identifier range; they validate like any Swiss IBAN. IBAN Plus is SWIFT’s licensed IBAN-to-BIC file: roadmap.

Checks, identifiers, SEPA flag, in one call.

Read the IBAN endpoint

Sources