If you are testing a SEPA transfer, a direct debit mandate, or any bank transfer integration, you need IBANs with correct check digits. This tool produces synthetic IBANs in each country’s own format, with valid ISO 7064 MOD-97-10 check digits, and validates ones you paste in. None of them is attached to a real account.

Test data only

IBAN Generator and Validator

Synthetic IBANs with correct ISO 7064 MOD-97-10 check digits, in each country's own format. Generated in your browser and linked to no account anywhere.

    These IBANs have valid check digits and the right shape for the country, which is what makes them useful for testing. They identify no account, and no money can be sent to or from one.

    IBAN structure

    An IBAN is three fields glued together:

    TR33 0006 1005 1978 6457 8413 26
    └┬┘ └┬┘ └──────────────┬───────┘
     │   │                 │
     │   │                 └── BBAN (Basic Bank Account Number) — country-specific
     │   └──────────────────── Check digits (ISO 7064 MOD-97-10)
     └──────────────────────── Country code (ISO 3166-1 alpha-2)
    

    The country code and check digits are universal. Everything after them is the BBAN, and its internal structure is decided by each country’s banking authority — typically a bank code, sometimes a branch code, the domestic account number, and in several countries a national check digit of its own that predates the IBAN entirely.

    That is the key thing to understand: the IBAN did not replace domestic account numbering. It wrapped it. A German IBAN contains the same Bankleitzahl and account number a German transfer always used; a British one contains the same sort code and account number. Only the outer layer is international.

    How the IBAN check digits work

    The algorithm is ISO 7064 MOD-97-10, and it runs in four steps:

    1. Move the first four characters — country code and check digits — to the end.
    2. Replace every letter with a number: A = 10, B = 11, through Z = 35.
    3. Read the result as one very large integer and take it modulo 97.
    4. A valid IBAN leaves a remainder of exactly 1.

    To produce check digits rather than verify them, put 00 in their place, run the same calculation, and subtract the remainder from 98.

    Why it is stronger than Luhn

    Luhn catches single-digit errors and most adjacent transpositions. MOD-97-10 catches all single-character errors, all transpositions of adjacent characters, and the overwhelming majority of other common mistakes — the probability of a random error slipping through is about 1 in 97. That difference matters when a mistyped account number sends money to a stranger rather than just failing a form.

    The comparison is worth holding onto when you work on both. A card number that fails Luhn validation is almost certainly mistyped, but a card number that passes tells you very little. An IBAN that passes MOD-97 is far stronger evidence that the characters are as the sender intended — still not evidence that the account exists, but a much narrower gap.

    The BigInt trap

    function isValidIban(iban) {
      const s = iban.replace(/\s+/g, '').toUpperCase();
      if (!/^[A-Z]{2}\d{2}[A-Z0-9]{11,30}$/.test(s)) return false;
    
      const rearranged = s.slice(4) + s.slice(0, 4);
      const numeric = rearranged.replace(/[A-Z]/g, (c) => c.charCodeAt(0) - 55);
    
      return BigInt(numeric) % 97n === 1n;
    }
    
    console.log(isValidIban('GB82 WEST 1234 5698 7654 32')); // true
    

    BigInt is not a stylistic choice here. Letters expand to two digits each, so a 31-character Maltese IBAN becomes a 45-digit integer — around twenty digits past what a JavaScript number represents exactly.

    Here is the failure, using the published Maltese example MT84 MALT 0110 0001 2345 MTLC AST0 01S. After rearranging and substituting letters, the numeric string is 45 characters long:

    • Number(numeric) % 97 returns 41
    • BigInt(numeric) % 97n returns 1

    The first result is not an error. Nothing throws, nothing warns, and the function confidently returns false for a perfectly valid IBAN. The symptom that gives it away is that short IBANs validate correctly and long ones fail — which reads like a country-specific bug and sends people looking in entirely the wrong place. The same applies in any language where the default integer type is 64-bit: use arbitrary precision, or feed the digits through the modulo in chunks.

    IBAN length by country

    CountryCodeLengthCountryCodeLength
    AlbaniaAL28ItalyIT27
    AustriaAT20LatviaLV21
    BelgiumBE16LithuaniaLT20
    BulgariaBG22LuxembourgLU20
    CroatiaHR21MaltaMT31
    CyprusCY28NetherlandsNL18
    CzechiaCZ24NorwayNO15
    DenmarkDK18PolandPL28
    EstoniaEE20PortugalPT25
    FinlandFI18RomaniaRO24
    FranceFR27SlovakiaSK24
    GermanyDE22SloveniaSI19
    GreeceGR27SpainES24
    HungaryHU28SwedenSE24
    IcelandIS26SwitzerlandCH21
    IrelandIE22TürkiyeTR26
    United KingdomGB22

    Norway at 15 and Malta at 31 are the extremes, and the sixteen-character spread between them is the argument against every fixed-length assumption. The standard permits up to 34, so even Malta is not the ceiling — a country could be added tomorrow that is longer.

    Sources: ISO 13616 / IBAN standard and the SWIFT IBAN Registry · Verified: 2026-08-04

    Testing SEPA and bank transfer flows

    • Length validation per country. Derive the expected length from the country code rather than accepting anything in a range. The tool above rejects a German IBAN of 21 characters and says why, which is the behaviour to copy.
    • Checksum validation. Run MOD-97 server-side as well as in the browser, with arbitrary precision arithmetic on both sides.
    • BIC handling. Under the SEPA IBAN-only rule the BIC is generally not required for euro transfers. If your form demands one, check whether it actually needs it.
    • Direct debit mandates. A mandate references the IBAN, so test what happens when a customer changes bank — the mandate has to be re-established, and a flow that silently keeps the old IBAN fails collection later, quietly.
    • Error message quality. “Invalid IBAN” tells a customer nothing. “That IBAN is 21 characters; German IBANs are 22” tells them where to look.

    Five mistakes that account for most of it

    1. Assuming a fixed length. Covered above, and still the most common.
    2. Using a normal number type for MOD-97. Also covered, and the hardest to diagnose.
    3. Storing the IBAN with spaces. Display in groups of four; store and compare without them. Otherwise DE89 3704… and DE893704… are two different rows.
    4. Rejecting lowercase input. People type lowercase. Normalise to uppercase before validating rather than telling them off.
    5. Not validating the country code. Two letters that are not an ISO 3166-1 country cannot be a valid IBAN, and checking that first produces a much better error message than a checksum failure.

    IBAN and PCI DSS

    A useful boundary to be clear about: an IBAN is not in scope for PCI DSS. That standard governs payment card data — primary account numbers, security codes, magnetic stripe contents — and a bank account identifier is none of those. Building your bank transfer flow does not drag it into your cardholder data environment.

    It is not unregulated, though. An IBAN attached to a person is personal data under GDPR, with the same obligations as any other customer record: a lawful basis, a retention period, and a breach notification duty if it leaks. That is precisely why synthetic IBANs belong in your test environment — the same reasoning as for the test identity generator, and a different compliance regime from the card side rather than a lighter one.

    For card rather than bank data, the all-network generator produces full records and the bulk generator does it at volume with reproducible seeds. The tool directory lists everything else, and the FAQ covers what a checksum does and does not prove. The payment form testing checklist covers the wider form.

    Frequently Asked Questions

    International Bank Account Number. It is a standardised way of writing an existing domestic account number so that it can be recognised across borders — the country code and check digits are wrapped around the account identifier your bank already uses. An IBAN does not replace your account number; it packages it.
    No. They are structurally correct — the right length for the country, the right mix of letters and digits in the right places, and check digits that pass MOD-97 — but the bank and account portions are random within that shape. No financial institution has any of them on file.
    No. An IBAN is a pointer to an account, and these point at nothing. A transfer to one will be rejected, usually at the sending bank’s validation step and otherwise by the receiving scheme. If a transfer somehow entered the system it would be returned as unmatched, not delivered somewhere convenient.
    It depends entirely on the country: 15 characters in Norway, 31 in Malta, and most of Europe somewhere between. There is no universal length, and the standard caps it at 34. Any validation with a fixed length in it is wrong for most of the world.
    The IBAN identifies the account; the BIC, also called the SWIFT code, identifies the bank. They answer different questions. Within SEPA the BIC has largely become unnecessary — the IBAN-only rule means the receiving institution can be derived from the IBAN itself — so a form that still demands a BIC for a euro transfer is asking for something the payment does not need.
    Almost certainly because you are doing the modulo with a normal number type. A 31-character IBAN converts to a 45-digit integer, far beyond what a double holds exactly, so the arithmetic silently loses precision and the remainder comes out wrong. Use BigInt in JavaScript, or process the number in chunks. The symptom is distinctive: short IBANs validate fine and long ones fail for no visible reason.