Ultra-fast, zero-dependency IBAN & BIC toolkit for Java 8+
🚀 Quick Start • 📖 Examples • 📊 Benchmarks • 💬 Discussions
The iban-commons library provides simple, fast, and reliable validation and decomposition of International Bank Account Numbers (IBAN) and Business Identifier Codes (BIC).
Designed for high-performance enterprise applications, it intentionally has zero compile or runtime dependencies outside the Java Standard Library.
| Feature | iban-commons | Apache Commons | iban4j | garvelink java-iban |
|---|---|---|---|---|
| Performance | 5,257 ops/s | 4,786 ops/s | 814 ops/s | 863 ops/s |
| Dependencies | 0 | 5 | 0 | 0 |
| Memory | 137 MB/op | 327 MB/op | 1,627 MB/op | 1,126 MB/op |
| Java Version | 8+ | 8+ | 11+ | 8+ |
Maven:
<dependency>
<groupId>de.speedbanking</groupId>
<artifactId>iban-commons</artifactId>
<version>1.8.1</version>
</dependency>Gradle:
implementation 'de.speedbanking:iban-commons:1.8.1'import de.speedbanking.iban.Iban;
// throws InvalidIbanException if invalid
Iban iban = Iban.of("DE91100000000123456789");
// returns Optional<Iban>, does not throw
Optional<Iban> maybeIban = Iban.tryParse("GB82WEST12345698765432");
// validate without parsing
boolean valid = Iban.isValid("FR1420041010050500013M02606");Iban iban = Iban.of("IT60X0542811101000000123456");
iban.getCountryCode(); // "IT"
iban.getCountryName(); // "Italy"
iban.getCountryFlag(); // "🇮🇹"
iban.getBankCode(); // "05428"
iban.getBranchCode(); // "11101"
iban.getAccountNumber(); // "000000123456"
iban.toFormattedString(); // "IT60 X054 2811 1010 0000 0123 456"-
Zero Dependencies
Keep your build clean and avoid dependency conflicts
-
High Performance
Optimized for execution speed and minimum memory footprint. 6.4x faster than iban4j, 11.9x less memory allocation
-
Small Footprint
~100 kB JAR
-
Simple, intuitive API
Intuitive factory methods (
Iban.of(),Bic.tryParse()), clear component accessors -
Immutability
Both
IbanandBicclasses are immutable and thread-safe -
Java 8 compatibility
Built with and compiled for Java 8 for maximum reach, tested on recent LTS versions
-
Comprehensive Coverage
Full support for IBAN and BIC validation according to ISO 13616 and ISO 9362 standards. Supports 95+ countries from the SWIFT IBAN Registry
-
Rich Metadata
Access country names, flags, bank codes, SEPA status, and regulatory organization details
The API is designed for simplicity, focusing on two main ways to create a valid object: a throwing factory method for quick use and a safe parsing method using Optional.
The Iban class implements Serializable, CharSequence, and Comparable<Iban>.
Use Iban.of() or Iban.parse() when you prefer an exception for validation failures.
import de.speedbanking.iban.Iban;
import de.speedbanking.iban.InvalidIbanException;
String ibanInput = "DE91100000000123456789";
try {
Iban iban = Iban.of(ibanInput);
// getters
System.out.println("Country Code: " + iban.getCountryCode()); // DE
System.out.println("Check Digits: " + iban.getCheckDigits()); // 91
System.out.println("BBAN : " + iban.getBban()); // 100000000123456789
System.out.println("Bank Code : " + iban.getBankCode()); // 10000000
System.out.println("Account No : " + iban.getAccountNumber()); // 0123456789
// output
System.out.println("Normalized : " + iban.toString()); // DE91100000000123456789
System.out.println("Formatted : " + iban.toFormattedString()); // DE91 1000 0000 0123 4567 89
} catch (InvalidIbanException ex) {
System.out.println("IBAN validation failed: " + ex.getMessage());
}Use Iban.tryParse() when dealing with external or uncertain input and to avoid exceptions for control flow.
import de.speedbanking.iban.Iban;
import java.util.Optional;
Optional<Iban> optionalIban = Iban.tryParse("PS92PALS000000000400123456702");
optionalIban.ifPresent(iban -> {
println("Country Code: " + iban.getCountryCode()); // PS
println("Country Name: " + iban.getCountryName()); // Palestine
println("Country Flag: " + iban.getCountryFlag()); // 🇵🇸
println("Organisation: " + iban.getOrganisation()); // Palestine Monetary Authority
});Batch Processing:
List<String> ibanStrings = loadFromDatabase();
List<Iban> validIbans = ibanStrings.stream()
.map(Iban::tryParse)
.flatMap(Optional::stream)
.collect(Collectors.toList());SEPA Filtering:
Iban iban = Iban.of("CH9300762011623852957");
if (iban.isSepa()) {
processSepaPayment(iban);
} else {
processCrossBorderPayment(iban);
}The Bic class implements Serializable, CharSequence, and Comparable<Bic>.
A BIC comparison is always based on the 11-character representation (toBic11()), meaning BIC-8 and its BIC-11 equivalent are considered equal.
import de.speedbanking.bic.Bic;
// BIC-11
Bic bic11 = Bic.of("PALSPS22XXX"); // Bank of Palestine P.S.C.
System.out.println("Bank Code : " + bic11.getBankCode()); // PALS
System.out.println("Country Code : " + bic11.getCountryCode()); // PS
System.out.println("Location Code: " + bic11.getLocationCode()); // 22
System.out.println("Branch Code : " + bic11.getBranchCode()); // XXX
System.out.println("is BIC-11 : " + bic11.isBic11()); // true
System.out.println("is BIC-8 : " + bic11.isBic8()); // false
System.out.println("to BIC-8 : " + bic11.toBic8()); // PALSPS22
// BIC-8
Bic bic8 = Bic.of("MARKDEFF"); // Deutsche Bundesbank, Zentrale
System.out.println("is BIC-8 : " + bic8.isBic8()); // true
System.out.println("is BIC-11 : " + bic8.isBic11()); // false
System.out.println("to BIC-11 : " + bic8.toBic11()); // MARKDEFFXXXimport de.speedbanking.bic.Bic;
Bic.tryParse("INVALIDBIC").ifPresentOrElse(
bic -> System.out.println("Valid BIC: " + bic),
() -> System.err.println("Invalid BIC")
);// Before (iban4j)
import org.iban4j.CountryCode;
import org.iban4j.Iban;
import org.iban4j.IbanFormatException;
try {
Iban iban = new Iban.Builder()
.countryCode(CountryCode.DE)
.bankCode("37040044")
.accountNumber("0532013000")
.build();
} catch (IbanFormatException ex) { }
// After (iban-commons)
import de.speedbanking.iban.Iban;
Iban iban = Iban.of("DE89370400440532013000");// Before (Apache Commons Validator)
import org.apache.commons.validator.routines.IBANValidator;
IBANValidator validator = IBANValidator.getInstance();
boolean valid = validator.isValid("GB82WEST12345698765432");
// After (iban-commons)
import de.speedbanking.iban.Iban;
boolean valid = Iban.isValid("GB82WEST12345698765432");
// or parse for component access
Iban iban = Iban.of("GB82WEST12345698765432");iban-commons is designed for high throughput and minimal overhead.
We use the Java Microbenchmark Harness (JMH) to compare the throughput of iban-commons against popular Java IBAN libraries: iban4j, Apache Commons Validator, and garvelink java-iban.
The results below demonstrate the significant throughput advantage (operations per second) of iban-commons.
| Benchmark Operation | iban-commons (ops/s) | Apache Commons (ops/s) | garvelink java-iban (ops/s) | iban4j (ops/s) | Speedup vs. iban4j |
|---|---|---|---|---|---|
Pure Validation (.isValid()) |
5257 | 4786 | n/a | 814 | ~6.4x faster |
Object Creation (.tryParse()/.of()) |
2993 | n/a | 863 | 754 | ~3.9x faster |
These results, derived from the JMH GC Profiler, quantify the memory allocation overhead per operation (B/op). Lower values indicate less work for the Garbage Collector (GC).
| Benchmark Operation | iban-commons (B/op) | Apache Commons (B/op) | garvelink java-iban (B/op) | iban4j (B/op) | Allocation Efficiency |
|---|---|---|---|---|---|
Pure Validation (.isValid()) |
136.9M | 326.8M | n/a | 1627.3M | ~11.9x smaller vs. iban4j |
Object Creation (.tryParse()/.of()) |
253.9M | n/a | 1126.1M | 1633.7M | ~6.4x smaller vs. iban4j |
Note on Memory Units: The B/op values represent normalized allocations per benchmark operation. The relative difference confirms the high allocation efficiency of iban-commons.
- Leading Throughput:
iban-commonsoutperforms all tested libraries, reaching 5257 operations per second for validation. - Superior Object Creation: Compared to
garvelink java-iban,iban-commonsis about 3.4x faster and uses 4.4x less memory when creating immutable objects. - Minimal GC Pressure: With only 136.9M B/op for validation, the library requires significantly less allocation than Apache Commons (~2.4x) and iban4j (~11.9x).
The benchmarks were executed under the following configuration:
- Intel Core i7-1165G7 @ 2.80GHz (4 Cores, 8 Threads), 32 GiB RAM
- Ubuntu 24.04.3 LTS (Noble Numbat)
- OpenJDK 21.0.7 LTS (
Temurin-21.0.7+6), 64-Bit Server VM - JMH Version 1.37 (using Compiler Blackholes)
All performance tests are fully open and available in the SpeedBankingDe/iban-commons-benchmarks repository.
Which countries are supported?
All 95+ countries from the SWIFT IBAN Registry Release 100 (October 2025), including:
- All SEPA countries
- Major economies: UK, Switzerland, Norway, etc.
- Full list available in the source code
Is this library production-ready?
Yes, and already in use in critical production systems. Features:
- Comprehensive test suite (>95% coverage)
- Zero runtime dependencies
- Immutable, thread-safe design
- Regular updates with SWIFT registry
How do I validate IBANs from user input?
String userInput = " de91 1000 0000 0123 4567 89 ";
// Option 1: Safe parsing (recommended for user input)
Optional<Iban> maybeIban = Iban.tryParse(userInput);
maybeIban.ifPresent(iban -> processPayment(iban));
// Option 2: Quick validation
if (Iban.isValid(userInput)) {
Iban iban = Iban.of(userInput);
}The library automatically handles whitespace and case normalization.
Can I use this with Spring Boot?
Yes! Works seamlessly with Spring Boot. For Jakarta Bean Validation integration.
Example custom validator:
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = IbanValidator.class)
public @interface ValidIban {
String message() default "Invalid IBAN";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}What's the difference between IBAN validation and checksum validation?
iban-commons performs complete validation:
- Format validation: Country code, length, character set
- Structural validation: Country-specific BBAN pattern
- Checksum validation: MOD-97 algorithm (ISO 13616)
- Country-specific rules: When available via
CountryValidator
Simple checksum validation alone is insufficient for real-world use.
We welcome contributions! See CONTRIBUTING.md for guidelines.
Quick Ways to Contribute:
- Report bugs via Issues
- Suggest features in Discussions
- Improve documentation
- Submit pull requests
Development Setup:
git clone https://github.com/SpeedBankingDe/iban-commons.git
cd iban-commons
mvn clean verify- 💡 Questions? Ask in Discussions
- 🐛 Found a bug? Open an Issue
- 🌐 Website: www.speedbanking.de
Star this repo if you find it useful! ⭐
This project is licensed under the Apache License, Version 2.0. You can find the full text of the license here.