# Brazil CNPJ Company Lookup & Search (Receita Federal) (`bigdavidson/brazil-cnpj-companies`) Actor

Look up Brazilian companies by CNPJ or search by CNAE, UF, city and status. Receita Federal open data: razão social, CNAEs, address, phone, Simples/MEI, capital, partners (QSA).

- **URL**: https://apify.com/bigdavidson/brazil-cnpj-companies.md
- **Developed by:** [Jack Sheward](https://apify.com/bigdavidson) (community)
- **Categories:** Lead generation, Business, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 company records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Brazil CNPJ Company Lookup & Search (Receita Federal)

**[Português (PT-BR) abaixo ↓](#português-pt-br)**

Get Brazilian company data from the **Receita Federal CNPJ open data** as clean JSON. You can do it two ways:

- **Lookup / enrich.** Give it a list of CNPJs (with or without punctuation, including the new alphanumeric CNPJs). You get back the full registration record for each one.
- **Search / lead lists.** Find companies by **CNAE** (activity code, or a word like `software`, `dentista` or `hotel`), **state (UF)**, **city**, **legal nature (natureza jurídica)** and **registration status (situação cadastral)**. Optional filters narrow by **size (porte)**, **opening date**, phone on file, or leave out MEIs.

Each company record includes razão social, nome fantasia, main and secondary CNAEs, full address, phone numbers on file, situação cadastral, opening date, capital social, porte, Simples Nacional / MEI status, tax regime, and the partners (QSA) with the CPF masking the Receita applies.

It suits sales and lead-generation teams building B2B prospect lists, KYC/onboarding and supplier checks, CRM enrichment, market sizing by CNAE and region, and AI agents that need to check a Brazilian company.

It uses public, no-login APIs only, with no scraping and no CAPTCHA solving. **Unofficial: not affiliated with the Receita Federal, Minha Receita or BrasilAPI.**

### What you get

One row per company (`tipo_registro: "empresa"`), with the same stable set of keys every time:

| Group | Fields |
|---|---|
| Identity | `cnpj`, `cnpj_formatado`, `cnpj_raiz`, `razao_social`, `nome_fantasia`, `descricao_identificador_matriz_filial` (MATRIZ/FILIAL) |
| Status | `descricao_situacao_cadastral` (ATIVA, BAIXADA, INAPTA, SUSPENSA, NULA), `data_situacao_cadastral`, `descricao_motivo_situacao_cadastral`, `situacao_especial`, `data_inicio_atividade` |
| Activity | `cnae_fiscal` (7-digit string, leading zeros kept), `cnae_fiscal_descricao`, `cnaes_secundarios` \[{codigo, descricao}] |
| Legal / size | `natureza_juridica`, `porte`, `capital_social` (R$), `opcao_pelo_simples`, `opcao_pelo_mei` and their dates, `regime_tributario` \[{ano, forma\_de\_tributacao}] |
| Address | `descricao_tipo_de_logradouro`, `logradouro`, `numero`, `complemento`, `bairro`, `cep`, `municipio`, `codigo_municipio_ibge`, `uf`, plus a ready-made `endereco_completo` |
| Contact | `ddd_telefone_1`, `ddd_telefone_2`, `ddd_fax` exactly as on file, plus `telefones`: a formatted, de-duplicated list of dialable numbers (`(11) 3849-9580`). The Receita stores every number with 8 subscriber digits, so mobiles appear in the form used before Brazil's 2016 switch to 9-digit mobiles (`1180778583`). In live samples, 36–53% of numbers (depending on the sector) were mobiles written this way, and none used the 9-digit form. An 8-digit number starting with 6–9 is a mobile (landlines start with 2–5), and `telefones` gives it in today's form, `(11) 98077-8583`, ready for calls or WhatsApp. It also reads numbers stored with a leading zero (`001138499580`) or the 55 country code, and leaves out values with no valid area code. `email` is always null (see FAQ). |
| Partners | `qsa` \[{nome\_socio, cnpj\_cpf\_do\_socio, qualificacao\_socio, data\_entrada\_sociedade, faixa\_etaria, ...}], `quantidade_socios`. `cnpj_cpf_do_socio` is the masked CPF (`***456789**`) for a person, the partner company's CNPJ as the source gives it (often only the 8-digit root, e.g. `04020670`) for a company, and usually empty for a foreign partner. |
| Meta | `consulta` (what you asked), `fonte`, `atualizacao_base` (Receita release month, e.g. `2026-09`), `consultado_em` |

Field names follow the Receita Federal layout, the same keys BrasilAPI and Minha Receita use, so existing integrations map almost one to one. The exception is CNAE codes, which are 7-digit strings here so leading zeros survive CSV and Excel. Empty strings become `null`.

### Input

| Field | Type | Used in | Description |
|---|---|---|---|
| `mode` | `auto` / `lookup` / `search` | both | `auto` (default): lookup when `cnpjs` are given, search when `cnae`/`uf`/`city` are given (search wins if both are present). |
| `cnpjs` | array of strings | lookup | `33.000.167/0001-01`, `33000167000101`, `12.ABC.345/01DE-35`. An item can hold several CNPJs separated by commas or spaces, and spaces inside one CNPJ (`33 000 167 0001 01`) are joined back. Lost leading zeros are restored, and an 8-digit root is treated as its headquarters (`/0001`). Max 10,000 per run; each extra CNPJ gets a free "not processed" row. |
| `cnae` | array of strings | search | Subclass codes (`5611-2/01`, `5611201`), a class/group prefix (`8630-5`, `8630`, `56`), or words. A built-in list of about 650 common words and phrases in Portuguese and English, covering 89 business types, maps each one to the codes people mean: `software` gives the 5 software/IT codes, `dentista`/`odontologia` gives 8630-5/04, `gráfica` gives the print-shop codes, and `hotel`, `farmácia`, `advogado`, `autopeças`, `livraria`, `marcenaria`, `academia`, `salão de beleza`, `pet shop`, `oficina`, `construtora`, `escola`, `restaurante`, `lawyer` and `gym` work too. Other Portuguese words are matched as whole words, singular or plural, against the official CNAE names (`borracharia`, `contabilidade`). Words too generic to mean one industry (`comércio`, `loja`, `serviços`, `distribuidora`) or matching more than 30 codes (`transporte`) are refused with a free row saying what to send, rather than searched and charged. A **free `aviso` row lists the exact codes each word became.** Max 50 codes. |
| `cnaeScope` | `main` / `any` | search | `main` (default): main activity must match. `any`: main **or** a secondary activity. |
| `uf` | array of strings | search | `SP`, `rj`, `Minas Gerais`… |
| `city` | array of strings | search | `Campinas`, `Campinas/SP`, `Bom Jesus - PI`, or 7-digit IBGE codes. Accents are optional, and old names or Receita spellings work (`Embu`, `Moji Mirim`, `Parati`, `Santa Barbara d Oeste`). A state capital's name means the capital even where smaller towns share it (`Campo Grande` = Campo Grande/MS; `Palmas`, `Boa Vista`, `Rio Branco` and `Belém` likewise). Any other name used in several states (`Bom Jesus`, `São Vicente`) matches all of them unless you add the UF. Either way an `aviso` row says what was chosen. |
| `naturezaJuridica` | array of strings | search | Legal nature, **filtered at the source**. 4-digit codes (`2062` Ltda, `2135` Empresário Individual, `2046`/`2054` S.A.) or words: `ltda`, `sa`, `eireli`, `cooperativa`, `associacao`, or `companies` (Ltda, S.A., EIRELI, sociedades simples and cooperatives, leaving out Empresário Individual/MEI, whose address and phone the source hides). It can be the only filter. |
| `situacao` | array of strings | search | `ATIVA` (default), `BAIXADA`, `INAPTA`, `SUSPENSA`, `NULA` or `all`. English also works (`active`, `closed`, `suspended`). |
| `porte` | array of strings | search | `ME` (micro), `EPP` (small) or `DEMAIS` (everything larger; the Receita does not split medium from large). |
| `openedFrom` / `openedTo` | string | search | Opening-date range (`data_inicio_atividade`): `2024-03-15`, `15/03/2024`, `2024-03` or `2024`. |
| `openedInLastDays` | integer | search | Shortcut for "opened in the last N days". |
| `requirePhone` | boolean | search | Keep only companies with a usable phone on file. |
| `excludeMei` | boolean | search | Drop MEI registrations. |
| `includePartners` | boolean | both | Default `true`. Set `false` to leave out the QSA (data minimisation). |
| `maxRecords` | integer | both | Maximum companies returned and charged. Search default is 100, max 50,000. Lookups return every CNPJ given unless you set this. |

`cnae`, `uf`, `city` and `naturezaJuridica` are filtered by the data source. `situacao`, `porte`, the opening dates, `requirePhone` and `excludeMei` are checked by the actor while it scans results, and companies skipped that way are not charged. The source returns results in its own order, not by date, so a narrow date range over a big area scans many pages. Page size grows with how rarely results match, up to 1,000 per page, and a run scans at most 300,000 results (300 pages). If that limit stops a search short, a free `aviso` row says so.

The Apify platform validates the declared fields against their types, so send list fields as **arrays of strings** and `maxRecords` as an integer. Beyond that the input is lenient. Keys are matched case-insensitively and common aliases work (`cnpj`, `state`, `cidade`, `status`, `activity`, `limit`…). Free-text keys that agents often use (`keyword`, `query`, `q`, `search`, `segmento`) are read as `cnae`, except that a full CNPJ in them is treated as a lookup. Values ignore case and accents. Input that can't be used gets a **free** explanatory row. A request made only of fields the actor doesn't recognise (for example a company `name`) is explained and not run, rather than falling back to the paid example. A search where the only filter is a state or city, sent next to an unrecognised text field, is also held back, because that field was probably meant as the activity. None of this fails the run or costs anything.

**Example: enrich a list**

```json
{ "cnpjs": ["33.000.167/0001-01", "60746948000112", "47960950000121"] }
```

**Example: lead list of active restaurants in Campinas that have a phone**

```json
{ "cnae": ["restaurante"], "city": ["Campinas/SP"], "requirePhone": true, "maxRecords": 500 }
```

**Example: dental clinics in Rio de Janeiro state, excluding MEI**

```json
{ "cnae": ["dentista"], "uf": ["RJ"], "excludeMei": true, "maxRecords": 1000 }
```

**Example: software companies (Ltda or S.A.) in Florianópolis opened in the last 12 months**

```json
{ "cnae": ["software"], "city": ["Florianópolis/SC"], "naturezaJuridica": ["ltda", "sa"], "openedInLastDays": 365, "maxRecords": 200 }
```

### Output example

This record comes from a real run on 2026-09-24 (`cnpjs: ["33.000.167/0001-01"]`). Only the partner, secondary-CNAE and tax-regime lists were shortened (Petrobras has 8 partners on file).

```json
{
  "tipo_registro": "empresa",
  "erro": null,
  "consulta": "33.000.167/0001-01",
  "cnpj": "33000167000101",
  "cnpj_formatado": "33.000.167/0001-01",
  "cnpj_raiz": "33000167",
  "razao_social": "PETROLEO BRASILEIRO S A PETROBRAS",
  "nome_fantasia": "PETROBRAS - EDISE",
  "identificador_matriz_filial": 1,
  "descricao_identificador_matriz_filial": "MATRIZ",
  "situacao_cadastral": 2,
  "descricao_situacao_cadastral": "ATIVA",
  "data_situacao_cadastral": "2005-11-03",
  "motivo_situacao_cadastral": 0,
  "descricao_motivo_situacao_cadastral": "SEM MOTIVO",
  "situacao_especial": null,
  "data_situacao_especial": null,
  "data_inicio_atividade": "1966-09-28",
  "cnae_fiscal": "0600001",
  "cnae_fiscal_descricao": "Extração de petróleo e gás natural",
  "cnaes_secundarios": [
    { "codigo": "1921700", "descricao": "Fabricação de produtos do refino de petróleo" },
    { "codigo": "3520401", "descricao": "Produção de gás; processamento de gás natural" }
  ],
  "codigo_natureza_juridica": 2038,
  "natureza_juridica": "Sociedade de Economia Mista",
  "qualificacao_do_responsavel": 10,
  "ente_federativo_responsavel": null,
  "codigo_porte": 5,
  "porte": "DEMAIS",
  "capital_social": 205431960000,
  "opcao_pelo_simples": null,
  "data_opcao_pelo_simples": null,
  "data_exclusao_do_simples": null,
  "opcao_pelo_mei": null,
  "data_opcao_pelo_mei": null,
  "data_exclusao_do_mei": null,
  "descricao_tipo_de_logradouro": "AVENIDA",
  "logradouro": "REPUBLICA DO CHILE",
  "numero": "65",
  "complemento": null,
  "bairro": "CENTRO",
  "cep": "20031170",
  "municipio": "RIO DE JANEIRO",
  "codigo_municipio": 6001,
  "codigo_municipio_ibge": 3304557,
  "uf": "RJ",
  "codigo_pais": null,
  "pais": null,
  "nome_cidade_no_exterior": null,
  "ddd_telefone_1": "2121660000",
  "ddd_telefone_2": null,
  "ddd_fax": "213224",
  "email": null,
  "qsa": [
    {
      "identificador_de_socio": 2,
      "nome_socio": "ANGELICA GARCIA COBAS LAUREANO",
      "cnpj_cpf_do_socio": "***912137**",
      "codigo_qualificacao_socio": 10,
      "qualificacao_socio": "Diretor",
      "data_entrada_sociedade": "2025-07-29",
      "codigo_faixa_etaria": 8,
      "faixa_etaria": "Entre 71 a 80 anos",
      "codigo_pais": null,
      "pais": null,
      "cpf_representante_legal": "***000000**",
      "nome_representante_legal": null,
      "codigo_qualificacao_representante_legal": 0,
      "qualificacao_representante_legal": "Não informada"
    }
  ],
  "regime_tributario": [
    { "ano": 2024, "forma_de_tributacao": "LUCRO REAL", "quantidade_de_escrituracoes": 1, "cnpj_da_scp": null }
  ],
  "endereco_completo": "AVENIDA REPUBLICA DO CHILE, 65, CENTRO, RIO DE JANEIRO/RJ, CEP 20031-170",
  "telefones": ["(21) 2166-0000"],
  "quantidade_socios": 8,
  "fonte": "minhareceita.org",
  "atualizacao_base": "2026-09",
  "consultado_em": "2026-09-24T16:36:37Z"
}
```

#### Row types

| `tipo_registro` | Charged? | Meaning |
|---|---|---|
| `empresa` | yes, `company-record` | A company record. |
| `erro` | **free** | A CNPJ that is invalid (bad check digits, a CPF, garbage), not found, couldn't be fetched, or wasn't attempted (sources down, run timeout, maxRecords or charge limit reached, over the 10,000 cap). Also a search that couldn't run, a search the source broke off partway (a later page failed after retries: the row says it is a source problem, not your filters), input that couldn't be used, or a max charge too low for one company. The reason is in `erro` and your input is echoed in `consulta`. |
| `aviso` | **free** | A note: how each CNAE word, prefix or legal-nature word was resolved (`filters used: cnae 'software' -> 6201501 …`), input values that were ignored or reinterpreted (including which city a shared name was read as), a CNPJ repeated in your input (looked up and charged once), a search with zero matches, or a search stopped by the per-run scan limit. |

Every row carries the full key set, so you can export it straight to CSV or Excel. A real `erro` row from the same run: `{"tipo_registro": "erro", "erro": "CNPJ not found in the Receita Federal open data (não encontrado) — not charged", "consulta": "12.ABC.345/01DE-35", "cnpj": "12ABC34501DE35", ...all other keys null}`.

### Pricing

Pay per event. There is no subscription.

| Event | Price | When |
|---|---|---|
| `actor-start` | $0.005 | Once per run, and only after the data source has actually answered. |
| `company-record` | $0.003 | For each company returned (`tipo_registro: "empresa"`). |

Error and notice rows are free. Invalid CNPJs are rejected before any request is made. Companies scanned during a search but filtered out by `situacao`, `porte`, the opening dates, `requirePhone` or `excludeMei` are not charged. If the data sources are down for the whole run, the input can't be used, or the run's maximum charge can't pay for the start plus one company ($0.008), the run makes no requests where it can avoid them and costs nothing.

Worked examples:

| Job | Cost |
|---|---|
| Empty input `{}`: the 2 example CNPJs (the daily health check) | $0.005 + 2 × $0.003 = **$0.011** |
| Enrich 100 CNPJs; 97 are found, 3 are invalid or not found | $0.005 + 97 × $0.003 = **$0.296** |
| Lead list: 1,000 active restaurants in São Paulo | $0.005 + 1,000 × $0.003 = **$3.005** |
| 10,000-company lead list | $0.005 + 10,000 × $0.003 = **$30.005** |

Set **Maximum cost per run** in the Apify Console (or `maxRecords`) to cap spend. The actor stops cleanly when it hits the cap and tells you in the status message.

### Data source, freshness and reliability

- **Source:** [Minha Receita](https://docs.minhareceita.org), an open-source project ([MIT licence](https://codeberg.org/cuducos/minha-receita), code now on Codeberg) that serves the Receita Federal's public CNPJ files, published under Brazil's Lei de Acesso à Informação, through a JSON API. Search uses its paginated `/?cnae_fiscal=&uf=&municipio=` endpoint. **Fallback:** if Minha Receita is unreachable, single lookups retry through [BrasilAPI](https://brasilapi.com.br) `/api/cnpj/v1`, capped at 25 per run to respect BrasilAPI's fair-use terms. Search has no fallback.
- **Freshness:** the Receita publishes the full base about once a month. `atualizacao_base` shows the release month each row came from.
- **Reliability:** requests are sequential and paced (≤5/s). 429 and 5xx responses and timeouts are retried with backoff, and a retry never comes sooner than `Retry-After` asks (in seconds or as an HTTP date). When the sources keep failing for about 30 seconds with no good answer (2 minutes for search pages), the actor stops waiting and uses short timeouts, so an outage costs seconds per CNPJ, not minutes. Requests are also fitted inside the run's own timeout: near the end the actor stops fetching, saves what it has, and gives each CNPJ it skipped a free row. Malformed items are skipped (never charged), NaN/Infinity and absurdly large numbers become `null`, and text the source sends that isn't valid UTF-8 is repaired. If a later search page fails after its retries, the companies already found are kept and a free `erro` row says the source broke off, so you know to run it again. The run ends **SUCCEEDED** with explanatory rows rather than failing. Minha Receita is run by volunteers and funded by donations, with no SLA. If you use this heavily, consider [supporting it](https://apoia.se/minhareceita).
- **Scope of search:** CNAE, UF, city and legal nature are filtered at the source. `situacao`, `porte`, opening dates, `requirePhone` and `excludeMei` are filtered by the actor while it scans. Results come in the source's internal order, not alphabetical or by date. Minha Receita labels its search feature as being in testing, so its parameters could change. Its search by partner CPF/CNPJ (`cnpf`) is not offered here: the source's docs warn that it tends to time out, and a search by a person's CPF is a people lookup this actor doesn't do.

### Privacy and LGPD

- This actor returns only what the Receita Federal publishes as open data. The public source already removes **e-mail addresses** from every record. For individual entrepreneurs (Empresário Individual / MEI) it also removes the **street, number, complement and phones**.
- Partner CPFs come **masked** the way the Receita publishes them (`***456789**`). The Receita data often ends an individual entrepreneur's company name with the owner's full CPF. This actor masks those CPFs the same way (`FULANO DE TAL ***456789**`).
- Set `includePartners: false` if you don't need partner names.
- You, the buyer, are the controller of any personal data you process. Under the **LGPD (Lei 13.709/2018)** you need a legal basis for your use, such as legitimate interest for B2B prospecting. You must honour data-subject requests and opt-outs, and you should follow the ANPD's guidance and anti-spam rules for any outreach.

### Use with AI agents / MCP

This actor is designed to be called by agents through the [Apify MCP server](https://mcp.apify.com):

- The output is flat and self-describing, with the same keys on every row. `tipo_registro` tells the agent whether a row is a company, an error or a note, and `erro` explains the problem in plain words.
- List fields (`cnpjs`, `cnae`, `uf`, `city`, `naturezaJuridica`, `situacao`, `porte`) are **arrays of strings**. The platform checks this, so a bare string is rejected before the run starts. Items may still contain comma-separated values.
- Put the activity, state and city in separate fields: `{"cnae": ["dentista"], "uf": ["SP"]}`, not `{"query": "dentistas em SP"}`. The second form isn't guessed at. It returns a free row explaining what to send.
- Common words work in `cnae` (`software`, `dentist`, `hotel`, `lawyer`, `gráfica`, `autopeças`…). Generic words (`comércio`, `loja`, `serviços`) are refused for free rather than guessed at. Always check the free `aviso` row "filters used", which lists the CNAE codes each word became, before trusting a big pull.
- Costs are $0.005 per run plus $0.003 per company returned. Use `maxRecords` to bound a search. The status message says what was charged and why the run stopped.

Example tool input an agent might send:

```json
{ "mode": "search", "cnae": ["contabilidade"], "city": ["Belo Horizonte/MG"], "situacao": ["ATIVA"], "maxRecords": 25, "includePartners": false }
```

### FAQ

**Why is `email` always null?** The Receita's raw open-data files have an e-mail column, but the public Minha Receita/BrasilAPI API strips it from every record to protect privacy. This actor doesn't add e-mails back from any other source. The key stays in the schema for compatibility.

**Why is the address or phone of some companies empty?** For individual entrepreneurs (EI/MEI) the source removes the street and phone numbers for privacy. `requirePhone: true` keeps only companies with a phone on file.

**Do alphanumeric CNPJs work?** Yes. New CNPJs issued from July 2026 can contain letters (e.g. `12.ABC.345/01DE-35`). The check digits are validated with the Receita's new rule.

**How current is the data?** It is as current as the latest Receita monthly release (see `atualizacao_base`). Status changes made after that release won't show yet.

**How do I search every status?** Send `"situacao": ["all"]`. The default is active companies only.

**How do I find the right CNAE?** Send a word (`"cnae": ["padaria"]`, `["software"]`, `["dentist"]`). The free `aviso` row "filters used" lists every code it became, with its official name. If that isn't what you meant, send 7-digit codes from the IBGE CNAE 2.3 table. Words with no CNAE equivalent (`e-commerce`, `startup`), words too generic to mean one industry (`comércio`, `loja`, `distribuidora`) and words that match more than 30 codes (`transporte`, `veículos`) get a free row explaining what to send instead, and nothing is searched with them. Words that match nothing (`sapateiro`) get a free row too.

**Can I search by company name?** No. The public source only searches by CNAE, state, city, legal nature and partner. Look companies up by CNPJ instead.

**Can I filter by size or opening date?** Yes: `porte` (ME / EPP / DEMAIS) and `openedFrom` / `openedTo` / `openedInLastDays`. The source can't filter these, so the actor checks each result as it scans. Narrow the area or activity first, so it doesn't have to scan hundreds of pages.

**How do I get only real companies, not individual entrepreneurs?** Send `"naturezaJuridica": ["companies"]` (or `["ltda"]`). This is filtered at the source, so it is fast. Empresário Individual rows have no street or phone in the public data.

**What if a city name exists in several states?** If one of them is a state capital, the capital is used: `Campo Grande` means Campo Grande/MS, not the towns of the same name in RN and AL. Otherwise, for example "Bom Jesus" (5 states), the actor searches all of them. Either way it adds an `aviso` row saying what it did. Add the UF (`Bom Jesus/PI`, `Campo Grande/RN`) to pick one.

**Are the phone numbers ready to dial?** `telefones` is. The Receita stores 8-digit subscriber numbers, so mobiles registered before 2016 are on file without the leading 9. `telefones` adds it back (`1180778583` → `(11) 98077-8583`), because every 8-digit number starting with 6–9 is a mobile. `ddd_telefone_1` / `ddd_telefone_2` keep the value exactly as on file. Whether a number still belongs to the company is something only a call can tell.

**Maximum sizes?** 10,000 CNPJs per lookup run and 50,000 companies per search run. Records are streamed in batches of 500, so memory doesn't grow with the result count. Peak memory measured locally (2026-09-24): 95 MB on a live 5,000-company search (`apify run`, 15 pages). In the test harness, which runs a simulated source inside the same process, it was 101 MB on a 50,000-company search and 80 MB on a 10,000-CNPJ lookup (78 MB at 1,000 CNPJs, so it stays flat). 128 MB is enough for typical runs; give the largest runs 256 MB. Lookups are sequential and paced at no more than 5 per second (Minha Receita is a volunteer service). Measured locally they average about 0.25 s each, so 10,000 CNPJs take about 45 minutes, and longer from a datacenter far from Brazil. Set the run timeout to at least 90 minutes for 10,000 CNPJs. If the timeout is shorter, the actor stops in time and gives every CNPJ it skipped a free row.

### Changelog

- **0.1 (2026-09-24):** First release. Lookup (numeric and alphanumeric CNPJs, check-digit validation, root → HQ, CNPJs typed with spaces) and search (CNAE code/prefix/word with a Portuguese and English common-word list, UF, city with spelling variants, legal nature at the source, situação, porte, opening date, phone/MEI filters). A free "filters used" row shows how every word was resolved. Minha Receita source with a BrasilAPI fallback. Retries, timeouts and backoff are bounded and fitted inside the run's own timeout. Free rows cover every CNPJ that wasn't looked up. Nothing is charged when the max charge can't pay for one company. Also: phone normalisation (pre-2016 8-digit mobiles returned in today's 9-digit form), CPF masking in company names, and dataset views for companies and contacts. Pre-release review fixes: 42 more business types in the common-word list (`gráfica`, `autopeças`, `livraria`, `marcenaria`, `mudança`…); generic or over-broad CNAE words refused for free instead of truncated; state capitals win for shared city names; free rows for duplicate CNPJs, for a search the source broke off partway, and for the scan limit; `Retry-After` HTTP dates honoured; absurd numbers from the source or the input can no longer fail a run.

***

### Português (PT-BR)

**Consulta CNPJ em lote e busca de empresas por CNAE, UF, cidade e situação cadastral.** Os dados vêm dos dados abertos de CNPJ da Receita Federal e saem em JSON limpo, com os mesmos nomes de campo do layout da Receita (usados também pela BrasilAPI e pelo Minha Receita).

**Não oficial: sem vínculo com a Receita Federal, o Minha Receita ou a BrasilAPI.**

#### O que faz

- **Consulta / enriquecimento:** envie uma lista de CNPJs, com ou sem pontuação e também no novo formato alfanumérico. O ator valida o dígito verificador antes de consultar, restaura zeros à esquerda perdidos no Excel e trata uma raiz de 8 dígitos como a matriz (`/0001`).
- **Busca / lista de leads:** filtre por CNAE (código, prefixo de classe ou palavra como `software`, `dentista`, `hotel`, `farmácia`, `advogado`, `restaurante`), UF, cidade, natureza jurídica e situação cadastral (padrão: `ATIVA`). Há filtros opcionais por porte (ME/EPP/DEMAIS), data de abertura, empresas com telefone e exclusão de MEI. Uma linha gratuita `aviso` mostra exatamente em quais códigos CNAE cada palavra foi convertida.

Cada empresa traz razão social, nome fantasia, CNAE principal e secundários, endereço completo, telefones, situação cadastral, data de abertura, capital social, porte, opção pelo Simples/MEI, regime tributário e o quadro societário (QSA) com o CPF mascarado como a Receita publica.

#### Entrada

| Campo | Descrição |
|---|---|
| `cnpjs` | Lista de CNPJs (consulta), com ou sem pontuação, inclusive com espaços (`33 000 167 0001 01`). Máximo de 10.000 por execução. |
| `cnae` | Códigos (`5611-2/01`), prefixos (`8630-5`) ou palavras (`software`, `dentista`, `padaria`, `gráfica`, `autopeças`, `borracharia`). Palavras genéricas demais (`comércio`, `loja`, `serviços`, `distribuidora`) ou que batem com mais de 30 códigos (`transporte`) são recusadas com uma linha gratuita explicando o que enviar, sem busca e sem cobrança. |
| `cnaeScope` | `main` (só o CNAE principal, padrão) ou `any` (principal ou secundário). |
| `uf` | `SP`, `RJ`, `Minas Gerais`… |
| `city` | `Campinas/SP`, `Bom Jesus - PI`, nomes ou grafias antigas (`Embu`, `Moji Mirim`) ou código IBGE de 7 dígitos. Nome de capital vale a capital (`Campo Grande` = Campo Grande/MS); outros nomes repetidos em vários estados buscam todos, a menos que você informe a UF. |
| `naturezaJuridica` | Códigos (`2062`, `2135`) ou `ltda`, `sa`, `eireli`, `cooperativa`, `companies` (sem empresário individual). Filtrado na fonte. |
| `situacao` | `ATIVA` (padrão), `BAIXADA`, `INAPTA`, `SUSPENSA`, `NULA` ou `all`. |
| `porte` | `ME`, `EPP` ou `DEMAIS`. |
| `openedFrom` / `openedTo` / `openedInLastDays` | Data de abertura (`2024-03-15`, `15/03/2024`, `2024`) ou "abertas nos últimos N dias". |
| `requirePhone` / `excludeMei` | Filtros opcionais da busca. |
| `includePartners` | `false` para omitir o QSA (minimização de dados). |
| `maxRecords` | Limite de empresas. Na busca, o padrão é 100 e o máximo é 50.000. |

Na plataforma Apify, os campos de lista devem ser enviados como **arrays de strings**.

Exemplo: `{"cnae": ["restaurante"], "city": ["Campinas/SP"], "naturezaJuridica": ["companies"], "requirePhone": true, "maxRecords": 500}`

#### Preço

A cobrança é por evento: **$0,005 por execução** (`actor-start`) + **$0,003 por empresa retornada** (`company-record`). Linhas de erro ou aviso são gratuitas, CNPJs inválidos não são cobrados e as empresas descartadas pelos filtros também não. Se o custo máximo da execução não cobrir o início mais uma empresa ($0,008), nada é consultado nem cobrado. Por exemplo, uma lista de 1.000 empresas custa $0,005 + 1.000 × $0,003 = **$3,005**, e o teste padrão (entrada vazia, 2 CNPJs de exemplo) custa **$0,011**.

#### LGPD e privacidade

- A fonte pública (Minha Receita) já **remove os e-mails** de todas as empresas. No caso de empresário individual/MEI, remove também **logradouro, número, complemento e telefones**. Por isso o campo `email` é sempre `null`.
- Os CPFs dos sócios pessoas físicas vêm **mascarados** como a Receita publica (`***456789**`). Sócios pessoas jurídicas aparecem com o CNPJ como a fonte informa (muitas vezes só a raiz de 8 dígitos), e sócios estrangeiros costumam vir sem documento. Quando o CPF aparece no fim da razão social de empresário individual, este ator o mascara do mesmo jeito.
- Quem usa os dados é o **controlador** perante a **LGPD (Lei 13.709/2018)**. É preciso ter base legal para o tratamento (por exemplo, legítimo interesse em prospecção B2B), atender pedidos de titulares e de descadastramento e seguir as orientações da ANPD. Use `includePartners: false` se não precisar dos nomes dos sócios.

#### Perguntas frequentes

- **Os dados estão atualizados?** Estão atualizados até a última base mensal divulgada pela Receita (campo `atualizacao_base`, por exemplo `2026-09`).
- **CNPJ alfanumérico funciona?** Sim. O dígito verificador é validado pela nova regra da Receita (IN RFB 2.229/2024).
- **Por que algumas empresas vêm sem telefone ou endereço?** Porque a fonte oculta esses dados de empresários individuais/MEI por privacidade. Use `requirePhone: true`.
- **Os telefones já vêm prontos para ligar?** O campo `telefones` sim. A Receita guarda números com 8 dígitos, então celulares cadastrados antes de 2016 aparecem sem o 9 inicial. Todo número de 8 dígitos começando com 6 a 9 é celular, e o ator devolve em `telefones` a forma atual (`1180778583` → `(11) 98077-8583`), pronta para ligação ou WhatsApp. `ddd_telefone_1` e `ddd_telefone_2` mantêm o valor original.
- **A busca inclui empresas baixadas?** Só se você pedir: `"situacao": ["all"]` ou `["BAIXADA"]`.
- **A fonte caiu, e agora?** O ator tenta de novo com espera crescente, respeitando o `Retry-After`, sempre dentro do tempo limite da execução. Para consultas individuais ele recorre à BrasilAPI e, se nada responder, devolve linhas de erro gratuitas sem cobrar a execução. Se uma página posterior da busca falhar, as empresas já encontradas são mantidas e uma linha `erro` gratuita avisa que o problema foi da fonte, não dos seus filtros.
- **Dá para buscar pelo nome da empresa?** Não. A fonte pública só busca por CNAE, UF, cidade, natureza jurídica e sócio. Use o CNPJ.
- **Como trazer só empresas (sem empresário individual)?** Use `"naturezaJuridica": ["companies"]` ou `["ltda"]`. O filtro é feito na fonte.

# Actor input Schema

## `mode` (type: `string`):

auto = lookup when CNPJs are given, search when cnae/uf/city/naturezaJuridica are given (search wins if both). lookup = enrich the CNPJ list. search = find companies by CNAE + UF + city + legal nature + situação. Cost: $0.005 per run + $0.003 per company returned; error/notice rows are free.

## `cnpjs` (type: `array`):

Lookup mode. Array of strings. CNPJs with or without punctuation (33.000.167/0001-01 or 33000167000101), numeric or the new alphanumeric format (12.ABC.345/01DE-35). An item may hold several CNPJs separated by commas or spaces; spaces inside one CNPJ (33 000 167 0001 01) are joined back. Leading zeros lost by spreadsheets are restored; an 8-digit root is read as its headquarters (0001). Check digits are validated before any request — invalid ones get a free error row. Max 10,000 per run (extra CNPJs each get a free 'not processed' row).

## `cnae` (type: `array`):

Search mode. Array of strings. CNAE subclass codes (5611-2/01 or 5611201), a class/group prefix (8630-5, 8630, 56) that expands to its subclasses, or words. Common business words in Portuguese or English map to the right codes (software, dentista, hotel, farmácia, advogado, academia, salão de beleza, pet shop, oficina, construtora, escola, restaurante, lawyer, gym...); other Portuguese words are matched whole-word (singular/plural) against the official CNAE names. Words too generic for one industry (comércio, loja, serviços, distribuidora) or matching over 30 codes (transporte) are refused with a free row instead of being searched. A free 'aviso' row lists exactly which codes each word became. Max 50 codes.

## `cnaeScope` (type: `string`):

main = the company's main activity (CNAE fiscal) must match. any = main OR any secondary activity matches (more results, less precise).

## `uf` (type: `array`):

Search mode. Array of strings. Two-letter state codes (SP, RJ, MG...) or state names (São Paulo, Minas Gerais). Several allowed.

## `city` (type: `array`):

Search mode. Array of strings. City names, accents optional, optionally with the state: Campinas, Campinas/SP, 'Bom Jesus - PI'. Old or Receita spellings are recognised (Moji Mirim, Parati). A state capital's name means the capital (Campo Grande = Campo Grande/MS); any other name that exists in several states matches all of them unless a UF is given. 7-digit IBGE codes also work.

## `naturezaJuridica` (type: `array`):

Search mode, filtered at the source. Array of strings: 4-digit codes (2062 = Sociedade Empresária Limitada, 2135 = Empresário Individual, 2046/2054 = S.A.) or words: ltda, sa, eireli, cooperativa, associacao, or 'companies' (Ltda, S.A., EIRELI, sociedades simples, cooperatives — leaves out Empresário Individual/MEI, whose address and phone the source hides). Can be the only search filter.

## `situacao` (type: `array`):

Search mode. Array of strings: ATIVA (default), BAIXADA, INAPTA, SUSPENSA, NULA, or 'all'. English also accepted (active, closed, suspended). Lookups always return the company whatever its status.

## `porte` (type: `array`):

Search mode. Array of strings: ME (micro), EPP (small) or DEMAIS (everything larger — the Receita does not split medium from large). Checked by the actor while it scans; skipped companies are not charged.

## `openedFrom` (type: `string`):

Search mode. Earliest opening date (data\_inicio\_atividade): YYYY-MM-DD, DD/MM/YYYY, YYYY-MM or YYYY. Checked by the actor while it scans — the source returns companies in its own order, so a narrow date range over a large area scans many pages (up to 300,000 results per run).

## `openedTo` (type: `string`):

Search mode. Latest opening date: YYYY-MM-DD, DD/MM/YYYY, YYYY-MM (end of that month) or YYYY (end of that year).

## `openedInLastDays` (type: `integer`):

Search mode. Shortcut for openedFrom = today minus N days. New companies only appear after the Receita's monthly release (see atualizacao\_base).

## `requirePhone` (type: `boolean`):

Search mode. Skip companies with no usable phone on file (telefones gives pre-2016 8-digit mobiles in today's 9-digit form). Individual entrepreneurs (MEI/EI) have their phone and street hidden by the source for privacy, so this mostly keeps legal entities (naturezaJuridica 'companies' does that at the source, faster).

## `excludeMei` (type: `boolean`):

Search mode. Skip companies registered as MEI (microempreendedor individual).

## `includePartners` (type: `boolean`):

Include the partner list (quadro societário) with names, roles, entry dates and age bands. Individual partners' CPFs come masked by the Receita (\***456789**); partner companies show their CNPJ as the source provides it. Turn off for data minimisation (LGPD).

## `maxRecords` (type: `integer`):

Maximum companies returned (and charged at $0.003 each). Search default: 100. Lookup default: every CNPJ given.

## Actor input object example

```json
{
  "mode": "auto",
  "cnpjs": [
    "33.000.167/0001-01",
    "00.000.000/0001-91"
  ],
  "cnaeScope": "main",
  "situacao": [
    "ATIVA"
  ],
  "requirePhone": false,
  "excludeMei": false,
  "includePartners": true
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `overview` (type: `string`):

No description

## `contacts` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "cnpjs": [
        "33.000.167/0001-01",
        "00.000.000/0001-91"
    ],
    "situacao": [
        "ATIVA"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("bigdavidson/brazil-cnpj-companies").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "cnpjs": [
        "33.000.167/0001-01",
        "00.000.000/0001-91",
    ],
    "situacao": ["ATIVA"],
}

# Run the Actor and wait for it to finish
run = client.actor("bigdavidson/brazil-cnpj-companies").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "cnpjs": [
    "33.000.167/0001-01",
    "00.000.000/0001-91"
  ],
  "situacao": [
    "ATIVA"
  ]
}' |
apify call bigdavidson/brazil-cnpj-companies --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bigdavidson/brazil-cnpj-companies"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/UwbXxyunwEELNFP29/builds/EJRF8n3WSsKoC4hhE/openapi.json
