Escribe o pega un RFC de persona física (13 caracteres) o de persona moral (12) y el validador comprueba su estructura: las letras iniciales, que la fecha exista y que el dígito verificador cuadre. Si algo falla, te dice qué parte es y por qué. También reconoce los RFC genéricos del SAT. Todo se calcula en tu navegador: el RFC no se envía a ningún sitio.
Bien formado no quiere decir que exista ni que esté activo. El validador comprueba la estructura y el dígito verificador, pero no consulta el padrón del SAT: un RFC inventado que cumpla las reglas también sale válido. Para saber si un RFC está registrado y puede recibir facturas, usa el servicio «Valida en línea RFC» en el portal del SAT.
Qué comprueba el validador
- La longitud: 13 caracteres para una persona física y 12 para una moral (una empresa o asociación). Si faltan los tres últimos, avisa de que falta la homoclave.
- Las letras iniciales: cuatro o tres, que pueden incluir la Ñ y el &. Avisa si forman una de las palabras que el SAT no asigna.
- La fecha de nacimiento o de constitución: que exista. El RFC no indica el siglo, así que se toma el más probable.
- La homoclave, con los caracteres que usa el SAT, y el dígito verificador, el último carácter.
- Los RFC genéricos:
XAXX010101000, para el público en general, yXEXX010101000, para extranjeros sin RFC mexicano.
Los botones generan RFC al azar que cumplen las reglas, útiles para probar formularios y sistemas de facturación. No corresponden a nadie en concreto y no sirven para facturar: para eso están los genéricos del SAT.
Cómo se forma el RFC
| Parte | Persona física | Persona moral | Qué es |
|---|---|---|---|
| Letras | GODE | MAB | En una persona física, las mismas cuatro letras que la CURP: inicial y primera vocal interna del primer apellido, inicial del segundo y del nombre. En una moral, tres letras de la razón social |
| Fecha | 561231 | 930714 | Nacimiento o constitución: año, mes y día, con dos cifras cada uno |
| Homoclave | GR | 8T | Dos caracteres que el SAT calcula con el nombre completo, para distinguir a quienes comparten los diez primeros |
| Verificador | 8 | 4 | Una cifra o una A, calculada con todo lo anterior |
Por eso los diez primeros caracteres del RFC de una persona física casi siempre coinciden con los de su CURP. La excepción son las palabras malsonantes: la CURP cambia la segunda letra por una X y el RFC, la última.
La homoclave no se puede comprobar sin el nombre completo, y este validador no lo pide. El dígito verificador, en cambio, se calcula solo con los caracteres anteriores.
Cómo se calcula el dígito verificador
Se toman los caracteres sin el último, y si son 11 (persona moral) se añade un espacio delante para que sean 12. A cada uno se le da un valor: las cifras valen su número, la A vale 10, el & va entre la N y la O, con 24, el espacio vale 37 y la Ñ, 38. Cada valor se multiplica por un peso que va de 13 a 2. Con el RFC GODE561231GR8:
| Carácter | Valor | Peso | Producto |
|---|---|---|---|
G | 16 | 13 | 208 |
O | 25 | 12 | 300 |
D | 13 | 11 | 143 |
E | 14 | 10 | 140 |
5 | 5 | 9 | 45 |
6 | 6 | 8 | 48 |
1 | 1 | 7 | 7 |
2 | 2 | 6 | 12 |
3 | 3 | 5 | 15 |
1 | 1 | 4 | 4 |
G | 16 | 3 | 48 |
R | 28 | 2 | 56 |
La suma es 1 026. Se divide entre 11 y queda un resto de 3, y el dígito es 11 − 3 = 8. Si el resto es 0, el dígito es 0, y si es 1, el resultado sería 10 y se escribe una A. El RFC termina en 8, así que cuadra.
Si el dígito no cuadra, el validador lo marca como aviso y no como error. Casi siempre se debe a un carácter mal copiado, pero existen RFC antiguos que el SAT asignó con un dígito que no sigue este cálculo. Si es un RFC real, confírmalo en el SAT antes de darlo por malo.
Validar un RFC en Python
import re
VALORES = "0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ Ñ"
FORMATO = re.compile(r"[A-ZÑ&]{3,4}\d{6}[0-9A-Z]{2}[0-9A]")
def digito_verificador(rfc_sin_digito: str) -> str:
s = rfc_sin_digito.rjust(12) # las morales (11 caracteres) llevan un espacio delante
suma = sum(VALORES.index(c) * (13 - i) for i, c in enumerate(s))
return VALORES[(11 - suma % 11) % 11]
def rfc_valido(rfc: str) -> bool:
rfc = rfc.strip().upper()
if rfc in ("XAXX010101000", "XEXX010101000"): # genéricos del SAT
return True
return (FORMATO.fullmatch(rfc) is not None
and rfc[-1] == digito_verificador(rfc[:-1]))
print(rfc_valido("GODE561231GR8")) # True, persona física
print(rfc_valido("MAB9307148T4")) # True, persona moral
print(rfc_valido("GODE561231GR9")) # False$ python3 rfc.pyTrue True False
rjust(12) añade el espacio delante del RFC de una persona moral. La función acepta los dos genéricos del SAT y rechaza cualquier RFC con el dígito descuadrado; si trabajas con RFC antiguos reales, quizá prefieras registrar el caso en lugar de rechazarlo.
Otros validadores: RFC, CURP y CLABE. Para facturas electrónicas, el validador de CFDI 4.0. Todas las herramientas, en decodigo.com/herramientas.
El cálculo del dígito verificador se comprobó contra la implementación de la biblioteca python-stdnum con 6 000 RFC generados, 3 000 cadenas al azar y 6 000 RFC con un carácter cambiado.