IBAN check digit generator
Country DE, bank code 37040044 and account 0532013000 give check digits 89 and the IBAN DE89370400440532013000. Build a complete IBAN from the domestic details for payroll, a SEPA file or an onboarding form, with a warning if the length looks wrong. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Country
- DE
- Bank
- 37040044
- Account
- 0532013000
- Bban
- 370400440532013000
- Check digits
- 89
- Iban
- DE89370400440532013000
- Iban formatted
- DE89 3704 0044 0532 0130 00
International payments, payroll files, and onboarding forms often need a complete IBAN before the counterparty ever sees the number. Banks issue domestic account details as a bank code plus an account number; the two ISO 13616 check digits that sit after the country code are not obvious to paste by hand. This IBAN check digit generator accepts a two-letter country code, a bank identifier, and an account number, builds the BBAN, rearranges it with the country and a zero placeholder, and applies the ISO 7064 mod 97-10 algorithm used by every SEPA and IBAN registry. You receive the compact IBAN, a space-grouped display form, the two check digits, the BBAN, and a short report of malformed parts such as wrong official length for that country.
How IBAN check digits are computed from country, bank and account
An IBAN always starts with a two-letter country code, then two decimal check digits, then a country-specific Basic Bank Account Number (BBAN). The BBAN is not invented by this tool: you supply the domestic pieces—typically a bank or sort code and an account number—and they are concatenated after stripping spaces and hyphens.
ISO 13616 then rearranges the string for checksumming: move the country code and the two check-digit positions to the end, put zeros in those check positions, map every letter A through Z to ten through thirty-five, and reduce the resulting digit string modulo ninety-seven. The official check value is ninety-eight minus that remainder, written as two digits from zero-zero through ninety-eight. Reassembling country, those two digits, and the BBAN yields the full IBAN.
A well-known German example is country DE, bank three-seven-zero-four-zero-zero-four-four, account zero-five-three-two-zero-one-three-zero-zero-zero, which produces check digits eighty-nine and IBAN DE89370400440532013000. Validation of a finished IBAN is the inverse check: rearrange and require remainder one. Generation never needs network access to a bank directory; it only needs correct domestic components for that country structure.
What you enter, what you get and the warnings
Country must normalize to exactly two A–Z letters. Bank and account must normalize to non-empty A–Z and zero–nine strings after spaces, hyphens, underscores, and dots are removed; letters are uppercased. Combined BBAN length must stay within thirty characters so the finished IBAN stays within the global thirty-four character limit.
The malformed array lists human-readable issues that did not block checksum computation: for example a generated length that does not match the registry length for DE or GB, or a country code outside that registry. Invalid input is not billed. Pair this generator with a separate IBAN validator if you need to re-check a string that already includes check digits.
What you can do with it
SEPA and payroll file prep
Turn ERP bank code and account columns into full IBANs with correct mod 97-10 check digits before generating credit-transfer or direct-debit batches.
Payout onboarding forms
Preview a compact and grouped IBAN from country, bank, and account fields so users confirm the number before it hits production payout rails.
QA oracles for payment code
Pin known vectors such as DE89370400440532013000 in CI so IBAN assembly and check-digit logic never drift across services.
FAQ
What algorithm do you use for the two check digits?
ISO 7064 MOD 97-10 as specified for IBAN in ISO 13616: rearrange BBAN + country + 00, map letters A–Z to 10–35, take 98 minus (value mod 97).
What does the malformed array mean?
Soft issues that still allow a checksum: wrong official length for a known country, or a country outside the built-in length registry.
Is this the same as validating an existing IBAN?
No. This capability generates check digits and a full IBAN from parts. To validate a complete IBAN string, use a dedicated IBAN validator capability.
Why does the tool warn that the length is wrong for my country?
Each country fixes the length of its IBAN; for Germany it is 22 characters. If your bank code and account do not add up to that length, the check digits are still calculated, but the warning tells you the domestic parts are probably incomplete or misplaced.
Does a generated IBAN prove that the account exists?
No. The tool only does the arithmetic on the parts you enter and never contacts a bank directory. If the bank code or account number is wrong, you get a correctly calculated IBAN for an account that may not exist.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/enc/iban-generate \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"country":"DE","bank":"37040044","account":"0532013000"}'const res = await fetch("https://api.kit.forhosting.com/enc/iban-generate", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"country": "DE",
"bank": "37040044",
"account": "0532013000"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/enc/iban-generate",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"country": "DE",
"bank": "37040044",
"account": "0532013000"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/enc/iban-generate", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"country":"DE","bank":"37040044","account":"0532013000"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"country":"DE","bank":"37040044","account":"0532013000"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/enc/iban-generate", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"country": "DE",
"bank": "37040044",
"account": "0532013000"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "enc.iban_generate",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Input contract, response fields, and how malformed parts are reported
POST a JSON body with three required fields: country (aliases country_code, cc, nation), bank (aliases bank_code, bank_id, sort_code, bic_bank), and account (aliases account_number, acct, account_no, iban_account). On success the body includes country, bank, account, bban, check_digits, iban, iban_formatted (groups of four), length, algorithm set to iso13616_mod97_10, and when the country is in the built-in official length table expected_length plus length_ok. Hard failures—missing fields, non-alphanumeric junk, country not two letters—throw invalid_input and name the malformed part in the message so clients can highlight the right form control.
Where an IBAN check digit generator earns its keep
SaaS onboarding flows collect country, bank, and account in separate fields and must show a preview IBAN before the user confirms a payout profile. QA and regression suites need a deterministic oracle for known vectors such as the German DE89 sample so CI fails when someone changes the mod-97 loop. Finance and ops teams build SEPA credit-transfer files from ERP exports that still store domestic bank and account columns; computing check digits in a tiny parse API avoids shipping a full banking library into every worker. Keep requests small, pin the returned iban and check_digits in tests, and treat malformed length warnings as soft signals that the domestic composition may not match the country’s BBAN layout even though the math itself is correct.
Technical questions
How do I generate IBAN check digits from country, bank and account?
Send country (two letters), bank, and account. The API builds the BBAN, applies ISO 13616 mod 97-10, and returns check_digits plus the full iban and iban_formatted strings.
What does the IBAN check digit generator cost?
The browser tool is free. API requests use prepaid KIT balance at $0.002 per successful call; invalid input is not billed.