Brazil CNPJ Lookup & Enrichment (Batch)
Pricing
$10.00 / 1,000 resolved cnpj records
Brazil CNPJ Lookup & Enrichment (Batch)
Batch-lookup Brazilian company registry (CNPJ) records: legal name, status, address, CNAE activity codes, partners, and more. Multi-source failover, pay only for resolved records.
Pricing
$10.00 / 1,000 resolved cnpj records
Rating
0.0
(0)
Developer
Alison Moura
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Batch-lookup Brazilian company registry (CNPJ) records and get back clean, normalized JSON: legal name, trade name, registration status, full address, primary/secondary CNAE activity codes, partners (sócios), Simples Nacional/MEI status, and more — one record per CNPJ, ready to pipe into a CRM, KYC/compliance check, lead-scoring pipeline, or sales database.
Who this is for
Anyone building on top of Brazilian company data without wanting to deal with Receita Federal's raw, denormalized open-data dumps directly: fintech/ KYC and AML tooling, B2B sales and lead-gen tools that need to validate and enrich a list of company CNPJs, compliance workflows, procurement/vendor vetting, or just a developer who needs "give me company X's registered address and legal status" without writing a CNPJ parser from scratch.
What you send in
{"cnpjs": ["33.000.167/0001-01","19191919000138"],"maxConcurrency": 5}
cnpjs— a list of CNPJs, punctuation optional (33.000.167/0001-01and33000167000101both work). Supports both the classic all-numeric CNPJ and the new alphanumeric CNPJ format Receita Federal began issuing to new registrations on 2026-07-31 (Instrução Normativa RFB nº 2229/2024) — existing numeric CNPJs are unaffected and keep working forever, the two formats simply coexist.maxConcurrency— optional, default 5, max 10. Kept modest on purpose; see "Rate limits & fair use" below.
What you get back
One dataset record per input CNPJ. Example (trimmed for length — the real output includes all 8 Petrobras partners and all 5 secondary CNAE codes):
{"cnpj": "33000167000101","cnpj_formatted": "33.000.167/0001-01","razao_social": "PETROLEO BRASILEIRO S A PETROBRAS","nome_fantasia": "PETROBRAS - EDISE","status": { "code": 2, "description": "ATIVA", "reason": "SEM MOTIVO", "date": "2005-11-03" },"opening_date": "1966-09-28","legal_nature": { "code": 2038, "description": "Sociedade de Economia Mista" },"company_size": { "code": 5, "description": "DEMAIS" },"share_capital_brl": 205431960000,"branch": { "is_headquarters": true, "type_code": 1, "type_description": "MATRIZ" },"primary_activity": { "code": "0600001", "description": "Extração de petróleo e gás natural" },"secondary_activities": [{ "code": "1921700", "description": "Fabricação de produtos do refino de petróleo" }],"address": {"street_type": "AVENIDA", "street": "REPUBLICA DO CHILE", "number": "65","complement": null, "neighborhood": "CENTRO", "city": "RIO DE JANEIRO","city_ibge_code": 3304557, "state": "RJ", "zip_code": "20031170", "country": "Brasil"},"contact": { "phones": ["2121660000"], "fax": "213224", "email": null },"simples_nacional": { "opted_in": null, "opted_in_date": null, "excluded_date": null },"mei": { "opted_in": null, "opted_in_date": null, "excluded_date": null },"partners": [{ "name": "ANGELICA GARCIA COBAS LAUREANO", "role": "Diretor", "role_code": 10,"entry_date": "2025-07-29", "age_range": "Entre 71 a 80 anos","document_masked": "***912137**", "legal_representative_name": null }],"partners_count": 8,"_meta": { "source": "minhareceita", "retrieved_at": "2026-08-17T13:45:00+00:00" }}
For a CNPJ that's invalid, not found, or that every source failed to answer, you still get a record so you can see what happened to every input — it's just not charged (see Pricing):
{ "cnpj_input": "not-a-cnpj", "status": "invalid_format", "error": "expected 14 characters after removing punctuation, got 8" }{ "cnpj": "10433218196071", "cnpj_formatted": "10.433.218/1960-71", "status": "not_found" }
Partner CPFs are pre-masked by the upstream source (e.g. ***912137**) —
Receita Federal's own public data never exposes full partner CPFs through
these APIs, so there's no additional PII handling risk here.
Pricing
Pay-per-event: you are charged only for successfully resolved CNPJs
(event cnpj-record). Invalid CNPJ formats, not-found CNPJs, and CNPJs
where every source failed are written to your dataset for visibility but
are never charged. See the Actor's Store page for the current per-event
price.
Data sources, freshness & accuracy
Underlying data is Brazil's official CNPJ company registry, published by Receita Federal (the federal tax authority) as free, public open data. Neither this Actor nor its upstream sources guarantee the data is real-time or free of errors — Receita Federal's own open-data dumps are refreshed periodically (commonly monthly), and any of the CNPJ record fields (status, address, capital, etc.) can lag a company's real-world state by that update cycle. For anything with legal/compliance weight, treat this as a fast first-pass lookup, not a substitute for an official Receita Federal certidão.
Rate limits & fair use
This Actor deliberately paces its own requests to the free upstream APIs
it wraps (see "Design decision" below) rather than firing everything at
once — neither upstream source publishes a fixed requests/second limit,
but both are free community services without an SLA, and hammering them
would be a good way to get blocked and break this Actor for everyone
using it. In practice this means: very large batches (hundreds+ of CNPJs)
will take some real wall-clock time to finish, by design. maxConcurrency
lets you tune this within a conservative ceiling (max 10).
For the Aurora project (internal)
This product was built as Aurora's first shippable revenue attempt (see
the repo root README.md, AGENTS.md, OPPORTUNITIES.md #1, and
DECISIONS.md ADR-003/ADR-004 for the full strategic context). This
section is the build record for that decision chain — deployment is the
one remaining owner action.
Design decision: wrap free public APIs (option A), not self-host (option B)
Chose option (a): wrap existing free public CNPJ lookup APIs with batching/failover/retry, rather than (b) downloading and self-hosting a queryable index of the full Receita Federal open-data dump on this VPS.
Reasoning:
- The full RFB CNPJ open-data dump lives at
dadosabertos.rfb.gov.br/CNPJ/dados_abertos_cnpj/, published monthly as zipped CSV files split intoEmpresas*.zip,Estabelecimentos*.zip,Socios*.zip, plus reference tables (CNAEs, municípios, etc). This VPS could not reach the domain directly during this research session (connection timed out on both an HTTPS fetch and a rawcurlfrom this machine — possibly transient, possibly network-level filtering; not investigated further since it wasn't blocking for the option-(a) path), so this is based on Receita Federal's own gov.br documentation page and the READMEs of the two community parser projects named in ADR-004 (cuducos/minha-receita,aphonsoar/...Dados_Publicos_CNPJ), not a direct fetch. Reported size as of 2021 was ~4.7GB compressed / ~17GB uncompressed; five more years of company registrations since then means the current size is almost certainly larger, and a queryable index (as opposed to raw CSVs) typically adds overhead on top of that. This VPS has 3.8GB RAM and 77GB disk total — self-hosting the full dataset would consume a large share of the disk budget and leave little headroom for anything else Aurora might need to run concurrently, for a V1 whose demand is still unvalidated. - Option (a) needs no VPS-uptime dependency for the Actor to function (it calls the source APIs directly from Apify's infrastructure, not from this VPS), ships in hours not days, and lets us learn whether this product gets real paid usage before investing in self-hosting — the exact sequencing ADR-003/004 already committed to ("ship one actor, measure 1-2 weeks, only then invest more").
- Nothing found during source research (below) made option (a) infeasible — the opposite of the trigger condition the task set for falling back to (b).
If this Actor gets real, sustained paid usage and the free public sources
turn out to be a reliability bottleneck, the natural next step (not done
here) is exactly option (b): self-host a minha-receita-style index built
from the same RFB open data minhareceita.org itself is built from, sized
down to just the fields this Actor's schema uses to fit VPS RAM/disk
constraints, and have this Actor's sources.py call http://127.0.0.1
instead of the public internet. The self-hosted instance would slot in as
a new highest-priority SourceConfig in sources.py with no change to
normalize.py, since it would speak the same RFB field schema.
Source selection (verified 2026-08-17, not assumed)
Three free public CNPJ APIs were evaluated: BrasilAPI, ReceitaWS, and Minha Receita.
| Source | Used as | Why |
|---|---|---|
| minhareceita.org | Primary | MIT-licensed, fully open source, explicitly built to be self-hostable ("I make this application available for each person to run in their own infrastructure"). No fixed published rate limit and no SLA, but also no clause anywhere restricting commercial use or resale — the strongest permissive signal of the three. |
| brasilapi.com.br | Failover only | Verified byte-identical response schema to minhareceita for the same CNPJ (see tests/fixtures/*_petrobras.json — same field names, same "não encontrado" 404 body), meaning it's backed by the same RFB data pipeline: it adds operational independence (separate infra/caching) if minhareceita.org is down, but not data independence. Its own Terms of Use are still in beta and ambiguous about bulk/automated use, so it's deliberately never the primary source here, and is paced even more conservatively than minhareceita (1 req/s self-imposed ceiling vs 2 req/s). |
| receitaws.com.br | Not used, anywhere | Its Terms of Use (receitaws.com.br/terms.pdf, Cláusula Oitava, fetched and read in full) state verbatim: "Os dados retornados através das APIs podem ser utilizados apenas para benefício próprio do usuário, não sendo permitida qualquer comercialização através de outros sites ou qualquer outro meio" — data returned may only be used for the user's own benefit; commercialization through other sites/means is explicitly forbidden. That's a direct conflict with reselling it as a paid Actor, so it was excluded per this task's own instruction to drop any source whose terms explicitly prohibit resale. (Its free tier is also capped at 3 requests/minute, which alone would make it impractical for a batch product.) |
Both used sources are paced with self-imposed, deliberately conservative
request intervals (not taken from a published limit — neither source
publishes one) plus exponential backoff on 429/5xx and automatic failover
between them; see the module docstring in cnpj_lookup/sources.py for the
full reasoning and exact ToS quotes.
What was actually tested vs. not
Tested and passing:
cnpj_lookup/cnpj_utils.py— CNPJ cleaning, both classic-numeric and new-alphanumeric check-digit validation, formatting. The alphanumeric check-digit algorithm was independently re-derived from Receita Federal's published rule (ASCII-48 char mapping + mod-11, same weight sequences as the classic algorithm) and cross-checked against a third-party worked example, which it reproduces exactly (seetests/test_cnpj_utils.pydocstring).cnpj_lookup/normalize.py— mapping tested against real API responses (not hand-written fixtures) captured 2026-08-17 for CNPJ 33.000.167/0001-01 (Petrobras, a public real-world CNPJ) from both live sources.cnpj_lookup/sources.py— failover, not-found short-circuiting, retry/ backoff, and rate-limiting logic, tested withhttpx.MockTransport(no real network calls in the automated test suite).- 31/31 tests pass (
pytest, run inside a Python 3.12 venv — see below on why 3.12 not the VPS's default 3.10). - Full end-to-end run against the live internet, via both a direct
python -m cnpj_lookupinvocation and the officialapify-cli runcommand (which reads.actor/actor.jsonexactly as the real platform would): verified all three real code paths live — a real resolved CNPJ (Petrobras), a real not-found CNPJ (10.433.218/1960-71, a randomly generated but checksum-valid CNPJ confirmed via live lookup to not exist in the registry), and a real invalid-format input. Deduping a CNPJ supplied in two different formats was also verified live (both"33.000.167/0001-01"and"33000167000101"in one input list produced exactly one output record). apify-cli validate-schemapasses for bothinput_schema.jsonanddataset_schema.json.- Ruff lint: clean, zero warnings.
Not tested / could not verify locally:
- The "all sources failed" path (
AllSourcesFailedError) is only exercised by the mocked unit tests, not live — there was no way to make both real upstream APIs fail simultaneously on demand. - Real pay-per-event charging behavior: running locally, the Apify
SDK correctly no-ops
Actor.charge/push_data(charged_event_name=...)with the log line, because no Apify platform pricing config is available outside a real platform run. The charging code path is exercised (it's called on every successful resolution) but the actual billing behavior can only be confirmed after deploying and monetizing on the real platform."Ignored attempt to charge for an event - the Actor does not use the pay-per-event pricing" - Docker build: this VPS has no Docker installed (
dockeris not on PATH, no root/sudo available to install it), so theDockerfilewas never actually built into an image here. It follows Apify's own current official Python Actor template (apify/actor-templates,templates/python-start/Dockerfile, fetched viagh api2026-08-17) line-for-line except for the base image tag (3.13, chosen for stability — some Apify example templates note 3.14 has known incompatibilities with certain compiled dependencies) and the package name (cnpj_lookupinstead ofmy_actor). Apify's own build pipeline will build this Dockerfile when youapify pushor upload via Console — that step has not happened yet (see Deployment below). - Local testing used Python 3.12 in a throwaway venv, not the VPS's
default Python 3.10.12 — the
apifySDK requires Python ≥3.11, and this VPS'spython3.10-venvisn't installed and there's no passwordless sudo to install it (a known constraint, seeAGENTS.md). Python 3.12 was available system-wide (python3.12, with a workingvenvmodule) and was used instead; this matches what the Actor will actually run under on Apify's platform (3.13 per the Dockerfile) closely enough not to be a concern, since the SDK's 3.11+ requirement is the load-bearing constraint, not the exact minor version. - No real paid usage, no Apify Store listing yet — this Actor has not been deployed anywhere outside this repo and this VPS.
Deployment (the one remaining owner action)
This Actor is built, tested (as above), and ready to push — it has not been published. Publishing requires an Apify account, which needs a one-time human browser step (OAuth consent) that's out of scope for Aurora to do autonomously (see ADR-004). Steps for the owner:
- Create an Apify account, if not already done: go to
apify.com, "Continue with GitHub" (should reuse
alison-moura's already-verified GitHub email, no new email verification loop expected). - Install the Apify CLI (already verified working via in this repo — no separate install needed) and log in:npx apify-cli$npx apify-cli login
- Push the Actor from this directory:
This builds the Docker image on Apify's infrastructure (not locally) and creates/updates the Actor under your account.cd products/cnpj-lookupnpx apify-cli push - Set up monetization in Apify Console (Actor → Monetization): choose
"Pay per event", and configure the
cnpj-recordevent (title, description, and price are already defined in.actor/pay_per_event.json— the Console may pick these up automatically on push, or may require re-entering them manually; this step was not verifiable without a live account). A price of $0.01–0.03 per resolved record is a reasonable starting point given Casa dos Dados (the existing commercial competitor named in ADR-004) charges for the same underlying data. - Write/attach a payout method (PayPal, $20 minimum payout — fastest path per ADR-003's own research) so revenue can actually be withdrawn.
- Publish to the Apify Store (Actor → Publication) so it's
discoverable — this Actor's
README.md(this file, the part above the "For the Aurora project" section) is written for that Store listing. - Report back actual results (impressions, runs, revenue) into
BUSINESS.md— do not fabricate numbers before they exist.
No code changes should be needed for any of the above; this is a Console/account-setup sequence, not a development task.