Cómo Validar la Vigencia de un Pasaporte (y la Regla de los 6 Meses)
Cómo comprobar automáticamente si un pasaporte está vigente, por qué muchos países exigen seis meses de validez restante y cómo implementar la validación con la fecha de la MRZ.
"¿Está vigente este pasaporte?" parece una comparación de fechas trivial. En la práctica tiene tres complicaciones que rompen las implementaciones ingenuas: el siglo ausente en la MRZ, la regla de los seis meses y la diferencia entre vigente y aceptable.
Dónde está la fecha
La fecha de vencimiento aparece en dos sitios de la página de datos, y conviene leer los dos:
- La zona visual (VIZ), impresa en formato legible.
- La MRZ, en las posiciones 22-27 de la línea 2, en formato
AAMMDD, seguida en la posición 28 de su dígito verificador.
La versión de la MRZ tiene una ventaja decisiva: viene con comprobación aritmética. Si el dígito de la posición 28 cuadra, la fecha se leyó bien. Ninguna otra fecha del documento ofrece esa garantía.
Cuando ambas lecturas coinciden, la fecha está confirmada por dos vías independientes. Cuando no, tienes una señal temprana de un problema de lectura — o de un documento manipulado.
Complicación 1: la MRZ no dice el siglo
330705 son seis dígitos. ¿2033 o 1933?
Para el vencimiento la respuesta es fácil: un pasaporte se emite con validez de cinco o diez años, así que la fecha siempre cae en el futuro cercano. 33 es 2033.
La regla práctica que funciona sin excepciones realistas:
function anioVencimiento(aa) {
const siglo = Math.floor(new Date().getFullYear() / 100) * 100 // 2000
const candidato = siglo + Number(aa)
// Un pasaporte válido no vence más de ~11 años en el futuro,
// pero sí puede estar vencido desde hace tiempo.
return candidato < new Date().getFullYear() - 20 ? candidato + 100 : candidato
}
Cuidado con copiar esta lógica a la fecha de nacimiento, donde la ambigüedad sí es real: 05 puede ser 1905 o 2005. Ahí la convención es que si los dos dígitos superan el año en curso, es del siglo pasado.
Complicación 2: la regla de los seis meses
Aquí es donde falla la mayoría de las implementaciones. Un pasaporte que vence dentro de tres meses está vigente hoy — y aun así muchos países no dejarán entrar a su titular.
Es la llamada regla de los seis meses: numerosos destinos exigen que el pasaporte conserve al menos seis meses de validez a partir de la fecha de entrada, y algunos la cuentan desde la fecha de salida prevista. Otros piden tres meses, y otros solo exigen que sea válido durante la estancia.
Las consecuencias para el diseño de tu sistema:
- "Vigente" y "aceptable" son dos preguntas distintas. No las mezcles en un solo booleano.
- La fecha de referencia no es hoy, sino la del viaje o la operación.
- El umbral depende del destino, así que es configuración, no una constante.
function evaluarVigencia(fechaVencimiento, { fechaReferencia = new Date(), mesesRequeridos = 6 } = {}) {
const vencimiento = new Date(fechaVencimiento)
const minimo = new Date(fechaReferencia)
minimo.setMonth(minimo.getMonth() + mesesRequeridos)
return {
vigente: vencimiento > fechaReferencia,
cumpleMargen: vencimiento >= minimo,
diasRestantes: Math.floor((vencimiento - fechaReferencia) / 86400000),
}
}
Un pasaporte con vigente: true y cumpleMargen: false es exactamente el caso que hay que señalar al usuario con antelación — no rechazarlo, sino avisarle de que probablemente necesite renovarlo antes del viaje.
Complicación 3: vigencia no es autenticidad
Que las fechas cuadren dice que el documento no ha caducado. No dice que sea auténtico, ni que no esté reportado como robado, ni que la persona que lo presenta sea su titular.
Un sistema de verificación completo distingue capas:
| Capa | Qué comprueba | Cómo |
|---|---|---|
| Lectura | Los datos se leyeron bien | Dígitos verificadores de la MRZ |
| Coherencia | Los campos concuerdan entre sí | MRZ contra zona visual |
| Vigencia | El documento no caducó | Fecha de vencimiento |
| Estado | No está reportado | Consulta a registros oficiales |
| Titularidad | Es de quien lo presenta | Biometría / verificación presencial |
Una API de extracción cubre bien las tres primeras. Las dos últimas requieren fuentes externas y quedan fuera del alcance de cualquier OCR — desconfía de quien afirme lo contrario.
Comprobaciones que casi nadie implementa
Con las fechas ya extraídas y validadas salen gratis algunas verificaciones adicionales:
Coherencia entre emisión y vencimiento. La diferencia debería corresponder a un periodo de validez plausible —típicamente 5 o 10 años, menos para menores de edad—. Una diferencia de 30 años es una anomalía que merece revisión.
Vencimiento posterior a la emisión. Suena obvio, pero es la comprobación que detecta un error de transcripción de siglo.
Edad coherente. La fecha de nacimiento derivada de la MRZ debería dar una edad razonable, y coincidir con la del expediente.
function comprobacionesDeCoherencia({ dateOfIssue, dateOfExpiry, dateOfBirth }) {
const emision = new Date(dateOfIssue)
const vencimiento = new Date(dateOfExpiry)
const nacimiento = new Date(dateOfBirth)
const anios = (vencimiento - emision) / (365.25 * 86400000)
return {
ordenCorrecto: vencimiento > emision && emision > nacimiento,
validezPlausible: anios > 0.5 && anios < 11.5,
}
}
Automatizarlo
Nuestra API devuelve las tres fechas ya normalizadas a DD/MM/YYYY, junto con las dos líneas de la MRZ validadas contra sus dígitos verificadores:
{
"dateOfBirth": "05/07/1980",
"dateOfIssue": "10/03/2023",
"dateOfExpiry": "05/07/2033",
"mrzLine2": "G123456786MEX8007050F3307054<<<<<<<<<<<<<<08"
}
Que el dígito de la posición 28 cuadre es lo que te permite construir la lógica de vigencia sobre una fecha en la que puedes confiar, en lugar de sobre una lectura que quizá salió mal.
Puedes probarlo con un pasaporte real en la demo gratuita, o pegar una MRZ que ya tengas en el validador para ver los dígitos recalculados. El detalle de esa aritmética está en Dígitos verificadores ICAO 9303, y el mapa de posiciones que ubica la fecha en la línea 2, en Cómo leer la MRZ línea por línea.
¿Necesitas extraer datos de pasaportes automáticamente?
Prueba nuestra API con 20 extracciones gratis. Integración en minutos, resultados en segundos.
Comenzar gratis