Skip to content

Instantly share code, notes, and snippets.

@canassa
Last active October 2, 2020 15:10
Show Gist options
  • Save canassa/5b9ab0ab9013afac31065d41d912b514 to your computer and use it in GitHub Desktop.
Save canassa/5b9ab0ab9013afac31065d41d912b514 to your computer and use it in GitHub Desktop.
Python CNPJ validation
import re
from typing import Union
class InvalidCNPJ(Exception):
pass
def clean_cnpj(value: Union[int, str]) -> str:
"""
Validates and cleans CNPJs, works with both string and ints as inputs
>>> clean_cnpj("57.823.152/0001-01")
'57.823.152/0001-01'
>>> clean_cnpj("32820286000148")
'32.820.286/0001-48'
>>> clean_cnpj("04520130000106")
'04.520.130/0001-06'
>>> clean_cnpj(4520130000106)
'04.520.130/0001-06'
>>> clean_cnpj("32.820.286/0000-67")
Traceback (most recent call last)
InvalidCNPJ:
"""
if isinstance(value, int):
v = f"{value:014d}"
elif isinstance(value, str):
v = re.sub(r"\D", "", value)
else:
raise InvalidCNPJ
if len(v) != 14:
raise InvalidCNPJ
# Suffixes start at 0001
suffix = int(v[8:12])
if suffix == 0:
raise InvalidCNPJ
# CNPJs with the following basic numbers are not valid:
# 11.111.111, 22.222.222, 33.333.333, 44.444.444, 55.555.555
# 66.666.666, 77.777.777, 88.888.888, 99.999.999.
if v[0:8] in {
"11111111",
"22222222",
"33333333",
"44444444",
"55555555",
"66666666",
"77777777",
"88888888",
"99999999",
}:
raise InvalidCNPJ
d = [int(i) for i in v[:14]]
v1 = 5 * d[0] + 4 * d[1] + 3 * d[2] + 2 * d[3]
v1 += 9 * d[4] + 8 * d[5] + 7 * d[6] + 6 * d[7]
v1 += 5 * d[8] + 4 * d[9] + 3 * d[10] + 2 * d[11]
v1 = 11 - v1 % 11
if v1 >= 10:
v1 = 0
if v1 != d[12]:
raise InvalidCNPJ
v2 = 6 * d[0] + 5 * d[1] + 4 * d[2] + 3 * d[3]
v2 += 2 * d[4] + 9 * d[5] + 8 * d[6] + 7 * d[7]
v2 += 6 * d[8] + 5 * d[9] + 4 * d[10] + 3 * d[11]
v2 += 2 * d[12]
v2 = 11 - v2 % 11
if v2 >= 10:
v2 = 0
if v2 != d[13]:
raise InvalidCNPJ
# CNPJ with an suffix number greater than 0300 and with the first three positions
# of the BASIC number with 000 (zeros) will not be considered valid.
# Unless the basic number of the CNPJ is equal to 00.000.000, then it's valid.
if v[0:8] != "00000000" and v[0:3] == "000" and suffix > 300:
raise InvalidCNPJ
return f"{v[0:2]}.{v[2:5]}.{v[5:8]}/{v[8:12]}-{v[12:14]}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment