Entender los números BIN: guía para desarrolladores
¿Qué es un número BIN/IIN?
El número de identificación bancaria (BIN, Bank Identification Number), cuyo nombre formal es número de identificación del emisor (IIN, Issuer Identification Number), corresponde a los primeros 6 u 8 dígitos de un número de tarjeta de pago. Identifica la red de la tarjeta y la institución que la emitió. Los sistemas de pago lo usan para enrutar transacciones, aplicar reglas antifraude y decidir qué reglas de validación corresponden.
Históricamente, el IIN tenía 6 dígitos. Desde la revisión de 2017 de la norma ISO/IEC 7812-1, los nuevos IIN tienen 8 dígitos, y Visa y Mastercard emiten BIN de 8 dígitos desde abril de 2022. Los BIN antiguos de 6 dígitos siguen en circulación, así que tu código tiene que manejar ambos.
Estructura del número BIN
Desglose del formato estándar
| Posición | Longitud | Propósito | Ejemplo |
|---|---|---|---|
| 1 | 1 dígito | Identificador de industria principal (MII) | 4 (banca y finanzas) |
| 1–6 o 1–8 | 6 u 8 dígitos | Número de identificación del emisor (BIN/IIN), incluido el MII | 453201 o 45320151 |
| Después del BIN, hasta el penúltimo dígito | Variable | Identificador de la cuenta individual | 5112830 |
| Último | 1 dígito | Dígito de verificación de Luhn | 6 |
Valores del identificador de industria principal (MII)
Estas son las categorías de la norma ISO/IEC 7812-1 para el primer dígito:
| Dígito MII | Industria |
|---|---|
| 0 | ISO/TC 68 y otras asignaciones de la industria |
| 1 | Aerolíneas |
| 2 | Aerolíneas, finanzas y otras asignaciones futuras de la industria |
| 3 | Viajes y entretenimiento |
| 4 | Banca y finanzas |
| 5 | Banca y finanzas |
| 6 | Comercio y banca/finanzas |
| 7 | Petróleo y otras asignaciones futuras de la industria |
| 8 | Salud, telecomunicaciones y otras asignaciones futuras de la industria |
| 9 | Para asignación por los organismos nacionales de normalización |
Rangos de BIN comunes por red de tarjeta
Rangos de BIN principales
Estos son los principales rangos publicados. Cada red tiene además rangos más pequeños, así que trata esta lista como una ayuda para clasificar, no como un registro completo.
bin_ranges = {
'Visa': ['4'],
'Mastercard': ['51-55', '2221-2720'],
'American Express': ['34', '37'],
'Discover': ['6011', '644-649', '65'],
'JCB': ['3528-3589'],
'Diners Club': ['300-305', '3095', '36', '38-39'],
'UnionPay': ['62', '8100-8171'],
}
En EE. UU., la red de Discover también acepta tarjetas UnionPay (incluido el rango 622126–622925) y Diners Club, pero esas tarjetas siguen perteneciendo a sus propias redes.
Implementación de la consulta de BIN
import re
NETWORK_LENGTHS = {
'Visa': {13, 16, 19},
'Mastercard': {16},
'American Express': {15},
'Discover': {16, 17, 18, 19},
'JCB': {16, 17, 18, 19},
'Diners Club': {14, 15, 16, 17, 18, 19},
'UnionPay': {16, 17, 18, 19},
}
def detect_network(number: str) -> str:
first2, first4 = int(number[:2]), int(number[:4])
if number.startswith(('34', '37')):
return 'American Express'
if number.startswith(('300', '301', '302', '303', '304', '305', '3095', '36', '38', '39')):
return 'Diners Club'
if 3528 <= first4 <= 3589:
return 'JCB'
if number.startswith(('6011', '65')) or 644 <= int(number[:3]) <= 649:
return 'Discover'
if number.startswith('62') or 8100 <= first4 <= 8171:
return 'UnionPay'
if 51 <= first2 <= 55 or 2221 <= first4 <= 2720:
return 'Mastercard'
if number.startswith('4'):
return 'Visa'
return 'Unknown'
def validate_bin(card_number: str) -> dict:
number = re.sub(r'\D', '', card_number)
if len(number) < 6:
return {'valid': False, 'error': 'Enter at least 6 digits'}
network = detect_network(number)
return {
'bin': number[:8] if len(number) >= 16 else number[:6],
'network': network,
'length': len(number),
'valid_length': len(number) in NETWORK_LENGTHS.get(network, set(range(12, 20))),
}
Que el BIN tenga 6 u 8 dígitos depende del emisor, por eso el fragmento conserva los primeros 8 dígitos en los números de longitud completa. Los servicios de consulta aceptan cualquiera de los dos.
Propiedades de los datos de BIN
Campos habituales de una consulta de BIN
No existe un esquema estándar: estos son los campos que devuelven la mayoría de los servicios de consulta de BIN, comerciales y abiertos, y los nombres varían según el proveedor.
| Campo | Descripción | Ejemplo |
|---|---|---|
| scheme | Red de la tarjeta | "visa" |
| country | País emisor | "US" |
| type | Tipo de tarjeta | "credit" |
| category | Nivel o producto de la tarjeta | "platinum" |
| issuer | Banco emisor | "CHASE" |
| length | Longitud del número de tarjeta | 16 |
Reglas de validación basadas en el BIN
Longitud del número de tarjeta por red
| Red | Longitudes válidas |
|---|---|
| Visa | 13, 16, 19 |
| Mastercard | 16 |
| American Express | 15 |
| Discover | 16–19 |
| JCB | 16–19 |
| Diners Club | 14–19 (36), 16–19 (otros rangos) |
| UnionPay | 16–19 |
Ejemplo de integración
const NETWORK_LENGTHS = {
visa: [13, 16, 19],
mastercard: [16],
amex: [15],
discover: [16, 17, 18, 19],
jcb: [16, 17, 18, 19],
diners: [14, 15, 16, 17, 18, 19],
unionpay: [16, 17, 18, 19],
};
const binValidator = {
checkBIN(cardNumber) {
const digits = cardNumber.replace(/\D/g, '');
if (digits.length < 6) {
return { valid: false, error: 'Enter at least 6 digits' };
}
const network = this.detectNetwork(digits);
const lengths = NETWORK_LENGTHS[network] || [];
return {
valid: lengths.includes(digits.length),
network,
bin: digits.slice(0, digits.length >= 16 ? 8 : 6),
cardLength: digits.length,
};
},
detectNetwork(digits) {
const first4 = Number(digits.slice(0, 4));
if (/^3[47]/.test(digits)) return 'amex';
if (/^(30[0-5]|3095|36|3[89])/.test(digits)) return 'diners';
if (first4 >= 3528 && first4 <= 3589) return 'jcb';
if (/^(6011|64[4-9]|65)/.test(digits)) return 'discover';
if (/^62/.test(digits) || (first4 >= 8100 && first4 <= 8171)) return 'unionpay';
if (/^5[1-5]/.test(digits) || (first4 >= 2221 && first4 <= 2720)) return 'mastercard';
if (/^4/.test(digits)) return 'visa';
return 'unknown';
},
};
Consideraciones de seguridad
-
Protección de datos
- Un BIN por sí solo no es un dato del titular de la tarjeta, pero un número de tarjeta completo (PAN) sí lo es. Evita almacenar PAN completos; si es imprescindible, el requisito 3 de PCI DSS exige que sean ilegibles (criptografía robusta, truncamiento, tokenización o hash con clave).
- Si conservas un número truncado, respeta los límites de truncamiento del PCI SSC: como máximo los primeros 8 y otros 4 dígitos cualesquiera en los PAN de 16 dígitos, y los primeros 6 y los últimos 4 en los números Amex de 15 dígitos.
- Cifra los números de tarjeta completos en tránsito (TLS) y restringe quién puede acceder a ellos.
-
Cumplimiento normativo
- Almacenar o procesar PAN completos hace que tus sistemas entren en el alcance de PCI DSS; la tokenización a través de tu proveedor de pagos deja fuera la mayor parte.
- Define períodos de retención para todo lo que se derive de datos de tarjetas, incluidos los logs.
-
Rendimiento
- Almacena en caché los resultados de las consultas de BIN; los datos de BIN cambian lentamente.
- Respeta los límites de solicitudes de tu proveedor de consultas y usa los endpoints masivos cuando estén disponibles.
Buenas prácticas para el procesamiento de BIN
| Práctica | Propósito | Implementación |
|---|---|---|
| Caché | Reducir las llamadas a la API | Guardar los datos de BIN en memoria o en una tabla local |
| Validación | Prevenir errores | Verificar el formato, la longitud y Luhn antes de llamar a una API |
| Monitoreo | Detectar problemas | Registrar las consultas fallidas y los BIN desconocidos |
| Soporte de 8 dígitos | Mantener la precisión | Buscar primero por 8 dígitos y, si no hay coincidencia, por 6 |
Los datos de BIN son una ayuda para clasificar, no una prueba de que una tarjeta exista o vaya a ser aprobada. Combínalos con la verificación de Luhn, las reglas de longitud y, en los pagos reales, el resultado de la autorización de tu pasarela de pago.