# LATAM Company Enrichment — CNPJ, RUT, NIT, RUC, CUIT Lookup (`latsouth/latam-company-enrichment`) Actor

Enrich lists of CNPJ, RUT, NIT, RUC, CUIT or company domains from the official registries of 7 LATAM countries: match status, legal name, status, industry, size, address, verified website, public contacts, gov-supplier flag. PT/ES: enriquecimento de empresas por CNPJ, RUT, RUC.

- **URL**: https://apify.com/latsouth/latam-company-enrichment.md
- **Developed by:** [LatSouth Data](https://apify.com/latsouth) (community)
- **Categories:** Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

## LATAM Company Enrichment: tax ID and domain lookup, 7 countries

**By [LatSouth](https://latsouth.com).** Paste a list of **CNPJ, RUT, NIT, RUC, CUIT, DENUE ids or company domains** and get
one row back per input: whether it matched, and the company's record from the **official registries of Brazil, Mexico,
Chile, Colombia, Peru, Argentina and Ecuador** — legal name, status, legal form, ISIC Rev.4 industry in English, size,
region, city, address, registration date, HTTP-verified website, **public company contacts** (BR, MX, CO) and
**government-supplier flags** (BR, CO). Up to 10,000 inputs per run.

Company data only: no owners, partners, personal mailboxes or personal phones; e-mail inputs are echoed with the local
part masked.

| | |
|---|---|
| Registries | 19.7M companies: BR 10.93M (CNPJ establishments) · CL 3.39M · CO 1.82M · AR 1.27M · PE 917k · MX 847k · EC 569k |
| Data as of | per country, 2026-05-20 to 2026-10-10; contacts fetched 2026-10-22/23; government contracts to 2026-10-23 |
| Price | **US$0.01 per matched input** (`enriched-match`) · **US$0.001 per input not matched** (`no-match`) |
| Typical run | prefilled 3 lines 14 s · 62 mixed tax IDs and domains 32 s · 3,000 tax IDs in 7 countries 71 s (about 4 min for the 10,000 maximum) |

### Use cases

- **CRM enrichment**: you have tax IDs (or website domains) in Salesforce/HubSpot and want legal name, status, industry,
  size and location in English, in one consistent schema across seven countries.
- **KYB pre-check**: is this CNPJ/RUT/NIT/RUC/CUIT valid (check digit), registered, active, private or public, a
  sole-owner entity? Does it win government contracts?
- **Lead list cleanup**: drop inactive, public-sector and sole-owner rows, normalize tax IDs, attach ISIC, find the
  company behind a domain and add its public role e-mail and phone.

### Input

The Console form is prefilled with three lines (Petrobras by CNPJ, Ecopetrol by NIT, Pipefy by domain).

**Mixed list, auto-detected**

```json
{
  "identifiers": ["33.000.167/0001-01", "CO:899999068-1", "pipefy.com", "77.552.777-3", "20100047218",
                  "30-70917199-9", "1790016919001"]
}
```

**One country, ids without punctuation**

```json
{
  "identifiers": ["900272469", "860002964", "890903938"],
  "default_country": "CO"
}
```

**API: your own reference, tax ID with domain fallback, no gov flags**

```json
{
  "records": [
    {"tax_id": "11.222.333/0001-81", "domain": "acme.com.br", "ref": "crm-001"},
    {"domain": "https://www.empresa.mx", "ref": "crm-002"}
  ],
  "include_gov_flags": false
}
```

| Field | What it does |
|---|---|
| `identifiers` | One per line (max 10,000): tax IDs in any punctuation, `CC:` prefix optional (`CO:900593229`), or a domain / URL / e-mail |
| `default_country` | Country for unprefixed ids; `AUTO` (default) tries every country whose format fits |
| `records` | API objects `{tax_id, country, domain, ref}`; `ref` is echoed as `input_ref`; the domain is the fallback when the tax ID is not found |
| `include_contacts` | Public company contacts for BR/MX/CO (default **true**) |
| `include_gov_flags` | Government-supplier flags for BR/CO (default **true**) |

#### Accepted identifiers

| Country | Identifier | Formats | Check digit |
|---|---|---|---|
| Brazil | CNPJ (establishment), or the 8-digit root → head office | `12.345.678/0001-95`, `12345678000195`, `12.345.678`, alphanumeric CNPJ | modulo 11 (Receita, incl. 2026 alphanumeric rule) |
| Mexico | DENUE establishment id | `6190221` | none — **the RFC is not published by INEGI** (`unsupported_id`); use the domain |
| Chile | RUT | `77.552.777-3`, `77552777-3`, `775527773`, DV `K` | modulo 11 |
| Colombia | NIT | `900.593.229-1`, `900593229` (with or without DV) | DIAN weights |
| Peru | RUC 20 | `20100047218` | modulo 11 |
| Argentina | CUIT | `30-70917199-9`, `30709171999` | modulo 11 |
| Ecuador | RUC (sociedad) | `1790016919001` | modulo 11 (reported only: ~21% of SRI company RUCs fail it) |
| all | domain | `acme.com.br`, `https://www.acme.mx/x`, `ventas@acme.co`, subdomains | free-mail, ISP, social and placeholder domains are rejected |

Without a country, an id is looked up in every country whose format fits; when it exists in two (e.g. an 8-digit number
that is a Colombian NIT and a Mexican DENUE id) the row is `ambiguous` with `candidate_tax_ids` — add the prefix.

### Output (one row per input, in input order)

| Group | Fields |
|---|---|
| Match | `input`, `input_ref`, `input_type` (tax_id / domain), `match_status` (`matched`, `ambiguous`, `not_found`, `invalid_input`, `unsupported_id`), `match_method` (`tax_id`, `cnpj_root`, `domain`, `parent_domain`), `match_note`, `normalized_id`, `id_check_digit_valid`, `candidate_tax_ids` |
| Company | `country`, `tax_id`, `tax_id_type`, `tax_id_formatted`, `legal_name`, `trade_name`, `legal_form`, `legal_form_normalized`, `is_sole_owner_entity`, `is_headquarters`, `is_active`, `status`, `sector`, local activity code + labels, `isic_section` / `isic_division` / `isic_class` (+ English labels), `size_class`, employees, `region`, `region_name`, `region_iso`, `city`, `address`, `zip`, `email_domain`, `website`, `website_verified`, `website_guess`, `registration_date`, `data_as_of`, `source`, `source_license` |
| Public contacts (BR, MX, CO) | `public_role_emails`, `public_phones`, `linkedin_url`, `instagram_url`, `facebook_url`, `has_public_contact`, `contact_source_url`, `contact_fetched_at` |
| Government supplier (BR, CO) | `is_gov_supplier`, `gov_contracts_count`, `gov_contracts_last_12m`, `gov_total_value_usd`, `gov_last_award_date`, `gov_top_category_en`, `gov_source` |
| Foreign trade (PE) / parish (EC) | `is_importer`, `is_exporter` (SUNAT Padrón RUC flags), `parish` (SRI parroquia of the head office) |

Fields that a country does not publish are `null` (contacts and gov flags are `null` outside their countries, `false`
when the country has data but the company has none). The run's `OUTPUT` record has status counts, matches per country,
timings and the dataset releases used.

#### How matching works

- **Tax IDs** are normalized (punctuation, spreadsheet-dropped leading zeros, Colombian DV stripped), validated, and looked
  up only in the countries they can belong to (one partition per country).
- **Domains** match a company when its registry website, HTTP-verified website or registered corporate e-mail uses that
  domain (exact first, then the parent domain). Brazil groups establishments by CNPJ root (the head office is returned)
  and Mexico by legal name; when several companies use the domain, the one whose own HTTP-verified website it is wins;
  otherwise (groups, agencies, accountants' domains) the row is `ambiguous` and lists up to 10 candidates. Domains are searchable for **Brazil (1.49M establishments / 756k domains), Mexico (359k /
  139k) and Colombia (22k / 18k)**; Chile, Peru, Argentina and Ecuador publish no website or e-mail, so look those up by
  tax ID. Large companies often register an accountant's e-mail: domain matching finds them only when their own domain
  is on the registry.
- **Public contacts** come from the company's own homepage and ship only when the domain belongs to that single company
  (not shared, not an accountant's), e-mails are role mailboxes on that domain, and phones are in the country's numbering
  plan. Coverage: BR 167,866 establishments, MX 78,920, CO 7,517.
- **Government suppliers**: 369,754 suppliers with contracts (Brazil PNCP 2025-01 to 2026-10: 268,216; Colombia SECOP II:
  101,538), matched on the exact tax ID.

### Pricing

Pay per event, charged per output row:

| Event | When | Price |
|---|---|---|
| `enriched-match` | the input matched exactly one company | **US$0.01** |
| `no-match` | not found, ambiguous, invalid or unsupported | **US$0.001** |

1,000 inputs with a 70% match rate cost US$7.30. Duplicate inputs are returned once. Set a maximum cost per run and the
actor stops when it is reached (`OUTPUT.stopped_by_budget`).

### Sources, licences and attribution

Every matched row carries its registry's credit in `source` and `source_license`; keep them when you publish the data:
Receita Federal do Brasil — Dados Abertos CNPJ · INEGI, DENUE 05/2026 (Términos de Libre Uso) · Chile RES (CC BY) + SII
nómina · Confecámaras RUES + Superintendencia de Sociedades (**CC BY-SA 4.0**: Colombian rows and derived works must be
shared alike) · SUNAT Padrón RUC (ODC-BY 1.0) · Registro Nacional de Sociedades (CC BY 4.0) · SRI Catastro RUC (CC BY 4.0).
Government contracts: PNCP (Lei 14.133/2021, "Fonte: PNCP") and SECOP II, Agencia Nacional de Contratación Pública -
Colombia Compra Eficiente (datos.gov.co `jbjy-vk9h`, CC BY-SA 4.0); the credit is in `gov_source`.
Public contacts: LatSouth, from each company's public homepage. Full texts per country: see the
[LATAM Company Finder](https://apify.com/latsouth/latam-company-finder) README.

### Limitations

- **Mexico has no RFC** in INEGI's open data: enrich Mexican companies by DENUE id or domain.
- Natural persons, MEI / individual entrepreneurs (BR), personas físicas (MX), RUC 10 (PE) and closed CNPJs are not in
  the registries we publish, so they come back `not_found` (by design).
- Brazil's `website_verified` is an HTTP check (2xx/3xx, not parked); other countries have no verified websites.
- Argentina has no company status (`is_active` is null; see `status`); Peru has no registration date; Ecuador has no
  street address.

### Related

[LATAM Company Finder](https://apify.com/latsouth/latam-company-finder) (search by segment) · country finders for
[Brazil](https://apify.com/latsouth/brazil-company-finder), [Mexico](https://apify.com/latsouth/mexico-company-finder),
[Chile](https://apify.com/latsouth/chile-company-finder), [Colombia](https://apify.com/latsouth/colombia-company-finder),
[Peru](https://apify.com/latsouth/peru-company-finder), [Argentina](https://apify.com/latsouth/argentina-company-finder),
[Ecuador](https://apify.com/latsouth/ecuador-company-finder) · [LATAM Government Contracts](https://apify.com/latsouth/latam-gov-contracts)
· data files: <https://latsouth.com/products/>

### Privacy

Company data only, from official open registries and company homepages. You are responsible for lawful use (LGPD,
LFPDPPP, Ley 19.628, Ley 1581, Ley 29733, Ley 25.326, LOPDP) and for honouring opt-out requests (hello@latsouth.com).

# Actor input Schema

## `identifiers` (type: `array`):

One per line, up to 10,000: CNPJ (12.345.678/0001-95 or the 8-digit root), DENUE id (Mexico), RUT (77.552.777-3), NIT (900.593.229-1, with or without the check digit), RUC (Peru 20..., Ecuador 13 digits), CUIT (30-70917199-9), or a domain / website / e-mail (acme.com.br, https://www.acme.mx, ventas@acme.co). Punctuation is ignored. Prefix a country to remove ambiguity: CO:900593229.

## `default_country` (type: `string`):

Country of identifiers that carry no prefix. Auto-detect looks the identifier up in every country whose format fits and reports `ambiguous` if it exists in more than one.

## `records` (type: `array`):

Optional, for API use: \[{"tax_id": "900593229", "country": "CO", "domain": "acme.co", "ref": "crm-123"}]. `ref` is echoed as `input_ref`. When both a tax ID and a domain are given, the tax ID is tried first and the domain is the fallback.

## `include_contacts` (type: `boolean`):

Role e-mails (contato@, ventas@...), company phones and social profiles published on the company's own website. Only when the domain belongs to that single company; never personal mailboxes.

## `include_gov_flags` (type: `boolean`):

Public contracts won (Brazil PNCP 2025-2026, Colombia SECOP II): count, last 12 months, total in USD, last award date, top category.

## Actor input object example

```json
{
  "identifiers": [
    "33.000.167/0001-01",
    "CO:899999068-1",
    "pipefy.com"
  ],
  "default_country": "AUTO",
  "include_contacts": true,
  "include_gov_flags": true
}
```

# Actor output Schema

## `rows` (type: `string`):

One item per input, in input order. Download as JSON, CSV, Excel or XML via the dataset API.

## `summary` (type: `string`):

Inputs, status counts, matches per country, rows with contacts / gov flags, timings, datasets used and whether the run stopped at the buyer's budget cap.

# 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 = {
    "identifiers": [
        "33.000.167/0001-01",
        "CO:899999068-1",
        "pipefy.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("latsouth/latam-company-enrichment").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 = { "identifiers": [
        "33.000.167/0001-01",
        "CO:899999068-1",
        "pipefy.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("latsouth/latam-company-enrichment").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 '{
  "identifiers": [
    "33.000.167/0001-01",
    "CO:899999068-1",
    "pipefy.com"
  ]
}' |
apify call latsouth/latam-company-enrichment --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,latsouth/latam-company-enrichment"
        }
    }
}
```

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/9qWcrO2c5tepGTAIE/builds/zu1Z9GdXH9JUqil0Y/openapi.json
