# GLEIF LEI Company Registry Scraper - Decoded Firmographics (`webdata_labs/gleif-lei-company-registry-scraper`) Actor

\[$1.50 / 1K] Search 3.4M+ legal entities in the official GLEIF LEI register. One flat row per company: legal form, registry, region and LOU decoded from GLEIF's raw codes, one canonical address, national registration number, optional parents.

- **URL**: https://apify.com/webdata\_labs/gleif-lei-company-registry-scraper.md
- **Developed by:** [WebData Labs](https://apify.com/webdata_labs) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.90 / 1,000 entity rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## GLEIF LEI Company Registry Scraper

**Search the official global LEI register (3.4M+ legal entities) and get back flat, readable company rows - not GLEIF's raw code soup.**

The GLEIF LEI register is the authoritative, regulator-backed record of who a company legally is: its legal name, its legal form, the national registry it is filed with, its registration number, its address, and its corporate parents. It is free and open. It is also close to unusable straight out of the API: the legal form comes back as `JC0Y`, the registry as `RA000181`, the region as `EE-37`, and the LEI issuer as another 20-character LEI. The address is scattered across six fields and duplicated between the legal and headquarters sites. This Actor does the decoding and flattening so you get one clean row per company instead of a nested JSON:API document you have to reverse-engineer.

### ✅ What you get / ❌ what this isn't

| ✅ What you get | ❌ What this isn't |
|---|---|
| `legalForm` reading **"Osaühing"**, `registrationAuthority` reading **"Commercial Register"** | Not a passthrough that hands you `JC0Y` and `RA000181` and lets you look them up yourself |
| One canonical `address` string plus split `city` / `postalCode` / `region` / `country` | Not six raw address fragments duplicated across two address blocks |
| Full result sets past **10,000 rows** via cursor pagination | Not a page-number implementation that silently stops at 10,000 and looks complete |
| `parentLei` and `ultimateParentLei` resolved on request | Not an ownership graph crawler - direct and ultimate parents only, children are unbounded |
| `registeredAs`, the **national registry number**, to join against local company registers | Not a source of financials, filings, employees, or contact details - GLEIF does not carry them |
| Live API reads, current as of the day you run it | Not a stale quarterly dump |

### 🔎 Why use this Actor

- **Codes resolved, not passed through.** 3,599 legal forms, 1,071 registration authorities, 5,046 regions and all 41 LEI issuers are bundled and applied to every row, so `legalForm` and `registrationAuthority` arrive as words.
- **Past the 10,000-result ceiling.** GLEIF's page-based pagination hard-fails above 10,000 results, which silently truncates any country-sized query. This Actor uses cursor pagination and returns the whole slice.
- **Four search modes.** Full-text by name, everything in a country, a specific list of LEI codes, or new registrations in a date range sorted newest first.
- **Sentinel legal forms handled.** GLEIF uses code `8888` to mean "the real legal form is in a free-text field" and `9999` for "not applicable". Both are unwrapped instead of coming back blank.
- **National registry number exposed.** `registeredAs` is the company's number in its home register, which is the join key back to Companies House, Handelsregister, JUCESP and the rest.
- **Corporate parents on demand.** `includeHierarchy` adds direct and ultimate parent LEI and name, off by default because it costs two extra requests per row.

### 👥 Who it's for

Compliance, KYC and onboarding teams who need an authoritative legal-entity record, and data and lead-generation teams building a company master list.

- Resolve a counterparty name to a verified legal entity, jurisdiction and registry number.
- Build a country-wide list of active registered entities as a firmographic base layer.
- Screen a list of LEI codes you already hold and refresh their status and addresses.
- Track newly registered entities in a market week by week.
- Map a corporate group by resolving direct and ultimate parents.

### Example tasks

Ready-made configurations you can open, inspect and duplicate:

- [Look up a company in the GLEIF LEI register by name](https://apify.com/webdata_labs/gleif-lei-company-registry-scraper/examples/gleif-lei-lookup-by-company-name) - the general-purpose name search.
- [Bulk look up LEI codes for KYC](https://apify.com/webdata_labs/gleif-lei-company-registry-scraper/examples/lei-code-bulk-lookup-for-kyc) - paste a list of LEI codes and get a verified entity record for each.
- [Monitor new LEI registrations this month](https://apify.com/webdata_labs/gleif-lei-company-registry-scraper/examples/new-lei-registrations-this-month) - newest first, built to be scheduled.
- [Scrape German companies from the LEI register](https://apify.com/webdata_labs/gleif-lei-company-registry-scraper/examples/german-companies-lei-register) - active German entities with Handelsregister numbers.
- [Scrape UK companies from the LEI register](https://apify.com/webdata_labs/gleif-lei-company-registry-scraper/examples/uk-companies-lei-register) - active UK entities with Companies House numbers.
- [Export active legal entities for any country](https://apify.com/webdata_labs/gleif-lei-company-registry-scraper/examples/active-legal-entities-by-country) - change one country code to retarget.
- [Find corporate parents and ultimate owners by LEI](https://apify.com/webdata_labs/gleif-lei-company-registry-scraper/examples/corporate-parent-ownership-lookup) - direct and ultimate parents resolved.

### ⚙️ How to look up companies in the LEI register

1. Open the Actor and pick a **Search mode**.
2. For a name search, leave the mode on `fulltext` and type a company name into **Search query**.
3. For a whole country, switch to `country` and add one or more two-letter codes such as `DE` to **Countries**.
4. Set **Entity status** to `Active only` if you want to exclude dissolved and merged companies.
5. Set **Maximum results** to the number of rows you actually want to pay for.
6. Click **Start**. Results stream into the dataset as they are fetched, so you can watch and export mid-run from the **Output** tab or **Storage**.

#### Track new registrations on a schedule

Switch **Search mode** to `newRegistrations`, set **Registered since** to your start date, and optionally narrow to one country. The [new registrations task](https://apify.com/webdata_labs/gleif-lei-company-registry-scraper/examples/new-lei-registrations-this-month) is already set up this way. Results come back newest first. Save this as a Task and schedule it, and each run writes a watermark to a named key-value store so you can see exactly what the previous run covered.

### 📥 Input

```json
{
  "searchMode": "country",
  "countries": ["DE"],
  "entityStatus": "ACTIVE",
  "registrationStatus": "ISSUED",
  "includeHierarchy": false,
  "maxResults": 1000
}
```

- `searchMode` - `fulltext`, `country`, `leiList` or `newRegistrations`. Defaults to `fulltext`.
- `query` - company name or keyword, used in `fulltext` mode. Matches legal names, other names and identifiers.
- `countries` - two-letter ISO 3166-1 codes of the legal address, used in `country` mode. Each country is fetched as its own slice. Optional in `newRegistrations` mode to narrow to one market.
- `leis` - exact 20-character LEI codes, used in `leiList` mode.
- `registeredSince` / `registeredUntil` - ISO dates bounding the initial-registration range in `newRegistrations` mode. `registeredUntil` defaults to today.
- `entityStatus` - `ANY`, `ACTIVE`, `INACTIVE` or `NULL`. The entity's own status.
- `registrationStatus` - status of the LEI record itself. `ISSUED` means a currently valid, maintained LEI.
- `cities` / `postalCodes` - *advanced, client-side.* GLEIF cannot filter on these server-side, so they are applied after fetching and do not reduce how many records are read. Pair them with `countries` to keep runs small.
- `includeHierarchy` - *optional.* Adds direct and ultimate parent LEI and name. Costs two extra requests per row.
- `includeRaw` - *optional.* Attaches the untouched GLEIF record under `raw`.
- `maxResults` - hard cap on rows delivered. Default 1000, maximum 100000.

### 📤 Output

| lei | legalName | legalForm | registeredAs | registrationAuthority | city | country | registrationStatus |
|---|---|---|---|---|---|---|---|
| 529900VGZ27M5ZHAEZ97 | Siemens Advanta Solutions GmbH | Gesellschaft mit beschränkter Haftung | HRB 269164 | Commercial Register | München | Germany | ISSUED |
| 2138003XX6CNEIKKEJ64 | ADT SECURITY SERVICES DO BRASIL LTDA. | Sociedade Limitada | 04.125.866/0001-80 | JUCESP Board of Trade of State of Sao Paulo | LAPA DE BAIXO | Brazil | ISSUED |
| 9845008O6CAU77451110 | Brandhouse Baltic OÜ | Osaühing | 11431008 | Commercial Register | Tallinn | Estonia | ISSUED |

Each row also carries `entityStatus` and a boolean `isActive`; `entityCategory` and `entitySubCategory`; the raw `legalFormCode` and `registrationAuthorityCode` alongside their resolved labels, plus the authority's `registrationAuthorityOrg` and `registrationAuthorityWebsite`; `jurisdiction` and `jurisdictionName`; the split address as `street`, `city`, `postalCode`, `region`, `regionCode`, `country`, `countryCode` and a joined `address`; the headquarters site as `headquartersAddress`, `headquartersCity`, `headquartersCountryCode` and a `headquartersSameAsLegal` flag; the LEI lifecycle as `initialRegistrationDate`, `lastUpdateDate`, `nextRenewalDate`, `corroborationLevel`, `managingLouLei` and the resolved `managingLou`; cross-identifiers `bic`, `mic`, `ocid` and `spglobalIds`; succession fields `expirationDate`, `expirationReason`, `successorLei` and `successorName`; a `gleifUrl` deep link to the public record; and `scrapedAt`. With `includeHierarchy` on, rows gain `parentLei`, `parentName`, `ultimateParentLei` and `ultimateParentName`.

### 💵 How much does it cost?

`[💵 $1.50 / 1K]` and no start fee, so you pay per entity row delivered and nothing for starting a run. Client-side `cities` and `postalCodes` filtering happens before billing, so you are charged for rows you keep, not rows read. A 1,000-row country slice costs $1.50; looking up 20 specific LEI codes costs three cents. Set `maxResults` deliberately: the register holds over 3.4 million entities and an uncapped country query will happily return a quarter of a million rows.

### 🔁 Run it on the Apify platform

Schedule any input as a recurring Task, call the Actor from the API or any Apify client, and export results as JSON, CSV, Excel or XML. Results stream to the dataset during the run, so webhooks and integrations to Make, Zapier, Google Sheets or your CRM can pick rows up as they land rather than waiting for the run to finish.

### ⚠️ Limits and caveats

- **City, postal code, region and legal form cannot be filtered server-side.** GLEIF rejects those filters outright. `cities` and `postalCodes` are applied client-side after fetching, so they narrow your output but not your run time. Filtering a large country by one city still reads the whole country slice.
- **The register covers legal entities that have an LEI, not all companies.** An LEI is required mainly for entities that trade in financial markets, so small local businesses are usually absent. This is not a general company database.
- **No financials, filings, employees, phone numbers or emails.** GLEIF does not publish them, and this Actor does not invent them.
- **Only direct and ultimate parents.** Children are not fetched: an entity can have an unbounded number, which would make run time unpredictable. Parent resolution costs two extra requests per row.
- **`/lei-records/{lei}/lei-issuer` returns HTTP 500 upstream** and is deliberately not called. The managing LOU is resolved from a bundled map instead.
- **Reference code lists are bundled at build time.** New legal-form or registration-authority codes issued after the last build will come through as a raw code with an empty label until the Actor is rebuilt.
- **Throughput is the source's, not ours.** GLEIF serves roughly 125-145 records per second, so a 100,000-row run takes about 12 minutes and the full register would take hours.
- **`registeredAs` is not normalized.** Registries format their numbers differently (`HRB 269164`, `04.125.866/0001-80`), and the value is passed through exactly as filed.

### 🧩 Related Actors

- **Brazil CNPJ Company API** - take `registeredAs` from a Brazilian row and pull full Receita Federal firmographics for it.
- **Sanctions Screening API** - screen the legal names and countries this Actor returns against sanctions and watchlists.
- **SEC Financials API** - add filings and financials for US entities you have identified here.
- **EU Tenders API** - match awarded suppliers back to a verified legal entity and jurisdiction.
- **Website Contact Extractor** - once you have a company list, find the contact details GLEIF does not carry.
- **Lead List Deduplicator** - merge LEI output with other lead sources without duplicate companies.

### ❓ FAQ

**Am I charged for rows filtered out by `cities` or `postalCodes`?**
No. Client-side filtering runs before rows are pushed, so you are billed only for delivered rows.

**Why did my country query return fewer rows than the count in the log?**
The log prints how many entities GLEIF matched. Delivery stops at your `maxResults` cap, so raise the cap to get more.

**Does this get past GLEIF's 10,000-result limit?**
Yes. GLEIF's page-based pagination fails above 10,000 results; this Actor uses cursor pagination and has been verified returning 12,000 unique rows in a single German country slice.

**Which countries are covered?**
All of them. The register is global, with 250 country codes and 5,046 regions resolved. Coverage per country varies with how many local entities hold an LEI.

**Can I get company owners or subsidiaries?**
You can get direct and ultimate parents with `includeHierarchy`. Subsidiary lists are not returned.

**Is the data live?**
Yes, every run reads the GLEIF API directly. GLEIF publishes a daily golden copy, so records are current to the most recent publication.

### 🛠️ Support

Something wrong or missing? Open an issue on the Actor's Issues tab with the run URL, the input you used, and what you expected instead. That is the fastest way to get it fixed.

### ⭐ Rate this Actor

If this saved you a decoding job, please leave a rating on the **Reviews** tab. Review count is the main trust signal buyers use on the Store, and reviews decide what gets built and improved next. If something is broken, please open an issue first so it can be fixed before you rate.

# Actor input Schema

## `searchMode` (type: `string`):

How to select entities. 'fulltext' searches names and identifiers; 'country' pulls every LEI registered in a country; 'leiList' looks up specific LEI codes; 'newRegistrations' returns LEIs first registered in a date range, newest first.

## `query` (type: `string`):

Company name or keyword, used when Search mode is 'fulltext'. Matches legal names, other names and identifiers. Example: siemens

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

Two-letter country codes of the legal address, used when Search mode is 'country'. Each country is fetched as its own slice. Optional in 'newRegistrations' mode to narrow to one country. Example: DE

## `leis` (type: `array`):

Exact 20-character LEI codes to look up, used when Search mode is 'leiList'. Example: 529900T8BM49AURSDO55

## `registeredSince` (type: `string`):

Start of the initial-registration date range, used when Search mode is 'newRegistrations'. Example: 2026-08-01

## `registeredUntil` (type: `string`):

End of the initial-registration date range for 'newRegistrations'. Defaults to today when left empty.

## `entityStatus` (type: `string`):

Filter by the legal entity's own status. ACTIVE excludes dissolved and merged companies, which is what most lead and compliance use cases want.

## `registrationStatus` (type: `string`):

Filter by the status of the LEI record itself. ISSUED means a currently valid, maintained LEI.

## `cities` (type: `array`):

Keep only entities whose legal-address city matches. GLEIF does not support city filtering server-side, so this is applied after fetching and does not reduce the number of records read. Combine with Countries to keep runs small.

## `postalCodes` (type: `array`):

Keep only entities whose legal-address postal code matches. Like Cities, this is applied after fetching because GLEIF does not support it server-side.

## `includeHierarchy` (type: `boolean`):

Add direct and ultimate parent LEI and name to every row. Costs two extra requests per row, so a large run takes noticeably longer. Leave off unless you need ownership data.

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

Attach the untouched GLEIF JSON:API record to each row under 'raw'. Useful for debugging or for fields this Actor does not flatten.

## `maxResults` (type: `integer`):

Hard cap on rows delivered. The full register holds over 3.4 million entities, so always set a cap you actually want to pay for.

## Actor input object example

```json
{
  "searchMode": "fulltext",
  "query": "siemens",
  "entityStatus": "ANY",
  "registrationStatus": "ANY",
  "includeHierarchy": false,
  "includeRaw": false,
  "maxResults": 50
}
```

# Actor output Schema

## `entities` (type: `string`):

One normalized row per legal entity, with GLEIF's legal-form, registry, region and LOU codes resolved to human labels.

## `ownership` (type: `string`):

Direct and ultimate corporate parents. Populated only when 'Resolve corporate parents' is enabled.

## `OUTPUT` (type: `string`):

Counts, applied filters and elapsed time for this run.

# 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 = {
    "searchMode": "fulltext",
    "query": "siemens",
    "maxResults": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("webdata_labs/gleif-lei-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 = {
    "searchMode": "fulltext",
    "query": "siemens",
    "maxResults": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("webdata_labs/gleif-lei-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 '{
  "searchMode": "fulltext",
  "query": "siemens",
  "maxResults": 50
}' |
apify call webdata_labs/gleif-lei-company-registry-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,webdata_labs/gleif-lei-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/p2C9G0nMQaR6rigaz/builds/Y5ce47dEydAlNCW9o/openapi.json
