IBAN Validation: Complete Developer Guide (2026)

Finance Guide February 2026 · 10 min read

If your app handles international payments, money transfers, or banking integrations, you'll need to validate IBANs. The International Bank Account Number is used across 80+ countries to identify bank accounts for cross-border transfers.

Getting IBAN validation wrong means failed transfers, returned payments, and unhappy users. This guide shows you exactly how the validation works, with code you can drop into any project.

What's Inside an IBAN?

Every IBAN follows the same structure, regardless of country:

DE893704 0044

Country Check digits Bank code
  1. Country code (2 letters) — ISO 3166-1 alpha-2 (DE = Germany, GB = UK, FR = France)
  2. Check digits (2 digits) — computed using MOD-97 to catch typos
  3. BBAN (Basic Bank Account Number) — the rest, format varies by country

The total length depends on the country. Germany is 22 characters, the UK is 22, France is 27, and Norway is just 15.

IBAN Lengths by Country

CountryCodeLengthExample
GermanyDE22DE89 3704 0044 0532 0130 00
United KingdomGB22GB29 NWBK 6016 1331 9268 19
FranceFR27FR76 3000 6000 0112 3456 7890 189
SpainES24ES91 2100 0418 4502 0005 1332
NetherlandsNL18NL91 ABNA 0417 1643 00
ItalyIT27IT60 X054 2811 1010 0000 0123 456
SwitzerlandCH21CH93 0076 2011 6238 5295 7
NorwayNO15NO93 8601 1117 947
PolandPL28PL61 1090 1014 0000 0712 1981 2874
BelgiumBE16BE68 5390 0754 7034

The MOD-97 Checksum Algorithm

IBAN validation uses the MOD-97 algorithm defined in ISO 7064. Here's how it works:

  1. Move the first 4 characters to the end: DE89... becomes ...DE89
  2. Convert letters to numbers: A=10, B=11, ..., Z=35. So D=13, E=14
  3. Calculate the remainder when divided by 97
  4. If the remainder is 1, the IBAN is valid

Walk-Through: DE89370400440532013000

Step 1: Move first 4 to end
  370400440532013000DE89
  → 370400440532013000131489  (D=13, E=14)

Step 2: MOD-97
  370400440532013000131489 % 97 = 1

Result: 1 → Valid ✓

The challenge with big numbers: this is a 24+ digit number, which exceeds JavaScript's Number.MAX_SAFE_INTEGER (2^53). You need to process it in chunks.

JavaScript Implementation

function validateIBAN(input) {
  // 1. Clean and uppercase
  const iban = input.replace(/\s/g, '').toUpperCase();

  // 2. Basic format check
  if (!/^[A-Z]{2}\d{2}[A-Z0-9]{4,30}$/.test(iban)) {
    return { valid: false, reason: 'Invalid IBAN format' };
  }

  // 3. Check country-specific length
  const lengths = {
    DE: 22, GB: 22, FR: 27, ES: 24, IT: 27, NL: 18,
    BE: 16, AT: 20, CH: 21, SE: 24, NO: 15, DK: 18,
    FI: 18, PL: 28, PT: 25, IE: 22, LU: 20, CZ: 24,
    // ... more countries
  };

  const country = iban.substring(0, 2);
  if (lengths[country] && iban.length !== lengths[country]) {
    return { valid: false, reason: `${country} IBAN must be ${lengths[country]} characters` };
  }

  // 4. MOD-97 check
  // Move first 4 chars to end
  const rearranged = iban.substring(4) + iban.substring(0, 4);

  // Convert letters to numbers
  let numeric = '';
  for (const char of rearranged) {
    if (char >= 'A' && char <= 'Z') {
      numeric += (char.charCodeAt(0) - 55).toString();
    } else {
      numeric += char;
    }
  }

  // MOD-97 on large number (process in chunks)
  let remainder = 0;
  for (let i = 0; i < numeric.length; i++) {
    remainder = (remainder * 10 + parseInt(numeric[i])) % 97;
  }

  if (remainder !== 1) {
    return { valid: false, reason: 'Checksum failed (MOD-97)' };
  }

  return {
    valid: true,
    country,
    check_digits: iban.substring(2, 4),
    bban: iban.substring(4),
    formatted: iban.replace(/(.{4})/g, '$1 ').trim(),
  };
}

validateIBAN('DE89 3704 0044 0532 0130 00');
// { valid: true, country: "DE", check_digits: "89",
//   bban: "370400440532013000",
//   formatted: "DE89 3704 0044 0532 0130 00" }

The key trick is the chunk-based MOD-97 on line 33-36. Instead of converting the entire string to a BigInt, we process digit by digit, taking the modulus at each step. This keeps the number small and works in any JavaScript environment.

DataCheck validates IBANs for 45+ countries with bank code extraction.
Try it free →

Extracting the Bank Code

The BBAN contains the bank code, but its position varies by country:

CountryBank Code PositionExample
Germany (DE)Characters 5-12 (8 digits)37040044
UK (GB)Characters 5-8 (4 letters)NWBK
France (FR)Characters 5-9 (5 digits)30006
Netherlands (NL)Characters 5-8 (4 letters)ABNA
Spain (ES)Characters 5-8 (4 digits)2100
function extractBankCode(iban, country) {
  const bankCodeLengths = {
    DE: 8, GB: 4, FR: 5, NL: 4, ES: 4,
    IT: 5, BE: 3, AT: 5, CH: 5, SE: 3,
  };

  const len = bankCodeLengths[country];
  if (!len) return null;

  return iban.substring(4, 4 + len);
}

Common Mistakes

1. Not handling spaces

IBANs are often displayed with spaces (DE89 3704 0044...) but stored without them. Always strip spaces before validation.

2. Case sensitivity

IBANs can be entered in lowercase. Always convert to uppercase before processing — the letter-to-number conversion depends on it.

3. Skipping the length check

An IBAN that passes MOD-97 but has the wrong length for its country is still invalid. A German IBAN must be exactly 22 characters — no more, no less.

4. Using parseInt on the full number

parseInt("370400440532013000131489") loses precision because it exceeds 2^53. Always use the chunk method or BigInt.

Using the DataCheck API

If you'd rather not maintain country-specific length tables and bank code extraction logic:

const res = await fetch(
  'https://datacheck.dev/api/validate?input=DE89370400440532013000&type=iban'
);
const data = await res.json();

// {
//   valid: true,
//   formatted: "DE89 3704 0044 0532 0130 00",
//   country: "DE",
//   details: {
//     country: "Germany",
//     check_digits: "89",
//     bban: "370400440532013000",
//     bank_code: "37040044"
//   }
// }

Test IBANs for Development

CountryValid Test IBAN
GermanyDE89 3704 0044 0532 0130 00
UKGB29 NWBK 6016 1331 9268 19
FranceFR76 3000 6000 0112 3456 7890 189
SpainES91 2100 0418 4502 0005 1332
NetherlandsNL91 ABNA 0417 1643 00
SwitzerlandCH93 0076 2011 6238 5295 7
BelgiumBE68 5390 0754 7034
NorwayNO93 8601 1117 947

Wrapping Up

IBAN validation comes down to three checks: format (letters + digits), country-specific length, and MOD-97 checksum. The tricky part is the big-number arithmetic, which the chunk-based approach solves cleanly.

For apps that just need to verify IBANs and extract bank codes, the 40-line implementation above works perfectly. For production use with 45+ countries and always-current formats, consider using an API.

Validate IBANs, phone numbers, credit cards, VAT IDs, and postal codes with one API call.
Get your free API key →