Determines the SWIFT BIC of an IBAN. Currently supports IBANs from the following countries: Austria, Belgium, Germany, Spain, France, Lithuania, Luxembourg, Netherlands. Inspired by sigalor/iban-to-bic.
Pure Dart with no dependencies: works in Flutter apps, on Dart servers and CLIs, and on the web.
dart pub add iban_to_bic
or, in a Flutter app, flutter pub add iban_to_bic.
import 'package:iban_to_bic/iban_to_bic.dart';ibanToBic returns a sealed IbanLookupResult. Pattern-match on it to handle
every case exhaustively — no exceptions, no surprise nulls:
import 'package:iban_to_bic/iban_to_bic.dart';
void main() {
final result = ibanToBic('DE64 5001 0517 9423 8144 35');
switch (result) {
case BicFound(:final bic):
print(bic.value); // INGDDEFFXXX
print(bic.bankShortName); // ING-DiBa
print(bic.bankLocation); // Frankfurt am Main
case InvalidIban(:final iban, :final reason):
print('Invalid ($reason): $iban');
case UnsupportedCountry(:final countryCode):
print('No data for: $countryCode');
case UnknownBank(:final countryCode, :final bankCode):
print('Unknown bank $bankCode in $countryCode');
}
}Bank-code datasets ship inside the package as one deferred library per country and are parsed on first use, so the default path is async. On the web, each country's data is a separate JavaScript (or Wasm) file that is only downloaded when that country is first looked up. Two APIs:
// Async — no setup required:
final result = await ibanToBicAsync('DE64 5001 0517 9423 8144 35');
// Sync — call preload first (e.g. from main()):
await preloadIbanToBic(['DE', 'NL']);
final result = ibanToBic('DE64 5001 0517 9423 8144 35');Calling the sync ibanToBic for a country that hasn't been preloaded throws
StateError. If startup latency matters more than first-call latency,
preload; otherwise just use the async variant.
Every built-in dataset records where it came from and how old it is:
final info = dataInfo('DE');
print(info?.publisher); // Deutsche Bundesbank
print(info?.sourceUrl); // https://www.bundesbank.de/…/blz-aktuell-txt-data.txt
print(info?.retrievedOn); // 2026-10-29 00:00:00.000Z
print(info?.effectiveFrom); // 2026-09-07 00:00:00.000Z
print(info?.validUntil); // 2026-12-06 00:00:00.000Z
print(info?.ageInDays()); // days since retrievalFields the package doesn't know are null; notes explains why. Spain,
France and Lithuania were carried over from older releases without a
recorded source, so only their content hash (sha256) is set.
Implement SyncBicResolver for in-memory data, or BicResolver (returns
FutureOr<Bic?>) for async sources — an overlay on top of the built-in maps,
a corporate registry, the ECB directory, etc.
For a JSON file in the built-in format ({"<bank code>": {"bic": …, "bankName": …, "bankShortName": …}}), LazyJsonResolver takes any loader,
loads it on first use and supports preload/evict like the built-in data:
// Flutter asset (replaces the deprecated AssetJsonResolver):
LazyJsonResolver(() => rootBundle.loadString('assets/my_banks.json'));
// File on a server:
LazyJsonResolver(() => File('my_banks.json').readAsString());class EcbResolver implements BicResolver {
@override
Future<Bic?> resolve(String bankCode) async =>
await httpClient.fetchBic(bankCode);
}
final lookup = IbanToBic(countries: {
'DE': CountrySpec(
bankCodeStart: 4,
bankCodeEnd: 12,
resolver: EcbResolver(),
),
});
await lookup.lookup('DE64 5001 0517 9423 8144 35');| Code | Country | Bank-code offset | Data source | BIC accuracy | Automated refresh |
|---|---|---|---|---|---|
| AT | Austria | 4–9 | OeNB SEPA directory | exact | yes (weekly) |
| BE | Belgium | 4–7 | NBB bank identification codes | exact | yes (weekly) |
| DE | Germany | 4–12 | Deutsche Bundesbank BLZ file | exact | yes (weekly) |
| ES | Spain | 4–8 | ECB MFI list via sigalor/iban-to-bic (2024), no national source yet | institution | no (unmaintained) |
| FR | France | 4–9 | ECB MFI list via sigalor/iban-to-bic (2024), no national source yet | institution | no (unmaintained) |
| LT | Lithuania | 4–9 | not recorded (added in 0.0.5), no official source yet | exact | no (unmaintained) |
| LU | Luxembourg | 4–7 | ABBL IBAN/BIC register | exact | yes (weekly) |
| NL | Netherlands | 4–8 | Betaalvereniging BIC list | exact | yes (weekly) |
BIC accuracy is reported on every BicFound as accuracy
(BicAccuracy.exact or BicAccuracy.institution, with an isExact
shortcut):
- exact — the IBAN has no branch code, and the national directory assigns one BIC per bank code, so the result is the account's BIC (as of the dataset's date). The Bundesbank, for example, requires each BLZ's main record to carry a BIC that reaches the institution in every SEPA scheme.
- institution — the IBAN carries a branch code after the bank code
(Spain: oficina, France: code guichet) that the lookup does not use.
The result is the institution's main BIC, which SEPA payments to that
institution generally accept, but the account may be held under a branch
BIC. Every La Banque Postale IBAN starts with bank code
20041, for instance, yet accounts are held at regional centres with BICs such asPSSTFRPPPAR(Paris) orPSSTFRPPLIL(Lille); the lookup returnsPSSTFRPPXXX. Don't present such a BIC to users as verified for their account.
if (result case BicFound(:final bic, isExact: false)) {
print('${bic.value} identifies the bank; the branch BIC may differ.');
}If you register your own CountrySpec, pass accuracy: to match your data
(it defaults to BicAccuracy.exact).
The datasets are kept in data/bank_codes/<cc>.jsonl: one bank code per
line, sorted, so every change to the data shows up as a readable diff.
tool/refresh_data.dart refreshes them from each country's central bank
or competent authority, for the countries that have an adapter (AT, BE,
DE, LU and NL); a weekly workflow opens a pull request that lists the added, removed
and changed codes.
The library loads compact datasets generated from those files
(lib/src/data/<cc>.g.dart). After editing a .jsonl file by hand,
regenerate them with:
dart run tool/build_assets.dartThe code is MIT-licensed. The bank-code datasets in data/bank_codes/
(and the lib/src/data/*.g.dart files generated from them) are not: they
come from the publishers below, whose terms apply to them. See
NOTICE for the full attribution text and links.
| Code | Source | Terms (summary) |
|---|---|---|
| AT | OeNB SEPA directory | CC BY 4.0, credit the OeNB |
| BE | NBB bank identification codes | Free use, credit the NBB |
| DE | Bundesbank BLZ file | Free use, unaltered, "Quelle: Deutsche Bundesbank" |
| ES, FR | ECB list of MFIs, via sigalor/iban-to-bic (2024) | Free use, credit the ECB |
| LT | Not recorded; most likely the Bank of Lithuania code list | Not yet established |
| LU | ABBL IBAN-BIC register | Reference use, unmodified, credit the ABBL; redistribution not addressed |
| NL | Betaalvereniging BIC list | Personal, non-commercial use; redistribution needs written consent |
The data is provided as published, without warranty. If you need guaranteed
coverage or redistribution rights, plug in your own data with a custom
BicResolver (see Extending with custom data).