Skip to content

DBT: Cnpj 2025 02 04 Gold

File location: s3://trase-storage/brazil/logistics/cnpj/gold/cnpj_2025_02_04/cnpj_2025_02_04_gold.parquet

DBT model name: cnpj_2025_02_04_gold

Explore on Metabase: Full table; summary statistics

Explore dependencies/lineage: link


Description

Final CNPJ table based on data from 'Receita Federal do Brasil'. Versions of different years should be located at brazil/logistics/cnpj/gold/cnpj_YYYY_MM_DD/cnpj_YYYY_MM_DD_gold.parquet.

Brazilian National Registry of Legal Entities (CNPJ) from the Federal Tax Agency (RFB)

This is a dataset of CNPJs (Cadastro Nacional de Pessoas Jurídicas, or National Registry of Legal Entities) downloaded from the publicly-available dataset hosted at Brazil's RFB (Receita Federal do Brasil, or Federal Tax Agency). CNPJs are unique identifiers for legal entities in Brazil. This dataset is important for Trase's efforts to map and model supply chains; in particular for all of our SEI-PCS models in Brazil.

It is a large dataset: in the 2026-02 version the final, cleaned table is about 70 million rows and ~25 GB uncompressed. Because of that, the easiest way to explore it is through Athena (see How to explore the data below) rather than downloading the whole file.

To build the CNPJ table, we consolidate data from multiple files that the Federal Tax Agency makes available. The details are found in the link on how to update the data (futher below). In summary, the relevant files for building the table are the following:

File Description
cnpj-metadados.pdf Data dictionary
Cnaes Economic activity codes
Empresas* Companies
Estabelecimentos Establishments (sites of a company)
Motivos Reasons (for a registration status)
Municipios Municipalities
Naturezas Juridic natures
Paises Countries
Qualificaoes Qualifications
Simples Simplified-tax-regime membership
Socios* Partners
Regime Tributario Tax regime data: Immune and Exempt, Arbitrated Profit, Presumed Profit and Actual Profit

How often is the data updated by the Brazilian government?

The data is updated on a monthly basis. We aim to download the February version each year, so it already reflects all new registrations from the previous year.

Version history

  • 2026: s3://trase-storage/brazil/logistics/cnpj/gold/cnpj_2026_02/cnpj_2026_02_gold.parquet
  • 2025: s3://trase-storage/brazil/logistics/cnpj/gold/cnpj_2025_02_04/cnpj_2025_02_04_gold.parquet
  • 2023: s3://trase-storage/brazil/logistics/cnpj/gold/cnpj_2023_08_12/cnpj_2023_08_12_gold.parquet
  • 2022: s3://trase-storage/brazil/logistics/cnpj/gold/cnpj_2022_11_24/cnpj_2022_11_24_gold.parquet
  • 2019: s3://trase-storage/brazil/logistics/cnpj/gold/cnpj_2019_02/cnpj_2019_02_gold.parquet

How to update the dataset to a newer version

The full process — downloading the raw files from the RFB share, converting them to UTF-8 + uploading them to S3, adjusting the dbt pipeline, and running it to produce the new gold table — is documented in:

trase/data/brazil/logistics/cnpj/receita_federal_do_brasil/cnpj_update_guide.md

How to explore the data

Because the table is large, the easiest entry points are the ones that don't require downloading the whole file: Metabase or Athena (an AWS service that lets you run SQL queries directly against the files in S3).

1. Metabase (no code)

Pre-configured Athena connection, browse and query in the browser:

Metabase cnpj_2026_02 table

Or navigate manually: Brazil CNPJs (Athena) → s3_big_data → cnpj_2026_02.

2. Athena from Python

Use the Trase helper functions, which connects to Athena and can return the result as a Pandas DataFrame, Polars, or Polars LazyFrame (read_athena_pandas, read_athena_polars, read_athena_polars_lazy):

import pandas as pd
from trase.tools.aws.aws_helpers import read_athena_pandas

# Example 1: read a few records into a Pandas dataframe
df_sample = read_athena_pandas("SELECT * FROM cnpj_2026_02 LIMIT 5")

# Example 2: get a few records from TO state with soy farming as primary or secondary activity (CNAE: 115600)
soy_query = f"""
    SELECT * FROM cnpj_2026_02
    WHERE state = 'TO'
    AND (cnae = 115600 OR cnae_secondary LIKE '%115600%')
    LIMIT 5
"""
df_soy_sample = read_athena_pandas(soy_query)

# Example 3: get company details based on their CNPJ number
example_cnpjs = pd.DataFrame({
    "cnpj": ['11641575000100', '65004913000121', '12345678910']
})
cnpj_values = ", ".join(f"'{cnpj}'" for cnpj in example_cnpjs["cnpj"])
query = f"""
    SELECT cnpj, company_name, municipality
    FROM cnpj_2026_02
    WHERE cnpj IN ({cnpj_values})
"""
df_cnpj_details = read_athena_pandas(query)

3. Athena from R

Minimal example using the noctua package (Athena client in pure R; install once with install.packages("noctua")):

library(noctua)
library(DBI)

con <- dbConnect(
  noctua::athena(),
  s3_staging_dir = "s3://trase-temp/athena/",
  region_name    = "eu-west-1"
)

df <- dbGetQuery(con, "
  SELECT cnpj, company_name, municipality
  FROM s3_big_data.cnpj_2026_02
  WHERE cnpj IN ('11641575000100', '65004913000121')
")

print(df)

Authentication uses the AWS credentials already configured on your machine.

Acceptance criteria for sufficient level of quality of the dataset

We currently have no acceptance criteria defined for this dataset.


Details

Column Type Description
cnpj VARCHAR
company_name VARCHAR
juridic_nature BIGINT
nature_name VARCHAR
company_social_capital DOUBLE
company_size VARCHAR
company_size_name VARCHAR
national_responsible_entity VARCHAR
id_head_branch UTINYINT
head_branch_name VARCHAR
trade_name VARCHAR
id_registration_status UTINYINT
registration_status_name VARCHAR
registration_status_date DATE
id_registration_status_reason VARCHAR
reason_name VARCHAR
foreign_city_name VARCHAR
id_country INTEGER
country_name VARCHAR
start_activity_date DATE
cnae INTEGER
cnae_name VARCHAR
cnae_secondary VARCHAR
cnae_secondary_array INTEGER[]
address_type VARCHAR
address_street VARCHAR
address_number VARCHAR
address_complement VARCHAR
address_neighbourhood VARCHAR
postal_code VARCHAR
id_city INTEGER
city_name VARCHAR
municipality VARCHAR
id_state BIGINT
state VARCHAR
phone_1_area_code VARCHAR
phone_1 VARCHAR
phone_2_area_code VARCHAR
phone_2 VARCHAR
fax_area_code VARCHAR
fax VARCHAR
email VARCHAR
special_status VARCHAR
special_status_date VARCHAR

No data tests defined 🧐

"""
Thin wrapper: join logic lives in
`trase.data.brazil.logistics.cnpj.cnpj_preprocessing.py`.
"""

from trase.data.brazil.logistics.cnpj.cnpj_preprocessing import process_gold


def model(dbt, cursor):
    dbt.config(materialized="external")

    return process_gold(
        cursor,
        site_rel=dbt.ref("cnpj_site_2025_02_04_silver"),
        company_rel=dbt.ref("cnpj_company_2025_02_04_silver"),
        nature_rel=dbt.ref("cnpj_nature_2025_02_04_silver"),
        reason_rel=dbt.ref("cnpj_reason_2025_02_04_silver"),
        country_rel=dbt.ref("cnpj_country_2025_02_04_silver"),
        cnae_rel=dbt.ref("cnpj_cnae_2025_02_04_silver"),
        city_rel=dbt.ref("cnpj_city_2025_02_04_silver"),
        city_ibge_rel=dbt.ref("cnpj_city_ibge_2025_02_04_silver"),
    )