# LATAM Company Registry Scraper — Ecuador & Costa Rica Tax ID (`registralia/latam-company-registry-scraper`) Actor

One call for Latin American company data: paste mixed Ecuadorian RUCs and Costa Rican cedulas and get one normalized record per entity from the official SRI and Hacienda registries - status, activity, representatives, branches, and each authority's own fraud and tax-debt flags.

- **URL**: https://apify.com/registralia/latam-company-registry-scraper.md
- **Developed by:** [Nico Dennis Günther](https://apify.com/registralia) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $14.00 / 1,000 company record returneds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## LATAM Company Registry Scraper — Ecuador & Costa Rica Tax ID

Scrape **official Latin American company registries** and get one normalized record per entity — whatever country the tax ID came from. Paste a mixed list of Ecuadorian RUCs and Costa Rican cédulas; the Actor works out which registry each one belongs to and returns the same schema for both.

Currently covering **Ecuador** (SRI) and **Costa Rica** (Ministerio de Hacienda), with more of the region on the way.

### The part other sources don't give you

Latin American tax authorities publish their own fraud and delinquency designations. Those are the fields due diligence actually turns on, and they are collapsed here into one comparable set:

| Flag | Meaning | Published by |
|---|---|---|
| `ghostTaxpayer` | Officially designated shell company (*contribuyente fantasma*) | Ecuador |
| `nonExistentTransactions` | Invoices found to cover transactions that never happened | Ecuador |
| `taxDelinquent` | Owes taxes (*moroso*) | Costa Rica |
| `nonFiler` | Failed to file required returns (*omiso*) | Costa Rica |
| `suspended` | Registration suspended or struck off | both |

Every record carries `hasRiskFlag` and `riskFlagsRaised`, so a reviewer can sort a 5,000-row export by risk in one click instead of learning four registries' vocabularies.

A flag a country does not publish stays `null` — never `false`. Costa Rica does not designate ghost taxpayers, and reporting that as "no ghost flag" would be a false clean bill of health.

### Output

```json
{
  "country": "EC",
  "countryName": "Ecuador",
  "identifier": "1790016919001",
  "identifierType": "ruc_company",
  "legalName": "CORPORACION FAVORITA C.A.",
  "entityType": "company",
  "status": "active",
  "statusOriginal": "ACTIVO",
  "mainActivity": "VENTA AL POR MAYOR DE OTROS PRODUCTOS DIVERSOS PARA EL CONSUMIDOR.",
  "taxRegime": "GENERAL",
  "registeredSince": "1957-11-30",
  "registryUpdatedAt": "2026-08-18",
  "obligations": {
    "mustKeepAccounting": true,
    "isWithholdingAgent": true,
    "isSpecialTaxpayer": true
  },
  "riskFlags": {
    "ghostTaxpayer": false,
    "nonExistentTransactions": false,
    "taxDelinquent": null,
    "nonFiler": null,
    "suspended": false
  },
  "riskFlagsRaised": [],
  "hasRiskFlag": false,
  "representatives": [
    { "identification": "1701529958", "name": "WRIGHT DURAN BALLEN RONALD OWEN", "role": "legal_representative" }
  ],
  "headOfficeAddress": "PICHINCHA / RUMIÑAHUI / COTOGCHOA / AV. GENERAL ENRIQUEZ S/N",
  "establishmentCount": 327,
  "source": "SRI — Servicio de Rentas Internas del Ecuador",
  "sourceUrl": "https://srienlinea.sri.gob.ec/sri-en-linea/SriRucWeb/ConsultaRuc/Consultas/consultaRuc?ruc=1790016919001",
  "scrapedAt": "2026-08-27T15:04:11.000Z",
  "found": true
}
```

Costa Rican records use the same keys, filling `activities` with the authority's full primary/secondary activity list and `taxOffice` with the administering tax office.

### Coverage

| Country | Source | Returns |
|---|---|---|
| 🇪🇨 Ecuador | SRI — Servicio de Rentas Internas | Legal name, status, activity, regime, obligations, legal representatives with national ID, every branch with address, ghost-taxpayer flags |
| 🇨🇷 Costa Rica | Ministerio de Hacienda | Legal name, registration status, full activity list with codes, tax regime, administering office, delinquency and non-filer flags |

### Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `identifiers` | array | — | Mixed-country tax IDs. Formatting ignored. Prefix `EC:` or `CR:` to force a registry. A 10-digit Ecuadorian cédula is completed to a RUC. |
| `countries` | array | both | Restrict routing to selected registries. |
| `includeEstablishments` | boolean | `true` | Ecuador only: adds every branch with address. |
| `includeRaw` | boolean | `false` | Attaches the untouched registry payload for auditing. |
| `skipInvalidChecksum` | boolean | `false` | Off by default — registries hold historical records that predate today's rules. |
| `verifyNotFound` | boolean | `true` | Confirms a miss against a second endpoint so an outage is not reported as an unknown company. |
| `maxConcurrency` | integer | `5` | Capped at 10. Public services; stay polite. |
| `requestTimeoutSecs` | integer | `30` | |
| `maxRetries` | integer | `3` | Exponential backoff on 429 and 5xx. |
| `proxyConfiguration` | object | off | Only if a registry rate-limits the datacenter IP. |

Simplest run:

```json
{ "identifiers": ["1790016919001", "3101005212"] }
```

### Four ways to read the results

The dataset ships with prepared views, so nothing needs flattening by hand:

- **Companies** — one row per ID with the review columns.
- **Flagged only** — just the entities an authority warned about.
- **Legal representatives** — one row per person, ready for screening.
- **Branches** — one row per establishment.

Export as CSV, Excel, JSON or XML, or pull from the API.

### How country detection works

ID length decides the registry: 13 digits is an Ecuadorian RUC, 9 or 11–12 digits is Costa Rican, and a 10-digit ID goes to Costa Rica when it starts with 3 or 5 (cédula jurídica, NITE) and to Ecuador otherwise. The one genuinely ambiguous case — an Ecuadorian foreign-resident cédula starting with 30 — routes to Costa Rica, and any record resolved from an ambiguous shape carries a `routingNote` telling you so. Prefix the ID with `EC:` or `CR:` and the guesswork disappears.

### Output notes

- One dataset item per input ID, so a batch of 500 gives 500 rows you can join back on `identifier`.
- Failures are data, not silence: `found: false` plus an `error` of `not_found`, `invalid_identifier`, `unroutable_identifier` or `lookup_failed`.
- Dates are ISO. `registryUpdatedAt` shows how fresh the authority's own record is.
- Registry `SI`/`NO` values become real booleans; Spanish statuses map to `active` / `suspended` / `inactive` / `not_registered`, with the original in `statusOriginal`.

### Pricing

Pay per event, and you only pay for what the registry actually returned:

| Event | Price | When |
|---|---|---|
| Company record | **$0.014** | Once per tax ID found, including status, activity, legal representatives, risk flags and the head office address |
| Additional branch | **$0.0005** | Per registered branch beyond the head office, and only when you ask for establishments |
| Actor start | $0.0001 | Container startup. Not an access fee. |

**Not-found, invalid and unroutable IDs are free**, so a dirty input list costs you nothing extra. There is no minimum spend and no subscription.

A worked example: 500 Ecuadorian and Costa Rican companies, establishments switched off — 500 × $0.014 = **$7.00**. The same 500 with full branch data, averaging four branches each, adds 1,500 branch rows at $0.0005 = **$0.75**.

For comparison, the manual alternative is opening a Spanish-language government portal and transcribing fields, one company at a time — two to four minutes each. At 500 companies that is roughly a full working day.

### Notes on the sources

Both registries are read through endpoints their authorities serve publicly. This Actor does not authenticate, does not bypass access controls and does not solve captchas. Sole traders are natural persons, so treat their records as personal data under your own GDPR/LOPDP obligations.

Ecuador's tax-debt endpoint is deliberately not used: it sits behind a web application firewall, and working around that would not be appropriate.

**Not an official product of either authority.** This Actor is an independent tool built by Echocall LLC. It is not affiliated with, endorsed by, or operated by Ecuador's Servicio de Rentas Internas, Costa Rica's Ministerio de Hacienda, or any other government body. Authority names are used descriptively to identify the public data sources.

### Roadmap

Same schema, more registries — Panama, Guatemala, Paraguay, Uruguay, and Mexico's Registro Público de Comercio. Adding a country is one adapter module; the output contract does not change, so your integration keeps working.

### FAQ

**How do I look up Latin American companies in bulk?**

Paste a mixed list of tax IDs. The Actor routes each one to the right national registry, queries it, and returns one normalized row per ID — so a 500-line list of Ecuadorian and Costa Rican entities comes back as a single table you can join on `identifier`.

**Which countries are covered?**

Ecuador (SRI) and Costa Rica (Ministerio de Hacienda) today. Panama, Guatemala, Paraguay and Uruguay are next; adding a country is one adapter module and the output contract does not change, so your integration keeps working.

**Do I have to tell it which country an ID belongs to?**

No. ID length and prefix decide the registry. Prefix an ID with `EC:` or `CR:` if you want to force one, and any record resolved from a genuinely ambiguous shape carries a `routingNote` telling you so.

**What risk flags does it return?**

`ghostTaxpayer` and `nonExistentTransactions` from Ecuador, `taxDelinquent` (*moroso*) and `nonFiler` (*omiso*) from Costa Rica, plus `suspended` from both. Every record also carries `hasRiskFlag` and `riskFlagsRaised`, so a reviewer can sort a 5,000-row export by risk in one click.

**Why is a flag `null` rather than `false`?**

Because the country does not publish it. Costa Rica does not designate ghost taxpayers, and reporting that as "no ghost flag" would be a false clean bill of health.

**Is scraping these registries legal?**

Both registries are read through endpoints their authorities serve publicly. This Actor does not authenticate, does not bypass access controls and does not solve captchas. Sole traders are natural persons, so treat their records as personal data under your own GDPR/LOPDP obligations.

**What does it cost to try?**

Every new Apify account includes free monthly usage credit, which covers a few hundred lookups before you pay anything.

### Related Actors

Need one country only, with a country-specific schema? Use **Ecuador SRI RUC Scraper** or **Costa Rica Cedula Scraper**.

# Actor input Schema

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

Company or taxpayer IDs, mixed countries welcome. Ecuador: 13-digit RUC or 10-digit cédula. Costa Rica: cédula jurídica (10 digits), física (9) or DIMEX (11-12). Formatting is ignored, so 3-101-005212 works. Prefix with a country code — EC:1790016919001 — when you want to be explicit.

## `countries` (type: `array`):

Restrict routing to these registries. Leave both selected to let the Actor detect the country from the ID shape.

## `includeEstablishments` (type: `boolean`):

Ecuador only: adds every registered branch with its full address. Large retailers can have hundreds.

## `includeRaw` (type: `boolean`):

Attach the untouched Spanish-language response under a `raw` field, for auditing.

## `skipInvalidChecksum` (type: `boolean`):

Off by default: registries hold historical records that predate today's check-digit rules.

## `verifyNotFound` (type: `boolean`):

When an ID returns nothing, confirm against the registry's existence endpoint so a service hiccup is not reported as an unknown company. Misses are free, so this costs you nothing.

## `maxConcurrency` (type: `integer`):

How many IDs to query at once, across all registries. These are public government services — keep it low.

## `requestTimeoutSecs` (type: `integer`):

How long to wait for a registry to answer one request before giving up and retrying.

## `maxRetries` (type: `integer`):

Exponential backoff on rate limiting and server errors.

## `proxyConfiguration` (type: `object`):

Optional. Only needed if a registry starts rate-limiting the datacenter IP.

## Actor input object example

```json
{
  "identifiers": [
    "EC:1790016919001",
    "CR:3101005212",
    "0990004196001"
  ],
  "countries": [
    "EC",
    "CR"
  ],
  "includeEstablishments": true,
  "includeRaw": false,
  "skipInvalidChecksum": false,
  "verifyNotFound": true,
  "maxConcurrency": 5,
  "requestTimeoutSecs": 30,
  "maxRetries": 3,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `companies` (type: `string`):

One normalized record per tax ID: legal name, status, economic activity, legal representatives, the authorities own risk flags and branch addresses.

# 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": [
        "1790016919001",
        "3101005212"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("registralia/latam-company-registry-scraper").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": [
        "1790016919001",
        "3101005212",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("registralia/latam-company-registry-scraper").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": [
    "1790016919001",
    "3101005212"
  ]
}' |
apify call registralia/latam-company-registry-scraper --silent --output-dataset

```

## MCP server setup

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

```

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/DeIaoar5POnzkaYQr/builds/ZUykzGgiLcZn2OJYw/openapi.json
