Skip to main content
The CNPJ (Cadastro Nacional da Pessoa Jurídica) is the tax identifier for companies in Brazil. With over 55 million registered companies, Brazil is the largest B2B market in Latin America. This guide covers:
  1. CNPJ structure and validation
  2. Official data sources available in 2026
  3. How to query company data with the EnrichLATAM API

CNPJ structure

A CNPJ has the format XX.XXX.XXX/XXXX-DD, where:
  • The first 8 digits identify the parent company
  • The next 4 digits identify the establishment (branch)
  • The last 2 are check digits
Example: 11.222.333/0001-81 The /0001 suffix indicates the headquarters. A company can have multiple CNPJs for different branches (/0002, /0003, etc.).

1. Validate a CNPJ in Python

import re

def validate_cnpj(cnpj: str) -> bool:
    """Validates format and check digits of a Brazilian CNPJ."""
    digits = re.sub(r"\D", "", cnpj)

    if len(digits) != 14:
        return False

    # Reject CNPJs with all identical digits
    if len(set(digits)) == 1:
        return False

    def calc_dv(digits: str, length: int) -> int:
        weights = list(range(length + 1, 1, -1))
        total = sum(int(d) * w for d, w in zip(digits[:length], weights))
        remainder = total % 11
        return 0 if remainder < 2 else 11 - remainder

    dv1 = calc_dv(digits, 12)
    dv2 = calc_dv(digits, 13)

    return int(digits[12]) == dv1 and int(digits[13]) == dv2


print(validate_cnpj("11.222.333/0001-81"))  # True
print(validate_cnpj("00.000.000/0000-00"))  # False
print(validate_cnpj("11222333000181"))       # True

2. Normalize the format

def normalize_cnpj(cnpj: str) -> str | None:
    """
    Normalizes a CNPJ to the standard format XX.XXX.XXX/XXXX-DD.
    Returns None if the CNPJ is invalid.
    """
    digits = re.sub(r"\D", "", cnpj.strip())

    if not validate_cnpj(digits):
        return None

    return f"{digits[:2]}.{digits[2:5]}.{digits[5:8]}/{digits[8:12]}-{digits[12:14]}"


print(normalize_cnpj("11222333000181"))       # 11.222.333/0001-81
print(normalize_cnpj("11.222.333/0001-81"))   # 11.222.333/0001-81

3. Official data sources in 2026

SourceTypeCostCoverage
Receita Federal (OpenCNPJ)Public REST APIFree55M+ companies, complete data
Junta Comercial (JUCESP, etc.)State web portalFree (query)Corporate acts, partners
PNCPOCDS REST APIFreeFederal contracts since 2017
OpenCNPJ (https://open.cnpj.ws) is the most complete source: legal name, situação cadastral, opening date, economic activity (CNAE), legal nature, address, and the partner/administrator registry (QSA).

4. Query company data with the API

EnrichLATAM connects to the Receita Federal and exposes the data in a consistent format — the same interface you use for Chile:
import requests

API_KEY = "your_api_key"

def enrich_company_br(cnpj: str) -> dict:
    """Fetches Brazilian company data by CNPJ using EnrichLATAM."""
    response = requests.post(
        "https://api.enrichlatam.com/v1/enrich",
        headers={"X-API-Key": API_KEY},
        json={"identifier": cnpj, "country": "BR"},
    )
    response.raise_for_status()
    return response.json()


cnpj = "11.222.333/0001-81"
if validate_cnpj(cnpj):
    data = enrich_company_br(cnpj)
    print(data["company_name"])    # Razão social
    print(data["status"])          # active / inactive / suspended
    print(data["activity"])        # Main economic activity (CNAE)
Example response:
{
  "country": "BR",
  "identifier": "11.222.333/0001-81",
  "company_name": "EXAMPLE COMPANY LTDA",
  "status": "active",
  "activity": "Custom software development",
  "activity_code": "6201-5/01",
  "size": "small",
  "region": "São Paulo, SP",
  "founded_year": 2010,
  "source": "receita_federal"
}

5. KYB — Business verification

For compliance or B2B onboarding use cases, use the /v1/kyb endpoint which returns the subset of data relevant for verification:
def kyb_company_br(cnpj: str) -> dict:
    response = requests.post(
        "https://api.enrichlatam.com/v1/kyb",
        headers={"X-API-Key": API_KEY},
        json={"identifier": cnpj, "country": "BR"},
    )
    response.raise_for_status()
    return response.json()


result = kyb_company_br("11.222.333/0001-81")
print(result["verified"])       # True / False
print(result["status"])         # active
print(result["legal_name"])     # Registered name

6. Check government contracts

To see whether a company has contracts with the Brazilian federal government:
def government_contracts_br(cnpj: str) -> dict:
    response = requests.post(
        "https://api.enrichlatam.com/v1/tenders",
        headers={"X-API-Key": API_KEY},
        json={"rut": cnpj, "country": "BR"},
    )
    response.raise_for_status()
    return response.json()


contracts = government_contracts_br("28.591.276/0001-00")
print(f"Total contracts: {contracts['total_orders']}")
for c in contracts["orders"]:
    print(f"  {c['code']}{c['name']}")

Brazil vs. Chile — key differences

AspectBrazil 🇧🇷Chile 🇨🇱
IdentifierCNPJ (14 digits)RUT (8 digits + check digit)
Check digits21 (09 or K)
Registered companies~55 million~2 million
BranchesSeparate CNPJ per branchSame RUT
Free official APIOpenCNPJ (Receita Federal)SII bulk file

Resources