Check an IBAN as someone types
Add IBAN structure and checksum feedback to an existing field with form.js.
On this page
Working example
HTML + form.jsMark your IBAN field
Include form.js once and add data-parse="iban" to a text input. An IBAN contains letters and may contain leading zeroes, so keep it out of a number input.
<script src="https://cdn.parseapi.com/v1/form.js" data-key="YOUR_PUBLIC_API_KEY" defer></script>
<div class="field">
<label for="iban">IBAN</label>
<input id="iban" name="iban" data-parse="iban" autocomplete="off" autocapitalize="characters" spellcheck="false" placeholder="DE89 3704 0044 0532 0130 00">
</div>
<div class="field">
<label for="bank-name">Bank name, when known</label>
<input id="bank-name" data-parse-from="iban" data-parse-fill="bank_name" readonly>
</div>
<div class="field">
<label for="bank-bic">BIC, when known</label>
<input id="bank-bic" data-parse-from="iban" data-parse-fill="bic" readonly>
</div>Replace YOUR_PUBLIC_API_KEY with a Public key from the example setup. Allow your site's hostname and localhost for local development. Serve the downloaded HTML over HTTP; keep secret keys on your server.
The person can paste spaces or hyphens, or type lowercase ASCII letters. Other punctuation and Unicode lookalikes receive an input error. The script checks after a typing pause and sends the input in the body of POST /bank, never in the lookup URL. Keep account input and returned data out of your own analytics and logs. The API checks the number's country-specific length, structure, and checksum, and the script shows feedback beside the field.
Check the number
Try DE89 3704 0044 0532 0130 00. Change its last digit to 1 to see a checksum failure. The preset shows the first correction from issues and reads the API's valid answer; a successful HTTP request alone does not mean the number passed.
Editing the IBAN clears the old verdict. A failed request leaves the field unchecked. Submission remains your form's job, and the script never waits for a pending lookup before allowing it.
Need the bank name in an existing field? Add data-parse-from="iban" data-parse-fill="bank_name" to that field. Unknown bank details stay blank.
The parse event includes answer.checks and answer.issues. Checks report passed, failed, not_checked, or not_supported. A national check marked not_supported does not invalidate the IBAN. Bind an existing output with data-parse-from="iban" data-parse-fill="issues.0.message" to show the first issue, or data-parse-fill="checks.checksum" to show its checksum state. Diagnostic bindings work for invalid results too.
Use data-parse-country="DE" only when the country prefix is missing; the input must still include its two numeric check digits. After changing that attribute, call parseform.scan() to refresh the result.
A valid structure and checksum do not prove account existence, ownership, or payment eligibility. Build directly with the Bank API for the full response and a custom integration.
Handle the result on your server
Use the API again when your application needs to make a decision; browser feedback is field assistance. Keep the secret key on your server. This request preserves leading zeros and distinguishes a service failure from an invalid IBAN:
const response = await fetch('https://api.parseapi.com/bank', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.PARSE_API_KEY,
'Parse-Version': '2.0.0',
},
body: JSON.stringify({ iban: input }),
});
if (!response.ok) throw new Error('Bank check unavailable; retry later.');
const answer = await response.json();
if (!answer.valid) {
// Render as text beside the relevant input. Keep future issue codes supported.
return { error: answer.issues[0]?.message ?? 'Check the IBAN.' };
}
return { iban: answer.iban, bank: answer.bank_name, bic: answer.bic };A null bank name or BIC is not an invalid-account verdict. Keep it null or leave its optional field blank. This check does not establish account existence, ownership or payment eligibility. POST keeps account input out of the request URL; it does not prevent body or response logging elsewhere in your application.
Complete example
One HTML file with your fields, styles, and the form.js include. Replace YOUR_PUBLIC_API_KEY with your public key, then run it on a domain you have added to that key.
View and copy the complete source
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Check an IBAN as someone types</title>
<style>
:root { color-scheme: light dark; --bg: #fff; --ink: #152029; --muted: #5e6b75; --line: #d9e2e7; --field: #f6f9fa; --accent: #007c91; --error: #b42335; }
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) { --bg: #0b1015; --ink: #eff7fa; --muted: #94a6b2; --line: #2c3942; --field: #121b23; --accent: #67e8f9; --error: #fda4af; }
}
:root[data-theme="dark"] { color-scheme: dark; --bg: #0b1015; --ink: #eff7fa; --muted: #94a6b2; --line: #2c3942; --field: #121b23; --accent: #67e8f9; --error: #fda4af; }
:root[data-theme="light"] { color-scheme: light; }
* { box-sizing: border-box; }
[hidden] { display: none !important; }
body { margin: 0; padding: 24px; background: var(--bg); color: var(--ink); font: 15px/1.5 system-ui, sans-serif; }
main { max-width: 540px; margin: 0 auto; }
label { display: block; margin-bottom: 8px; font-size: 14px; font-weight: 600; }
input { display: block; width: 100%; min-width: 0; padding: 13px 14px; border: 1px solid var(--line); border-radius: 8px; background: var(--field); color: var(--ink); font: inherit; }
input::placeholder { color: var(--muted); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Your form owns these styles. form.js adds semantic markup and states. */
input[data-parse-status="invalid"], input[data-parse-status="disposable"] { border-color: var(--error); }
.parse-hint { margin: 6px 0 0; color: var(--muted); font-size: .875em; line-height: 1.4; overflow-wrap: anywhere; }
.parse-hint[data-parse-status="invalid"], .parse-hint[data-parse-status="disposable"] { color: var(--error); }
@media (max-width: 380px) { body { padding: 18px; } }
</style>
</head>
<body>
<main>
<!-- example:form -->
<script src="https://cdn.parseapi.com/v1/form.js" data-key="YOUR_PUBLIC_API_KEY" defer></script>
<div class="field">
<label for="iban">IBAN</label>
<input id="iban" name="iban" data-parse="iban" autocomplete="off" autocapitalize="characters" spellcheck="false" placeholder="DE89 3704 0044 0532 0130 00">
</div>
<div class="field">
<label for="bank-name">Bank name, when known</label>
<input id="bank-name" data-parse-from="iban" data-parse-fill="bank_name" readonly>
</div>
<div class="field">
<label for="bank-bic">BIC, when known</label>
<input id="bank-bic" data-parse-from="iban" data-parse-fill="bic" readonly>
</div>
<!-- /example:form -->
</main>
</body>
</html>
Need a key? Set up this browser example. For every field and parameter, see Bank API reference.