Cómo generar un IBAN válido en código (Python, JS, PHP)

Cómo generar un IBAN válido en código (Python, JS, PHP)

Una guía práctica para generar IBAN válidos y correctos según MOD-97 mediante programación en Python, JavaScript y PHP, para datos de prueba, datos semilla y procesos de QA.

Escrito por David S · Publicado el 2026-05-26
#generate IBAN #IBAN in code #Python IBAN #JavaScript IBAN #PHP IBAN #test data #MOD-97 #fixtures

En algún momento, la mayoría de quienes desarrollan sistemas de pago chocan contra el mismo muro: necesitan IBAN válidos para las pruebas y no hay una buena forma de escribirlos a mano. Copiar y pegar el mismo puñado de ejemplos genera conjuntos de pruebas frágiles, y usar un IBAN real es un problema de cumplimiento esperando a suceder. La solución limpia es generarlos mediante programación: estructuralmente correctos, con dígitos de control válidos y tantos como necesites.

Esta guía explica exactamente cómo hacerlo en Python, JavaScript y PHP. Al terminar tendrás una función pequeña y con pocas dependencias que podrás incorporar a una factoría, a un script de datos semilla o a un módulo de datos de prueba. Si solo necesitas unos pocos números ahora mismo sin escribir código, el generador de Random IBAN los produce al instante y los exporta a CSV, JSON o TXT.


Qué significa realmente «generar un IBAN»

Un IBAN no es un único número opaco: son tres partes concatenadas.

ES 76 21000418450200051332
│  │  └── BBAN (country-specific: bank + branch + account)
│  └───── Check digits (calculated, positions 3–4)
└──────── Country code (ISO 3166-1, positions 1–2)

Así que generar uno significa hacer tres cosas en orden:

  1. Elegir un país y consultar su longitud de IBAN y la disposición de su BBAN.
  2. Construir un BBAN aleatorio que se ajuste a esa disposición (la cantidad correcta de dígitos, y letras donde la especificación las permita).
  3. Calcular los dos dígitos de control con el algoritmo MOD-97 para que el conjunto sea válido.

El primer paso necesita una pequeña tabla de consulta. El segundo es pura generación aleatoria. El tercero es la única parte con lógica real, y es la misma rutina que usarías para validar un IBAN, ejecutada a la inversa.


El núcleo: calcular los dígitos de control

Todos los lenguajes de más abajo comparten la misma rutina de dígitos de control. La regla de la norma ISO 7064 / ISO 13616 es:

  1. Toma el BBAN, añade el código de país y luego añade 00.
  2. Sustituye cada letra por dos dígitos (A=10, B=11, … Z=35).
  3. Lee el resultado como un único entero grande y calcula 98 - (entero mod 97).
  4. Rellena ese resultado con ceros hasta dos dígitos.

Ese número rellenado es tu par de dígitos de control. Colócalo entre el código de país y el BBAN, y el IBAN terminado superará la validación MOD-97. Vamos a implementarlo.


Generar un IBAN en Python

Los enteros de precisión arbitraria de Python hacen que esto sea casi trivial: no hace falta ninguna biblioteca de enteros grandes.

import random

# Minimal layout table: country -> (total length, BBAN length)
IBAN_SPECS = {
    "DE": 22, "ES": 24, "FR": 27, "GB": 22,
    "NL": 18, "IT": 27, "PT": 25, "BE": 16,
}

def _check_digits(country: str, bban: str) -> str:
    rearranged = bban + country + "00"
    numeric = "".join(
        str(ord(c) - 55) if c.isalpha() else c
        for c in rearranged
    )
    check = 98 - (int(numeric) % 97)
    return f"{check:02d}"

def generate_iban(country: str = "ES") -> str:
    total_len = IBAN_SPECS[country]
    bban_len = total_len - 4            # minus country code + check digits
    bban = "".join(random.choices("0123456789", k=bban_len))
    return country + _check_digits(country, bban) + bban

# Usage
print(generate_iban("DE"))   # e.g. DE21 ... (valid checksum)
print([generate_iban("ES") for _ in range(5)])

Esto mantiene el BBAN numérico por simplicidad, lo cual es correcto para los países anteriores. Unos pocos países (el Reino Unido, por ejemplo) incluyen letras en el código de banco; para esos también tendrías que aleatorizar las posiciones de las letras. Para datos de prueba, un BBAN totalmente numérico suele bastar, porque sigue superando las comprobaciones de MOD-97 y de longitud.


Generar un IBAN en JavaScript

El único inconveniente en JS es que el número reordenado es demasiado grande para un Number normal. La solución estándar es un bucle de resto acumulado, que mantiene el valor por debajo de 97 en todo momento.

const IBAN_SPECS = {
  DE: 22, ES: 24, FR: 27, GB: 22,
  NL: 18, IT: 27, PT: 25, BE: 16,
};

function mod97(numericString) {
  let remainder = 0;
  for (const ch of numericString) {
    remainder = (remainder * 10 + Number(ch)) % 97;
  }
  return remainder;
}

function checkDigits(country, bban) {
  const rearranged = bban + country + '00';
  const numeric = rearranged.replace(/[A-Z]/g, c =>
    (c.charCodeAt(0) - 55).toString()
  );
  const check = 98 - mod97(numeric);
  return String(check).padStart(2, '0');
}

function generateIban(country = 'ES') {
  const bbanLen = IBAN_SPECS[country] - 4;
  let bban = '';
  for (let i = 0; i < bbanLen; i++) {
    bban += Math.floor(Math.random() * 10);
  }
  return country + checkDigits(country, bban) + bban;
}

// Usage
console.log(generateIban('FR'));
console.log(Array.from({ length: 5 }, () => generateIban('NL')));

Si necesitas una aleatoriedad criptográficamente más robusta (rara vez es necesario para datos de prueba), sustituye Math.random() por crypto.getRandomValues(). Para datos de prueba y demostraciones, la versión sencilla es perfectamente adecuada.


Generar un IBAN en PHP

PHP necesita la extensión bcmath para el módulo del número grande, que viene incluida en la mayoría de las instalaciones.

<?php
const IBAN_SPECS = [
    'DE' => 22, 'ES' => 24, 'FR' => 27, 'GB' => 22,
    'NL' => 18, 'IT' => 27, 'PT' => 25, 'BE' => 16,
];

function checkDigits(string $country, string $bban): string {
    $rearranged = $bban . $country . '00';
    $numeric = '';
    foreach (str_split($rearranged) as $ch) {
        $numeric .= ctype_alpha($ch) ? (string)(ord($ch) - 55) : $ch;
    }
    $check = 98 - (int) bcmod($numeric, '97');
    return str_pad((string) $check, 2, '0', STR_PAD_LEFT);
}

function generateIban(string $country = 'ES'): string {
    $bbanLen = IBAN_SPECS[$country] - 4;
    $bban = '';
    for ($i = 0; $i < $bbanLen; $i++) {
        $bban .= random_int(0, 9);
    }
    return $country . checkDigits($country, $bban) . $bban;
}

// Usage
echo generateIban('IT'), PHP_EOL;

Fíjate en el uso de random_int() en lugar de rand(): es la opción moderna y sin sesgo, y aquí no cuesta nada más.


Usar IBAN generados en un conjunto de pruebas

Una vez que tengas un generador, intégralo en tus pruebas en lugar de esparcir valores literales. Algunos patrones que funcionan bien:

  • Factorías y datos de prueba. Llama a generateIban() dentro de tu factoría (FactoryBoy, un proveedor de Faker, una factory de Laravel) para que cada ejecución de pruebas obtenga datos nuevos y válidos.
  • Datos semilla para staging. Llena las bases de datos de demostración con unos cientos de IBAN de varios países para ejercitar el formato específico de cada uno.
  • Casos límite. Mantén un conjunto aparte de cadenas deliberadamente defectuosas (longitud incorrecta, dígito de control erróneo, país no compatible) para comprobar que tu validación las rechaza.
  • Determinismo cuando lo necesites. Fija la semilla de tu generador de números aleatorios al inicio de una prueba si quieres IBAN reproducibles; déjala sin fijar para una cobertura de tipo fuzzing.

Sea lo que sea que generes, etiquétalo claramente como sintético. Estos números son estructuralmente válidos y superan el MOD-97, pero no son cuentas reales y nunca deben llegar a un sistema de pagos en producción. Consulta nuestra guía sobre cómo almacenar IBAN de forma segura en sistemas de pago para evitar que se mezclen los datos de prueba y los de producción.


Cuándo no escribir tu propio generador

Crear el tuyo propio es estupendo para una integración estrecha, pero no siempre merece la pena. Sáltate el código cuando:

  • Necesites un lote rápido ahora mismo: pégalos en segundos desde el generador de Random IBAN y expórtalos a CSV/JSON.
  • Necesites una amplia cobertura de países con subestructuras de BBAN correctas (dígitos de control nacionales, posiciones de letras) que una tabla mínima no contempla.
  • Estés trabajando fuera de una base de código: preparando una hoja de cálculo, una colección de Postman o documentación.

Y sea cual sea el camino que elijas, valida la salida. Pasa una muestra por el validador de IBAN para confirmar que tu lógica de dígitos de control coincide con la implementación de referencia. Si algo no supera el MOD-97, el error casi siempre está en la conversión de letras a números o en un error de desplazamiento en uno (off-by-one) en la longitud del BBAN.


Preguntas frecuentes

¿Es seguro usar IBAN generados mediante programación?

Sí, para pruebas, QA, demostraciones y documentación. Son estructuralmente válidos y superan la validación de la suma de control, pero no están vinculados a ninguna cuenta bancaria real. Nunca uses IBAN generados para transacciones reales ni en un sistema de pagos en producción.

¿Necesito una biblioteca externa para generar un IBAN?

No. Los ejemplos anteriores usan solo la biblioteca estándar de cada lenguaje: los enteros grandes integrados de Python, un bucle de resto acumulado en JavaScript y el bcmath incluido en PHP. Las bibliotecas pueden ayudar con la cobertura completa de países, pero el algoritmo central son unas pocas líneas.

¿Por qué mi IBAN generado no supera la validación?

Las causas más comunes son una conversión incorrecta de letras a números (debe ser de A=10 a Z=35), olvidar añadir el código de país y 00 antes del paso del módulo, o usar una longitud de BBAN equivocada para el país. Compara un único caso fallido con el validador para aislarlo.

¿Cómo genero IBAN para países con letras en el BBAN?

Amplía el paso del BBAN aleatorio para colocar letras donde la especificación del país las permita; por ejemplo, el código de banco del Reino Unido son cuatro letras. Mantén un patrón por país (qué posiciones son letras y cuáles dígitos) en lugar de una única longitud, y luego rellena cada posición en consecuencia antes de calcular los dígitos de control.

¿Puedo generar miles de IBAN a la vez?

Sí. Las funciones generadoras son baratas de llamar en un bucle, así que producir miles es instantáneo. Si prefieres no ejecutar código, el generador de Random IBAN admite la generación masiva y la exportación con un clic a CSV, JSON y TXT.

¿Cuál es la diferencia entre generar y validar un IBAN?

La validación comprueba un número existente confirmando que mod 97 == 1. La generación ejecuta la misma aritmética a la inversa: construyes primero el BBAN y luego calculas 98 - (mod 97) para hallar los dígitos de control que hacen válido el número. Comparten la misma rutina central.

Prueba Nuestras Herramientas IBAN

Pon en práctica tus conocimientos con nuestras herramientas gratuitas.