Brazil CNPJ Sanctions — CEIS, CNEP, CEPIM and Leniency
Pricing
$2.00 / 1,000 cnpj checkeds
Brazil CNPJ Sanctions — CEIS, CNEP, CEPIM and Leniency
Screen Brazilian legal entities against four official CGU public downloads, with checksum validation and daily caching.
Pricing
$2.00 / 1,000 cnpj checkeds
Rating
0.0
(0)
Developer
Kadev Code
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Brazil CNPJ Sanctions Screening
Screen Brazilian companies against the official CEIS, CNEP, CEPIM and Acordos de Leniência public downloads from the CGU Portal da Transparência. This Actor accepts a batch of CNPJs and produces one structured dataset item for each distinct normalized identifier. It requires no Portal API key and runs with Python 3.12 and the Apify SDK, without a browser.
This is an informational lookup and does not replace an official certificate (consulta informativa; não substitui certidão oficial). Review source records and obtain the appropriate official certificate before making a procurement or legal decision. A list occurrence is not a risk score or an automatic rejection rule.
Input
{"cnpjs": ["00.000.000/0001-91", "11.222.333/0001-81"]}
Provide between 1 and 1,000 strings. Standard or partial masks (for example,
00.000.000/000191), unformatted numeric CNPJs,
and alphanumeric CNPJs are supported. The two check digits are validated using
the Receita Federal algorithm.
Validation checks the identifier's syntax and checksum, not its registration or
operating status. Duplicate normalized identifiers are delivered and billed once.
Missing local input uses the schema's default example, a public company CNPJ.
An empty list or malformed top-level input produces a free input-error item.
Output and interpretation
The following is an illustrative shape, not a live statement about this company:
{"cnpj": "00000000000191","companyName": null,"validCnpj": true,"sanctioned": false,"activeSanction": false,"lists": [],"records": [],"stale": false,"staleSources": [],"partialData": false,"warnings": [],"sourceQuality": {},"datasetDate": {"CEIS": "2026-10-21","CNEP": "2026-10-21","CEPIM": "2026-10-21","Acordos de Leniência": "2026-10-22"},"error": null}
Each matching record contains list, cnpj (the source identifier), matchType,
sanctionType, sanctioningBody, sanctionScope (ABRANGÊNCIA DA SANÇÃO when
published), startDate, endDate, dateUnknown, active and legalBasis.
Matching includes every establishment sharing the first eight CNPJ characters:
matchType: "exact" matches the requested identifier; "sameRoot" identifies
another branch or headquarters in that company root. Review the source's scope
before deciding whether a sanction legally applies to a specific establishment.
Dates use ISO format; absent or invalid dates and unavailable fields are null.
CEPIM does not publish start/end dates in this download, so
both remain null. For leniency, legalBasis contains the published agreement
terms; for CEPIM, it contains the reason for the impediment.
Every record has the same 36 keys. The table below includes all fields. Text is
trimmed and CPF patterns are redacted, including in company names and remarks.
Empty or unavailable fields are null; dates are ISO YYYY-MM-DD. Invalid
publication/information/transit dates are also null and do not change the
activity calculation, which uses only the original start/end bounds.
| Field | Type (nullable unless stated) | Source / meaning |
|---|---|---|
list | string, required | Official list name |
cnpj | string, required | Validated source CNPJ |
matchType | string, required | exact or sameRoot |
sanctionType | string | CEIS/CNEP CATEGORIA DA SANÇÃO; source category for CEPIM/leniency |
sanctioningBody | string | ÓRGÃO SANCIONADOR; CEPIM ÓRGÃO CONCEDENTE |
sanctionScope | string | CEIS/CNEP ABRAGÊNCIA DA SANÇÃO (published spelling); ABRANGÊNCIA is also supported |
startDate, endDate | date string | Sanction dates or leniency agreement start/end |
dateUnknown | boolean, required | A nonempty start/end bound could not be parsed |
active | boolean, required | Activity on the screening date, using start/end bounds |
legalBasis | string | FUNDAMENTAÇÃO LEGAL, CEPIM reason, or leniency terms |
registry | string | CEIS/CNEP CADASTRO |
sanctionId | string | CEIS/CNEP CÓDIGO DA SANÇÃO |
personType | string | CEIS/CNEP TIPO DE PESSOA (company rows only) |
sanctionedName | string | CEIS/CNEP NOME DO SANCIONADO |
reportedName | string | CEIS/CNEP NOME INFORMADO PELO ÓRGÃO SANCIONADOR |
companyName | string | RAZÃO SOCIAL - CADASTRO RECEITA; CEPIM NOME ENTIDADE |
tradeName | string | NOME FANTASIA - CADASTRO RECEITA, including the leniency en-dash spelling |
sanctionedUf | string | Always null in the verified downloads: no company-state column is published |
sanctioningBodyUf | string | CEIS/CNEP UF ÓRGÃO SANCIONADOR; this is the authority's state |
sanctioningBodySphere | string | CEIS/CNEP ESFERA ÓRGÃO SANCIONADOR |
processNumber | string | CEIS/CNEP/leniency NÚMERO DO PROCESSO |
publicationDate | date string | CEIS/CNEP DATA PUBLICAÇÃO |
publicationSource | string | CEIS/CNEP PUBLICAÇÃO |
publicationDetails | string | CEIS/CNEP DETALHAMENTO DO MEIO DE PUBLICAÇÃO |
transitDate | date string | CEIS/CNEP DATA DO TRÂNSITO EM JULGADO |
fineValue | number | CNEP VALOR DA MULTA in BRL; decimal comma/grouping dots become a JSON number; invalid text becomes null |
informationDate | date string | CEIS/CNEP DATA ORIGEM INFORMAÇÃO; leniency DATA DA INFORMAÇÃO |
informationSource | string | CEIS/CNEP ORIGEM INFORMAÇÕES |
remarks | string | CEIS/CNEP OBSERVAÇÕES |
transferAgreementNumber | string | CEPIM NÚMERO CONVÊNIO |
impedimentReason | string | CEPIM MOTIVO DO IMPEDIMENTO; also in legalBasis |
agreementId | string | Leniency ID DO ACORDO |
agreementStatus | string | Leniency SITUAÇÃO DO ACORDO DE LENIÊNICA (published spelling) |
agreementTerms | string | Leniency TERMOS DO ACORDO; also in legalBasis |
agreementEffects | array | Leniency Efeitos.csv rows joined by agreement ID; each has nullable effect (EFEITO DO ACORDO DE LENIENCIA) and details (COMPLEMENTO) |
Identifiers and process/agreement numbers remain strings to preserve leading
zeros. There is no separate decision-date column in the checked files;
transitDate is the published final-decision date. Leniency's responsible body
is in sanctioningBody; its dates are startDate and endDate. An absent effect
file or an agreement without matching effects produces agreementEffects:null.
Other lists have agreementEffects:null as well.
At item level, companyName comes from the first exact record, or the first
record if there is no exact match. Within that selected record, the Actor uses
companyName, then sanctionedName, then reportedName. It returns null if
that record has no name or there are no records. Billing-status items retain
the delivered item's name. The Actor uses only the names already present in
CGU downloads; it makes no Receita or Portal API lookup.
For example, a synthetic CNEP match can contain this record (all values below are invented test data, not a real sanctions finding):
{"list": "CNEP","cnpj": "00000000000191","matchType": "exact","sanctionType": "Multa","sanctioningBody": "Example authority","sanctionScope": "Nacional","startDate": "2026-01-01","endDate": "2026-12-31","dateUnknown": false,"active": true,"legalBasis": "Synthetic legal basis","registry": "CNEP","sanctionId": "00012","personType": "J","sanctionedName": "Example company","reportedName": "Example company as reported","companyName": "Example company Ltda","tradeName": "Example trade name","sanctionedUf": null,"sanctioningBodyUf": "DF","sanctioningBodySphere": "Federal","processNumber": "001/2026","publicationDate": "2026-01-02","publicationSource": "DOU","publicationDetails": "Section 1","transitDate": "2026-01-03","fineValue": 1234567.89,"informationDate": "2026-10-22","informationSource": "CGU","remarks": "Synthetic observation","transferAgreementNumber": null,"impedimentReason": null,"agreementId": null,"agreementStatus": null,"agreementTerms": null,"agreementEffects": null}
The containing item's companyName would be "Example company Ltda" if this
were its first exact record. A leniency record can instead have
"agreementEffects":[{"effect":"Synthetic effect","details":null}].
sanctioned and activeSanction mean at least one active matching record.
Historical records remain visible with active:false. Activity is evaluated on
the run's UTC date, including the start/end dates themselves, even for cached
records. Missing bounds are open-ended; an invalid date sets dateUnknown:true
and conservatively keeps the record active. This date-based indicator includes
leniency and CEPIM occurrences and is not a legal enforceability decision.
A successful no-match result has all four dataset dates and error:null.
On source/cache failure the indicators are null (unknown), with an explicit
error and no screening fee. Never interpret an error as clearance.
Every output item includes partialData and warnings. If any used base has
discarded malformed rows without a recoverable CNPJ within the 1% tolerance,
partialData:true applies to every screening using that base, including matches
and no matches. warnings contains one readable notice per affected base:
{"code": "SOURCE_PARTIAL","source": "CEPIM","rejectedRows": 1,"message": "CEPIM: 1 malformed row(s) discarded; at least one has no recoverable CNPJ, so occurrences may be missing."}
rejectedRows counts all malformed rows discarded in that base, including
those with known CNPJs; it is not a count of unidentified rows or missing sanctions.
Clean bases produce partialData:false and warnings:[]. The flag uses the
snapshot actually screened, including daily cache and stale fallback; it does
not describe a failed refresh that was replaced by another snapshot. Status
items of type:"billingStatus" inherit these fields from the delivered screening.
Input/source errors and unprocessed items that use no bases have partialData:false
and warnings:[]; that flag alone does not establish a successful screening.
Always check error, partialData and stale alongside the sanction indicators.
Official sources and freshness
The following official pages and their dated download routes were checked on
2026-10-22. The Actor reads the page's embedded arquivos.push date metadata and
uses the latest published date, rather than guessing today's archive name.
| List | Official discovery page | Verified download route |
|---|---|---|
| CEIS | CEIS downloads | 20261022 |
| CNEP | CNEP downloads | 20261022 |
| CEPIM | CEPIM downloads | 20261021 |
| Leniency | Agreement downloads | 20261022 |
These routes redirected to
https://dadosabertos-download.cgu.gov.br/PortalDaTransparencia/saida/<slug>/<YYYYMMDD>_<name>.zip.
Names were CEIS, CNEP, CEPIM and AcordosLeniencia, respectively. Agreements
contain both an Acordos.csv and an auxiliary Efeitos.csv; effects are joined
to validated company agreements by ID. Windows-1252 and UTF-8 CSV files are supported.
Each base is normalized once when its published date changes and retained as
compressed JSON in the named key-value store br-cnpj-sanctions-cache-v3.
This store belongs to the user's Apify account: it is reused across that
account's sequential runs, not shared globally between customers. Version 3
uses new cache keys for enriched records, with a root index and row-quality
metadata; v1/v2 data is not reused because it lacks the complete fields.
The first run after this upgrade downloads all four bases again.
Subsequent sequential runs reuse snapshots during the UTC day.
The next day checks publication metadata and downloads a ZIP only if the source
date changed. There is no download per CNPJ. Dates describe the publisher's
snapshot, not the time of this run; weekends can legitimately retain older dates.
If refreshing a base fails, a validated prior snapshot can be used for at most
seven days after its datasetDate (and last successful check). The item exposes
stale:true, staleSources and the unchanged datasetDate for each list. Failed
refreshes never advance that date or the successful-check timestamp. An accepted
fallback screening uses the normal event price. Expired, corrupt,
future-dated or incompatible cache cannot authorize a result: return an error
without a fee if any source lacks an acceptable snapshot. Concurrent cold runs
may duplicate a refresh because the key-value store does not provide a distributed
lock; serialize scheduled runs when avoiding that duplication is essential.
Privacy, limits and errors
Only validated company identifiers enter the normalized cache. Individual rows
are excluded; company names and the documented fields are retained through an
explicit column allowlist. Raw rows and unrelated columns are not retained.
CPF patterns in all text fields are redacted. An invalid CPF-shaped input is returned as
cnpj: null, without echoing the supplied personal identifier. Raw downloads
remain in memory only. The dataset contains the requested company screening
results and follows your Apify storage retention settings.
Requests have a 15-second connection timeout, a 40-second idle-operation timeout,
and a 60-second global deadline covering redirects, streaming, all retries and
backoff. Loading all four bases has an additional 240-second global deadline.
If that deadline cancels refresh, a cache-only recovery validates all four
snapshots and returns them with stale metadata; no further HTTP is attempted.
Recovery reads the account's KVS after the refresh deadline. If any snapshot is
unusable, the result remains SOURCE_TIMEOUT and is not charged.
Up to three attempts use exponential backoff on transient failures. ZIPs are
limited to 32 MiB compressed and 160 MiB expanded; normalized cache is capped at
64 MiB per base. The Actor checks headers and rejects empty or changed schemas.
Malformed rows are discarded and counted; more than 1% rejects the entire base
with SOURCE_TOO_MANY_BAD_ROWS. sourceQuality reports total, rejected and
invalid-date row counts, unknownIdentityRows (whether any discarded row lacks
a recoverable CNPJ), and uncertainRootCount. A discarded row with a known
company root prevents screening that root (SOURCE_INCOMPLETE_ROWS). An
unidentified discarded row consumes the same 1% allowance and does not block
every company; it sets partialData:true and a SOURCE_PARTIAL warning for every
screening using the affected base. Tolerated rejects mean occurrences may be
missing, so sanctioned:false with partialData:true is a partial lookup and
does not establish absence of sanctions. These warnings do not change error
or the normal screening fee. If all rejected rows have recoverable CNPJs,
partialData remains false; known affected roots still return
SOURCE_INCOMPLETE_ROWS and are not charged. Above 1%, refresh fails and uses a
validated snapshot up to seven days old before returning an error. Cache encoding
above 64 MiB follows that same
fallback rule. Error items are not charged.
The internal uncertainRoots array remains in the account cache to identify
affected queries, but is omitted from dataset items: aggregate counts explain
source quality without repeating unrelated company identifiers in every result.
Invalid dates become null, are counted separately and preserve the record.
Common errors include
INVALID_CNPJ, SOURCE_UNAVAILABLE, SOURCE_SCHEMA_CHANGED, SOURCE_EMPTY and
SOURCE_TIMEOUT and CACHE_OR_SOURCE_UNAVAILABLE.
Permission to read/write the account's named cache is needed. The platform's
limited permissions mode was not tested by this enrichment change; see verification.md for that
launch prerequisite. A permissions failure returns an error without a fee.
Foreign entities without a valid Brazilian CNPJ cannot be matched.
The Actor definition defaults to 256 MiB, with a 256–512 MiB allocation range.
Configure a 300-second run timeout in Console when preparing the unpublished Actor.
Pricing and SDK integration
Proposed pricing is $0.002 per cnpj-checked event ($2 per 1,000 complete,
valid screenings). A completed no-match lookup is a delivered screening result.
Tolerated partial-data screenings use the same fee, including no-match results;
SOURCE_PARTIAL is a warning, not a billing error.
Invalid inputs, unavailable/empty sources and failed deliveries are not billed;
there is no startup event. The Actor checks the SDK's remaining event allowance
before loading data and before each valid screening, pushes the result, then
calls Actor.charge(event_name="cnpj-checked", count=1, idempotency_key=cnpj).
The normalized CNPJ prevents duplicate billing inside a run. On a charge failure,
the delivered result remains, followed by a type:"billingStatus" item with
the normalized cnpj, validCnpj:true,
CHARGE_FAILED_AFTER_DELIVERY and chargeConfirmed:false (confirmation was
unavailable; this does not assert a refund). Further valid CNPJs receive
NOT_PROCESSED_CHARGING_FAILURE errors. Spending limits similarly produce
NOT_PROCESSED_SPENDING_LIMIT items. Status/error items generate no events.
Consumers should branch on type:"billingStatus": it reports billing state
for the preceding screening and does not contain screening records.
Configure the event in Apify Console before enabling monetization;
the repository's pricing document is a proposal, not a publication action.
The current API was verified against the official
Actor.charge reference,
ChargingManager reference
and ChargeResult reference,
and exercised with pinned SDK 4.1.0. The code uses the result's
event_charge_limit_reached attribute and
calculate_max_event_charge_count_within_limit, which returns None when
unlimited. See .actor/pricing.md for current market comparisons
and cost assumptions.
Local development and verification
Create a Python 3.12 virtual environment and install requirements-dev.txt.
From the repository root, with that environment activated:
python -m pytest actors/br-cnpj-sanctions/tests -qpython actors/br-cnpj-sanctions/tests/smoke.py
Tests use local synthetic CSV fixtures and mocked HTTP; external socket connections
are blocked (Windows asyncio's internal loopback wake-up sockets are allowed).
The smoke script runs the real main() and SDK with default input and local
dataset/KVS storage, replacing only official HTTP responses with synthetic
fixtures. It prints a clearly labelled synthetic output item and incurs no charge.
Its ignored .local-smoke directory can be inspected after execution.
For a live local run, change into this Actor directory and run python -m src;
that command accesses official public downloads. No cloud deployment, publication,
real paid event, or Docker build is implied by local verification.