<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Oyinlola Abolarin</title>
    <description>The latest articles on DEV Community by Oyinlola Abolarin (@khris_breezy).</description>
    <link>https://dev.to/khris_breezy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3880722%2Fbd535630-b844-45d9-890d-465b833fd287.jpg</url>
      <title>DEV Community: Oyinlola Abolarin</title>
      <link>https://dev.to/khris_breezy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/khris_breezy"/>
    <language>en</language>
    <item>
      <title>I Got Tired of Copy-Pasting IBAN Validation Code Across Every Project — So I Built Two Open Source Packages</title>
      <dc:creator>Oyinlola Abolarin</dc:creator>
      <pubDate>Wed, 15 Apr 2026 15:02:07 +0000</pubDate>
      <link>https://dev.to/khris_breezy/i-got-tired-of-copy-pasting-iban-validation-code-across-every-project-so-i-built-two-open-source-3n6l</link>
      <guid>https://dev.to/khris_breezy/i-got-tired-of-copy-pasting-iban-validation-code-across-every-project-so-i-built-two-open-source-3n6l</guid>
      <description>&lt;p&gt;&lt;em&gt;Announcing iban_validator for Flutter/Dart and iban-validate for TypeScript/JavaScript&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;There is a piece of code I have written at least four times in the last two years.&lt;/p&gt;

&lt;p&gt;It strips spaces from a string, converts letters to numbers, rearranges some characters, and computes a modular arithmetic checksum. It validates IBAN numbers, the international bank account format used for cross-border payments, and it lives in a different file in a different language in every project I have ever worked on that needed it.&lt;/p&gt;

&lt;p&gt;Flutter app? I write it in Dart. React dashboard? I write it in TypeScript. New project six months later? I find the old file, copy it across, tweak it slightly, and inevitably introduce a subtle bug that only shows up when a user from Norway tries to make a payment because Norwegian IBANs are 15 characters and I hardcoded 16 somewhere.&lt;/p&gt;

&lt;p&gt;I got tired of it. So I built it properly.&lt;/p&gt;

&lt;p&gt;Today, I am releasing two open source packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;iban_validator&lt;/code&gt;&lt;/strong&gt; for Dart and Flutter — &lt;a href="https://pub.dev/packages/iban_validator" rel="noopener noreferrer"&gt;pub.dev/packages/iban_validator&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;iban-validate&lt;/code&gt;&lt;/strong&gt; for TypeScript and JavaScript — &lt;a href="https://www.npmjs.com/package/iban-validate" rel="noopener noreferrer"&gt;npmjs.com/package/iban-validate&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both support 116 countries, implement the official ISO 7064 MOD-97–10 validation algorithm, return typed errors with human-readable messages, and have zero production dependencies.&lt;/p&gt;

&lt;p&gt;This article explains why I built them, how the algorithm works, what makes them different from existing solutions, and how to use them in your project.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is an IBAN and why does validation matter?
&lt;/h2&gt;

&lt;p&gt;IBAN stands for International Bank Account Number. If you have sent money internationally, especially within Europe, or to the Middle East, you have used one. They look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DE89 3704 0044 0532 0130 00   ← Germany
GB29 NWBK 6016 1331 9268 19   ← United Kingdom
SA44 2000 0001 2345 6789 1234  ← Saudi Arabia
CI93 CI00 8011 1301 1342 9120 0589  ← Ivory Coast
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first two characters are the ISO country code. The next two are check digits. The rest is the domestic bank account number in a country-specific format. Every country that uses IBAN has a fixed, registered length. Germany is always 22 characters, Norway is always 15, and Malta is always 31.&lt;/p&gt;

&lt;p&gt;What makes IBAN genuinely interesting from an engineering perspective is that &lt;strong&gt;the check digits are mathematically derived from the rest of the number&lt;/strong&gt;. This means you can detect errors, transposed digits, missing characters, typos, before you ever attempt to send the payment.&lt;/p&gt;

&lt;p&gt;In fintech, that matters. A failed international transfer is not just an inconvenience. It can mean frozen funds, customer support tickets, refund delays, and, in some cases, fees charged by intermediate banks for routing a payment that bounced. Catching a bad IBAN at the moment a user types it, rather than after submission, is genuinely valuable.&lt;/p&gt;




&lt;h2&gt;
  
  
  How the validation algorithm works
&lt;/h2&gt;

&lt;p&gt;The algorithm is defined in ISO 7064 and has five steps. I want to walk through it properly because understanding it will make the code make sense.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 — Clean the input
&lt;/h3&gt;

&lt;p&gt;Strip all spaces and convert to uppercase. Users type IBANs in all sorts of formats with spaces, without spaces, in lowercase. The algorithm does not care about any of that. Normalise first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="s2"&gt;"de89 3704 0044 0532 0130 00"&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"DE89370400440532013000"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2 — Validate the country and length
&lt;/h3&gt;

&lt;p&gt;The first two characters identify the country. Every IBAN-supporting country has a fixed, registered length defined by the SWIFT IBAN Registry. Germany’s IBANs are always 22 characters. If you receive a 21-character string starting with DE, it is wrong before you even look at the checksum.&lt;/p&gt;

&lt;p&gt;This step alone catches a large proportion of errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 — Rearrange the string
&lt;/h3&gt;

&lt;p&gt;Move the first four characters of the country code plus the two check digits to the end of the string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="s2"&gt;"DE89370400440532013000"&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"370400440532013000DE89"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4 — Convert letters to numbers
&lt;/h3&gt;

&lt;p&gt;Replace every letter with its numeric equivalent: A=10, B=11, C=12, and so on up to Z=35. This converts the alphanumeric string into a pure digit string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="s2"&gt;"370400440532013000DE89"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"370400440532013000"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"13"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"14"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"89"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3704004405320130001314 89"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;D becomes 13, E becomes 14, because D is the 4th letter (A=10, B=11, C=12, D=13).&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5 — Compute mod 97
&lt;/h3&gt;

&lt;p&gt;Interpret the entire digit string as a large integer and compute its remainder when divided by 97. If the remainder equals exactly 1, the IBAN is valid.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;3704004405320130001314 89  mod  97  =  1  ✓
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The mathematical reason this works is rooted in number theory; the check digits were specifically chosen during IBAN generation to make this remainder equal 1. Any single-character error or transposition will (in virtually all cases) produce a different remainder.&lt;/p&gt;

&lt;h3&gt;
  
  
  The integer overflow problem
&lt;/h3&gt;

&lt;p&gt;Here is the engineering challenge: that digit string can be up to 34 characters long, representing a number around 1⁰³⁴. JavaScript’s Number type can only safely represent integers up to about 9×10¹⁵. Dart int handles arbitrary sizes natively on VM platforms, but for portability across web and mobile, you want to avoid relying on that.&lt;/p&gt;

&lt;p&gt;The solution is to process the digit string in 7-character chunks, carrying the remainder forward at each step. The result after all chunks is mathematically identical to computing mod 97 on the entire number in one go, and every intermediate value stays well within safe integer range on every platform.&lt;/p&gt;

&lt;p&gt;No BigInt. No external dependencies. Just arithmetic.&lt;/p&gt;




&lt;h2&gt;
  
  
  What was missing from existing solutions
&lt;/h2&gt;

&lt;p&gt;Before building these packages, I looked at what existed. The picture was not great.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;European-only coverage&lt;/strong&gt;. Most IBAN libraries were built by European developers for European use cases. They covered SEPA countries well and quietly ignored the rest of the world. If you needed to validate a Bahraini IBAN (BH, 22 characters) or a Kazakh IBAN (KZ, 20 characters), You were on your own.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Boolean returns&lt;/strong&gt;. The majority of libraries returned true or false. That is fine for a basic check, but useless for building good user experiences. When validation fails, your UI needs to know why to show the right error message, to highlight the right field, and to give the user actionable guidance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No metadata&lt;/strong&gt;. Length constraints, SEPA membership, and sample IBANs were not available. You could not build a country picker that showed only supported countries, or a length hint that updated as the user selected their country.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Abandonment&lt;/strong&gt;. Several of the most-starred packages had not been updated in two or three years. The IBAN registry is not static; new countries are added, and formats occasionally change.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I built instead
&lt;/h2&gt;

&lt;h3&gt;
  
  
  116 countries
&lt;/h3&gt;

&lt;p&gt;The official SWIFT IBAN Registry has 94 registered countries as of March 2026. I added 22 more, mostly in Africa, that have adopted IBAN-like formats locally but are not yet formally registered. These include the Ivory Coast, Senegal, Mali, Cameroon, Togo, Burkina Faso, Benin, Niger, and others. They are flagged as isExperimental: true in the registry so you can make an informed decision about whether to trust them in production.&lt;/p&gt;

&lt;p&gt;The African coverage matters to me personally. A significant amount of fintech development is happening across West and East Africa right now, and developer tooling often lags behind. If you are building a payment product for this market, you need these country codes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Typed errors
&lt;/h3&gt;

&lt;p&gt;Both packages return a result object with a typed error and a human-readable message.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Flutter / Dart&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IbanValidator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'DE99370400440532013000'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// IbanValidationError.checksumFailed&lt;/span&gt;

  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;errorMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// "The mod-97 checksum failed. The IBAN contains an error."&lt;/span&gt;

  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;countryInfo&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;countryName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// "Germany"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// TypeScript / JavaScript&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DE99370400440532013000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// 'checksumFailed'&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errorMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// 'The mod-97 checksum failed. The IBAN contains an error.'&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;countryInfo&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;countryName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// 'Germany'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The possible error values are:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;emptyInput&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Input was empty&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tooShort&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fewer than 4 characters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;invalidCharacters&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Contains characters outside A–Z and 0–9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;unknownCountry&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Country code not in the registry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;countryMismatch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Doesn't match the country constraint you passed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;invalidLength&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Wrong length for the country&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;checksumFailed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The mod-97 check failed, likely a typo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This means you can show specific, actionable error messages rather than a generic "invalid IBAN" that leaves the user guessing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Country metadata
&lt;/h3&gt;

&lt;p&gt;Both packages expose a full country registry you can query at runtime.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Dart&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IbanValidator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCountryInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'CI'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;countryName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// 'Ivory Coast'&lt;/span&gt;
&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ibanLength&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// 28&lt;/span&gt;
&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isSepa&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;         &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isExperimental&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;example&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;        &lt;span class="c1"&gt;// 'CI93CI0080111301134291200589'&lt;/span&gt;

&lt;span class="c1"&gt;// Useful for building country pickers, length hints, etc.&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;sepaCountries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IbanValidator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getSepaCountries&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;africanCountries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IbanValidator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getExperimentalCountries&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// TypeScript&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getCountryInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SA&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;countryName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 'Saudi Arabia'&lt;/span&gt;
&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ibanLength&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// 24&lt;/span&gt;
&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isSepa&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;      &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// 'SA4420000001234567891234'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Consistent API across both ecosystems
&lt;/h3&gt;

&lt;p&gt;This was the design constraint I cared about most. If you use both packages, Flutter for mobile, React for web, the mental model should be identical.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flutter/Dart&lt;/th&gt;
&lt;th&gt;TypeScript/JS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;IbanValidator.isValid(iban)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;isValid(iban)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;IbanValidator.validate(iban)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;validate(iban)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;IbanValidator.getCountryInfo('DE')&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;getCountryInfo('DE')&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;IbanValidator.getSepaCountries()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;getSepaCountries()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Same country registry. Same validation logic. Same error vocabulary. Your mobile and web products behave identically, and switching between codebases does not require context-switching in your head.&lt;/p&gt;




&lt;h2&gt;
  
  
  Using the packages in practice
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Flutter
&lt;/h3&gt;

&lt;p&gt;Add to &lt;code&gt;pubspec.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;iban_validator&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^1.0.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basic form validation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:iban_validator/iban_validator.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;TextFormField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;decoration:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;InputDecoration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;labelText:&lt;/span&gt; &lt;span class="s"&gt;'IBAN'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nl"&gt;validator:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;'Please enter your IBAN.'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IbanValidator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isValid&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;errorMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Country-constrained validation (when your app already knows the user's country):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IbanValidator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;ibanInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;countryCca2:&lt;/span&gt; &lt;span class="n"&gt;selectedCountryCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// e.g. 'FR', 'AE', 'CI'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TypeScript / JavaScript
&lt;/h3&gt;

&lt;p&gt;Install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;iban-validate
&lt;span class="c"&gt;# or&lt;/span&gt;
yarn add iban-validate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With React Hook Form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isValid&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;iban-validate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;iban&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Please enter a valid IBAN.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Zod:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isValid&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;iban-validate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;iban&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;refine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Please enter a valid IBAN.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a Next.js API route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;validate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;iban-validate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;iban&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;iban&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errorMessage&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;422&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Safe to use result.cleanedIban from here&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cleanedIban&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CommonJS also works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isValid&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;iban-validate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DE89 3704 0044 0532 0130 00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What is next
&lt;/h2&gt;

&lt;p&gt;A few things I want to add in upcoming versions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Format helpers.&lt;/strong&gt; A &lt;code&gt;formatIban&lt;/code&gt; function that takes a raw IBAN string and returns it in the standard human-readable grouped format (&lt;code&gt;DE89 3704 0044 0532 0130 00&lt;/code&gt;). Useful for display.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;More African countries.&lt;/strong&gt; The continent is rapidly adopting IBAN and I want to stay ahead of that. Several countries are in the process of formal SWIFT registration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BBAN extraction.&lt;/strong&gt; Pull out the domestic bank code and account number from the IBAN for countries where the format is well-defined. This would let you display the sort code from a UK IBAN or the Bankleitzahl from a German one.&lt;/p&gt;

&lt;p&gt;If there is something you need that is not there, open an issue on GitHub. PRs are very welcome.&lt;/p&gt;




&lt;h2&gt;
  
  
  Find the packages
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Flutter / Dart&lt;/strong&gt;&lt;br&gt;
pub.dev → &lt;a href="https://pub.dev/packages/iban_validator" rel="noopener noreferrer"&gt;pub.dev/packages/iban_validator&lt;/a&gt;&lt;br&gt;
GitHub → &lt;a href="https://github.com/khrisbreezy/iban_validator" rel="noopener noreferrer"&gt;github.com/khrisbreezy/iban_validator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TypeScript / JavaScript&lt;/strong&gt;&lt;br&gt;
npm → &lt;a href="https://www.npmjs.com/package/iban-validate" rel="noopener noreferrer"&gt;npmjs.com/package/iban-validate&lt;/a&gt;&lt;br&gt;
GitHub → &lt;a href="https://github.com/khrisbreezy/iban-validation" rel="noopener noreferrer"&gt;github.com/khrisbreezy/iban-validation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both are MIT licensed. If you use them, the best thing you can do is star the GitHub repos and leave a like on pub.dev. It helps other developers find them.&lt;/p&gt;

&lt;p&gt;And if you are building something in fintech, especially for African or Middle Eastern markets, I would genuinely love to hear what you are working on.&lt;/p&gt;




</description>
      <category>flutter</category>
      <category>dart</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
