# Gleif Lei Scraper (`normdata/gleif-lei-scraper`) Actor

3.4 million companies worldwide from GLEIF's official Legal Entity Identifier registry - legal name, addresses, jurisdiction, registration number, and real ownership links. When a company shows no parent, this is the only scraper that tells you why instead of leaving it blank.

- **URL**: https://apify.com/normdata/gleif-lei-scraper.md
- **Developed by:** [Norm Data](https://apify.com/normdata) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

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?

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

![Norm Data](https://i.ibb.co/rGbhM5Y8/Chat-GPT-Image-Sep-8-2026-02-20-50-PM.png)

## 🏢 GLEIF LEI Scraper

Pull the global **Legal Entity Identifier (LEI)** registry straight from GLEIF's own official data, no login: 3.4 million real legal entities with legal name, addresses, jurisdiction, national registration number, registration status, and real ownership links, including the actual reason a parent relationship is absent, not just a blank field.

### 🎯 Who uses it?

#### 🛂 KYC/AML & compliance teams

Validate a counterparty's legal identity, jurisdiction, and registration status before onboarding.

#### 🗺️ Corporate ownership researchers

Trace a group's real subsidiary tree, or find a subsidiary's real ultimate parent, and know why when there isn't one.

#### ⚠️ Risk & credit monitors

Track LEIs that have lapsed as an early compliance signal.

#### 🗂️ Data & entity-resolution teams

Build a clean, joinable company master file keyed on real national registration numbers.

### ✨ What it does

Reads GLEIF's own official data directly, no key, no login.

- **Registry:** pull every real entity in one or more countries, or the whole registry, filtered by entity status and registration status, each country getting its own fair share of the row cap.
- **Search:** full-text search across real legal entity names.
- **Lookup:** enrich a list of known LEI codes with their full real record.
- **Subsidiaries:** given a LEI, the real companies it directly owns.
- **Parents:** given a LEI, its real direct and ultimate parent, and when there isn't one, the real documented reason (e.g. a public company with no single controlling owner).

Missing source values are returned as `null`, never invented.

### Why this scraper

- **No practical result ceiling.** Pull an entire country, however large, in one clean run, with no gaps and no manual splitting into smaller requests.
- **The real reason a parent is missing, not just a blank field.** When a company has no reported parent, this Actor tells you why, instead of leaving you to guess whether it's independent, undisclosed, or simply not checked.
- **Reliable under real load.** Built and tested for sustained, concurrent pulls with no slowdown.
- **Bidirectional ownership in one Actor.** Subsidiaries and parents are both first-class modes, not bolted onto a single generic mode.

### How it compares

Checked directly against the closest real competitor on Apify (their own declared input and output):

| Capability | This actor | Closest competitor |
|---|:--:|:--:|
| Practical result ceiling on a large country or query | **none hit in testing** | requires manually splitting large requests |
| Real reason for a missing parent relationship | **yes** | not exposed |
| Registry / Search / Lookup / Subsidiaries / Parents modes | **all 5** | all 5 |
| Source | Official GLEIF data | Official GLEIF data |

### 📦 What data you get

| Entity | Useful fields |
| --- | --- |
| Identity | LEI, legal name, and record URL. |
| Classification | Entity category, entity status, legal form code, and jurisdiction. |
| Registration | Real national registration number and registration authority, a join key to local registries. |
| Addresses | Separate legal and headquarters addresses, plus whether they differ. |
| LEI health | Registration status, lapsed flag, and next renewal date. |
| Data quality | Managing LOU, validation sources, and conformity flag, GLEIF's own quality metadata. |
| Relationships | Related LEI and relationship type in Subsidiaries/Parents mode, plus the real reason a parent relationship is absent when one applies. |

### 💡 Use cases

#### 🇩🇪 Every active company in a country

```json
{ "mode": "registry", "countries": ["DE"], "entityStatus": "ACTIVE" }
```

#### 🔤 Search by company name

```json
{ "mode": "search", "searchQuery": "Tesla" }
```

#### 🆔 Look up known LEI codes

```json
{ "mode": "lookup", "leiCodes": ["HWUPKR0MPOU8FGXBT394"] }
```

#### 🌳 Real subsidiaries or parents of a company

```json
{ "mode": "subsidiaries", "relationshipLeiCodes": ["HWUPKR0MPOU8FGXBT394"] }
```

### ⚙️ How the input is organised

The input form is split into a top-level mode picker plus one section per mode:

| Section | What it's for |
| --- | --- |
| **Mode + row cap** | Pick Registry, Search, Lookup, Subsidiaries, or Parents, plus the row cap for the run. |
| **Registry mode** | Countries, entity status, and registration status. |
| **Search mode** | The company name to search. |
| **Lookup mode** | The exact LEI codes to enrich. |
| **Subsidiaries / Parents mode** | The LEI codes to look up real ownership links for. |

Only the fields for the mode you pick are used; the rest are ignored.

> **Apify Free plan:** every run is limited to a fixed 10-row sample. Upgrade your Apify plan to run your own settings.

### 🛡️ Limits & responsible use

This Actor reads only GLEIF's own publicly documented data. It never signs in and never accesses anything gated behind an account.

`reporting_exception_reason` surfaces the real reason GLEIF itself gives when an entity reports no parent: `NATURAL_PERSONS` means it's owned by individual people rather than a single corporate parent (common for public companies), and other real reasons include the parent being non-consolidating, legally restricted from disclosure, or genuinely unknown; it is never a guess. `bic` and `successor_lei` are usually null because GLEIF only sets them when they genuinely apply, most entities have no BIC code and have never merged into a successor.

Read live from GLEIF on every run. It is not cached.

Is this an official GLEIF tool? No. Independent, not affiliated with GLEIF. It reads only the publicly documented data.

### 📧 Contact

Need a scraper for a different site, or found something wrong with this one? norm.data.scrapers@gmail.com

### Local development

```bash
bun install
bun test                       # offline: normalization (real fixtures)
bun run src/main.ts             # reads storage/key_value_stores/default/INPUT.json
```

# Changelog

This Actor's version history is a separate document: https://apify.com/normdata/gleif-lei-scraper/changelog.md

# Actor input Schema

## `mode` (type: `string`):

Registry: bulk-pull entities filtered by country/status. Search: full-text company-name search. Lookup: enrich a list of known LEI codes. Subsidiaries/Parents: real ownership links for a list of LEI codes, including the real reason a parent is absent when there is one. Only the fields for the mode you pick are used - the rest are ignored.

## `maxItems` (type: `integer`):

Caps how many rows this run writes. Starts at 10 for a quick sample; raise it for a full run.

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

One or more real ISO 3166-1 alpha-2 country codes (e.g. "DE", "US", "GB"), each getting its own fair share of maxItems. Leave empty or use "ALL" for the full global registry with no country filter.

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

Optional. Leave empty for both.

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

Optional. Leave empty for all real registration statuses.

## `searchQuery` (type: `string`):

Full-text search across real legal entity names.

## `leiCodes` (type: `array`):

One or more real 20-character LEI codes to enrich.

## `relationshipLeiCodes` (type: `array`):

One or more real 20-character LEI codes to look up real ownership links for.

## Actor input object example

```json
{
  "mode": "registry",
  "maxItems": 10,
  "countries": [
    "DE"
  ]
}
```

# Actor output Schema

## `listings` (type: `string`):

Complete dataset with all scraped rows.

## `overview` (type: `string`):

Overview view with key fields displayed in a table.

# 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 = {
    "mode": "registry",
    "maxItems": 10,
    "countries": [
        "DE"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("normdata/gleif-lei-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 = {
    "mode": "registry",
    "maxItems": 10,
    "countries": ["DE"],
}

# Run the Actor and wait for it to finish
run = client.actor("normdata/gleif-lei-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 '{
  "mode": "registry",
  "maxItems": 10,
  "countries": [
    "DE"
  ]
}' |
apify call normdata/gleif-lei-scraper --silent --output-dataset

```

## MCP server setup

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