Escribe o pega una CURP y el validador comprueba, carácter a carácter, que siga las reglas de RENAPO: que la fecha de nacimiento exista, que el sexo y la entidad sean claves válidas y que el dígito verificador cuadre con el resto. Si algo falla, te dice en qué posición y por qué. Todo se calcula en tu navegador: la CURP no se envía a ningún sitio.
Bien formada no quiere decir que exista. El validador comprueba la estructura y el dígito verificador, pero no consulta el registro de RENAPO: una CURP inventada que cumpla las reglas también sale válida. Para saber si una CURP existe y a quién pertenece, consúltala en la página oficial gob.mx/curp.
Qué comprueba el validador
- Longitud y caracteres: 18, solo letras sin acento y cifras. La CURP no lleva Ñ: en su lugar va una X.
- Las cuatro letras iniciales, y que la segunda sea una vocal o una X. Avisa si forman una de las palabras que RENAPO no asigna.
- La fecha de nacimiento: que exista y que no esté en el futuro. El siglo lo da la posición 17.
- El sexo (H, M o X) y la entidad de nacimiento: una de las 32 claves de los estados o NE, si nació en el extranjero.
- Las tres consonantes internas de las posiciones 14 a 16.
- El dígito verificador, que detecta casi cualquier carácter mal copiado.
El botón Generar una CURP de prueba crea CURP al azar que cumplen todas las reglas, útiles para rellenar formularios y bases de datos de prueba. No corresponden a ninguna persona concreta, así que no sirven para ningún trámite.
Cómo se forma la CURP
La Clave Única de Registro de Población tiene 18 caracteres, y cada posición tiene un significado. Como ejemplo, la CURP HEGG560427MVZRRL04, la que se usa en muchas guías, correspondería a Gloria Hernández García, una mujer nacida el 27 de abril de 1956 en Veracruz:
| Posición | En el ejemplo | Qué es |
|---|---|---|
| 1 | H | Inicial del primer apellido (Hernández) |
| 2 | E | Primera vocal interna del primer apellido: la primera vocal después de la inicial |
| 3 | G | Inicial del segundo apellido (García), o X si no lo hay |
| 4 | G | Inicial del nombre (Gloria). Con un nombre compuesto que empieza por José o María, se toma el segundo |
| 5 a 10 | 560427 | Fecha de nacimiento: año, mes y día, con dos cifras cada uno |
| 11 | M | Sexo: H (hombre), M (mujer) o, desde 2022, X (no binario) |
| 12 y 13 | VZ | Entidad de nacimiento (Veracruz), o NE si nació en el extranjero |
| 14 a 16 | RRL | Primera consonante interna del primer apellido, del segundo y del nombre |
| 17 | 0 | Diferenciador: una cifra si nació antes de 2000 y una letra a partir de 2000. Si ya existe otra CURP igual en las 16 primeras posiciones, cambia para distinguirlas |
| 18 | 4 | Dígito verificador, calculado con los 17 anteriores |
Hay dos ajustes que explican CURP que a primera vista parecen raras. Cuando las cuatro primeras letras forman una palabra malsonante, RENAPO cambia la segunda por una X. Y la Ñ de un apellido como Muñoz o Peña se escribe como X.
Cómo se calcula el dígito verificador
A cada uno de los 17 primeros caracteres se le da un valor: las cifras valen lo mismo que su número, y las letras van de la A, que vale 10, a la Z, que vale 36. La tabla incluye la Ñ entre la N y la O, aunque la CURP no la use, así que la N vale 23 y la O vale 25. Cada valor se multiplica por un peso, que empieza en 18 y baja de uno en uno, y se suman los productos:
| Carácter | Valor | Peso | Producto |
|---|---|---|---|
H | 17 | 18 | 306 |
E | 14 | 17 | 238 |
G | 16 | 16 | 256 |
G | 16 | 15 | 240 |
5 | 5 | 14 | 70 |
6 | 6 | 13 | 78 |
0 | 0 | 12 | 0 |
4 | 4 | 11 | 44 |
2 | 2 | 10 | 20 |
7 | 7 | 9 | 63 |
M | 22 | 8 | 176 |
V | 32 | 7 | 224 |
Z | 36 | 6 | 216 |
R | 28 | 5 | 140 |
R | 28 | 4 | 112 |
L | 21 | 3 | 63 |
0 | 0 | 2 | 0 |
La suma es 2 246. Su última cifra es 6, y el dígito verificador es lo que le falta para llegar a 10: 10 − 6 = 4. Cuando la última cifra de la suma es 0, el dígito es 0. Como el último carácter de la CURP es un 4, el dígito cuadra.
Validar una CURP en Python
Esta función hace las mismas comprobaciones esenciales que el validador de la página: el formato con una expresión regular (que incluye la lista de entidades), que la fecha exista y no sea futura, y el dígito verificador.
import re
from datetime import date
VALORES = "0123456789ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"
FORMATO = re.compile(r"[A-Z][AEIOUX][A-Z]{2}\d{6}[HMX]"
r"(AS|BC|BS|CC|CL|CM|CS|CH|DF|DG|GT|GR|HG|JC|MC|MN|MS|NT"
r"|NL|OC|PL|QT|QR|SP|SL|SR|TC|TS|TL|VZ|YN|ZS|NE)"
r"[B-DF-HJ-NP-TV-Z]{3}[0-9A-Z]\d")
def digito_verificador(curp17: str) -> str:
suma = sum(VALORES.index(c) * (18 - i) for i, c in enumerate(curp17))
return str((10 - suma % 10) % 10)
def curp_valida(curp: str) -> bool:
curp = curp.strip().upper()
if not FORMATO.fullmatch(curp):
return False
siglo = 1900 if curp[16].isdigit() else 2000
try:
nacimiento = date(siglo + int(curp[4:6]), int(curp[6:8]), int(curp[8:10]))
except ValueError:
return False
return nacimiento <= date.today() and curp[17] == digito_verificador(curp[:17])
print(curp_valida("HEGG560427MVZRRL04")) # True
print(curp_valida("HEGG560427MVZRRL05")) # False$ python3 curp.pyTrue False
La expresión regular es un poco más estricta que el validador de esta página, que en esos casos solo avisa: exige una vocal o X en la posición 2 y consonantes en las posiciones 14 a 16. Si tienes que aceptar datos antiguos con excepciones, relaja esas dos partes.
Otros validadores: RFC, CURP y CLABE. Para facturas electrónicas, el validador de CFDI 4.0. Todas las herramientas, en decodigo.com/herramientas.
Reglas: Instructivo Normativo para la asignación de la CURP (DOF, 18 de junio de 2018). El algoritmo del dígito verificador y la lista de palabras que no se asignan se comprobaron contra la implementación de la biblioteca python-stdnum con 3 000 CURP generadas, 3 000 cadenas al azar y 3 000 CURP con un carácter cambiado.