# LEI Company Lookup (GLEIF) – Legal Entities, Parents & Groups (`shadow-tools/lei-company-lookup-gleif`) Actor

Search and look up companies in the GLEIF LEI register: legal name, legal form, address country and city, status, renewal dates, direct and ultimate parent, subsidiaries. Legal entities only (GDPR by design: sole proprietors removed). Unofficial, built on CC0 data.

- **URL**: https://apify.com/shadow-tools/lei-company-lookup-gleif.md
- **Developed by:** [Shadow Tools](https://apify.com/shadow-tools) (community)
- **Categories:** Lead generation, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 lei records

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

## LEI Company Lookup (GLEIF) – legal entities, parents and groups

Call this Actor to **find a company's LEI (Legal Entity Identifier) and its official register data**: legal name, legal form (with a readable label), registry number, legal and headquarters address (country, city, postcode), status, renewal dates, managing LEI issuer, and the **direct and ultimate parent** (or the reason none is reported). Use `search` when you only know a name, country or legal form, `lookup` when you already have LEIs, `subsidiaries` to list the entities of a group. Data comes from the public GLEIF API; it is **legal entities only** (see *Privacy / GDPR by design*).

> **Unofficial tool.** Not provided, supported or endorsed by GLEIF or any LEI issuer (LOU). It reads the public GLEIF data and adds filters, flat clean field names, legal-form labels, parent chains and agent-friendly notes.

#### Minimal input per mode

| Mode | Minimal input | What comes back |
|---|---|---|
| `search` | `{"legalName": "Airbus", "countries": ["FR"], "maxResults": 5}` | LEI records whose legal name starts with "Airbus", legal address in France |
| `lookup` | `{"mode": "lookup", "leis": ["529900RJ7K80E91EKN44"], "includeParents": true}` | one full record per LEI, with direct and ultimate parent |
| `subsidiaries` | `{"mode": "subsidiaries", "leis": ["529900S21EQ1BO4ESM68"], "maxResults": 10}` | entities that report this LEI as their direct parent (`"subsidiaryLevel": "ultimate"` = the whole group) |

Empty input `{}` returns the 20 most recently updated LEI records (non-empty, useful as a health check).

Short real output (lookup with `parentChain`, 5 Nov 2026; the full record has about 45 fields, every record also carries `attribution` and `extractedAt`):

```json
{
  "lei": "529900RJ7K80E91EKN44",
  "legalName": "TotalEnergies Aviation Suisse SA",
  "category": "GENERAL",
  "entityStatus": "ACTIVE",
  "legalFormCode": "MVII",
  "legalFormLabel": "Company limited by shares",
  "jurisdiction": "CH",
  "registrationNumber": "CHE-105.924.515",
  "legalAddressCountry": "CH",
  "legalAddressCity": "Genève",
  "legalAddressPostalCode": "1215",
  "registrationStatus": "ISSUED",
  "nextRenewalDate": "2027-08-25T10:39:13Z",
  "managingLou": "5299000J2N45DDNE4Y28",
  "parentsStatus": "ok",
  "directParentLei": "529900S21EQ1BO4ESM68",
  "directParentName": "TotalEnergies SE",
  "ultimateParentLei": "529900S21EQ1BO4ESM68",
  "ultimateParentName": "TotalEnergies SE",
  "parentChain": [{ "level": 1, "lei": "529900S21EQ1BO4ESM68", "legalName": "TotalEnergies SE", "country": "FR" }]
}
```

#### For AI agents (MCP)

- **One call = one answer.** Default `maxResults` is 20; keep it small and raise it only when the run SUMMARY says `capped: true`. Empty input is valid and returns data.
- **Pick the mode by what you have.** Name or country but no LEI: `search`. LEI known: `lookup` (batches of up to 2000 LEIs). Parent LEI known and you want its group: `subsidiaries`.
- **`legalName` matches the START of the name** (case-insensitive): "Total" finds "TotalEnergies SE" but not "Groupe Total". For words anywhere use `nameMatch: "fulltext"`, for typos `nameMatch: "fuzzy"`. A French SIREN or other registry number can be searched with `registrationNumber`, written as the registry shows it (for example `383 474 814`).
- **Speed and limits.** A search takes 1-5 s. Parents cost 1 to 2 extra GLEIF calls per record (`parentChain`: one per level); GLEIF allows 60 requests per minute, so with `includeParents` keep `maxResults` at 50 or less for a quick answer. The Actor throttles itself, retries on HTTP 429 and returns partial results (flagged) before the platform time limit.
- **Errors fail fast** in the form `Field X invalid: expected Y, got Z, example W` (for example `Field countries invalid: expected ISO 3166-1 alpha-2 country codes, got "FRA", example ["FR", "DE"].`). Fix that field and call again; nothing is charged.
- **0 results is not an error.** The run succeeds with an empty dataset and the key-value record `SUMMARY` has `note` saying why (no match, every match is a sole proprietor removed by design, unknown LEIs...) and how to widen the search. The same `note` explains truncated (`capped`), partial and cost-capped runs.
- `parentsStatus` is `ok`, `partial` (some parent data could not be fetched: run again) or `not-requested`. A record with no parent has `directParentException` / `ultimateParentException` set to GLEIF's reason (for example `NON_CONSOLIDATING`, `NATURAL_PERSONS`, `NO_KNOWN_PERSON`).

### Who uses it

- **KYB / onboarding and compliance teams**: confirm that a counterparty exists, is active, has a valid (non-lapsed) LEI, and see who is above it in the group.
- **Credit, risk and procurement analysts**: group structure from a subsidiary up to its ultimate parent, and from a parent down to its entities.
- **Sales and lead generation**: companies in a country with a given legal form, or LEIs due for renewal in the next weeks (`renewalFrom` / `renewalTo`) or newly registered (`registeredFrom`).
- **Data teams**: enrich a customer or supplier list with LEI, official legal name, legal form label, jurisdiction and registry number.
- **AI agents** that need a reliable identifier for a company mentioned in a document.

### What you get

One flat record per LEI. Main fields: `lei`, `legalName`, `category`, `subCategory`, `entityStatus`, `legalFormCode`, `legalFormLabel` (from the GLEIF ELF code list), `legalFormOther`, `jurisdiction`, `registrationAuthorityId`, `registrationNumber`, `legalAddress{Country,Region,City,PostalCode}`, `headquartersAddress{Country,Region,City,PostalCode}`, `entityCreationDate`, `entityExpirationDate`, `entityExpirationReason`, `successorLei`, `registrationStatus`, `initialRegistrationDate`, `lastUpdateDate`, `nextRenewalDate`, `managingLou`, `corroborationLevel`, `conformityFlag`, then `parentsStatus`, `directParent{Lei,Name,Country,Exception}`, `ultimateParent{Lei,Name,Country,Exception}`, `parentChain`, `parentsNote`, `childOfLei`, `childRelationship` (subsidiaries mode), `gleifUrl`, `attribution`, `extractedAt`.

No street address lines, alternative names, contacts or other free text are output: only the structured fields above.

### Quick start

**All active French SAS that renewed last month**

```json
{ "countries": ["FR"], "legalForms": ["6CHY"], "entityStatuses": ["ACTIVE"], "registrationStatuses": ["ISSUED"], "lastUpdatedFrom": "2026-10-01", "maxResults": 100 }
```

**LEIs about to lapse in Monaco**

```json
{ "countries": ["MC"], "renewalFrom": "2026-11-01", "renewalTo": "2026-12-31", "sortBy": "renewalAsc", "maxResults": 50 }
```

**Group structure of a subsidiary**

```json
{ "mode": "lookup", "leis": ["529900RJ7K80E91EKN44"], "parentChain": true }
```

**Find a company despite a typo**

```json
{ "legalName": "airbsu", "nameMatch": "fuzzy" }
```

**Newly registered funds in Luxembourg**

```json
{ "countries": ["LU"], "categories": ["FUND"], "registeredFrom": "2026-10-01", "sortBy": "registeredDesc", "maxResults": 100 }
```

#### Filters (search mode)

| Field | Meaning |
|---|---|
| `legalName`, `nameMatch` | name text; `prefix` (default), `fulltext` or `fuzzy` |
| `countries` | ISO alpha-2 codes of the legal address (any of) |
| `jurisdictions` | registration jurisdiction, e.g. `US-DE` (any of) |
| `legalForms` | 4-character ELF codes, e.g. `6CHY` = French SAS (any of) |
| `entityStatuses` | `ACTIVE`, `INACTIVE` |
| `registrationStatuses` | `ISSUED`, `LAPSED`, `ANNULLED`, ... |
| `categories` | `GENERAL`, `FUND`, `BRANCH`, `RESIDENT_GOVERNMENT_ENTITY`, `INTERNATIONAL_ORGANIZATION` (sole proprietors do not exist here, by design) |
| `registrationNumber` | national registry number, as written in the registry |
| `lastUpdatedFrom/To`, `renewalFrom/To`, `registeredFrom/To` | date windows, `YYYY-MM-DD` |
| `sortBy` | `lastUpdatedDesc`, `lastUpdatedAsc`, `registeredDesc`, `renewalAsc` |

Filters are combined with AND; lists are OR. `includeParents` / `parentChain` work in every mode.

### Privacy / GDPR by design

This Actor is **deliberately built not to return data about natural persons**. This filtering is applied on purpose, to respect the GDPR; it cannot be switched off.

- **Fail-closed allow-list.** A record is kept only if GLEIF's `entity.category` is one of `GENERAL`, `FUND`, `BRANCH`, `RESIDENT_GOVERNMENT_ENTITY`, `INTERNATIONAL_ORGANIZATION` (legal entities and arrangements). `SOLE_PROPRIETOR` (individuals acting in a business capacity) is always dropped; an empty, missing, unreadable or unknown category is dropped too. The API request itself already asks only for the allowed categories, and the code checks every record again.
- **Second safety net.** Records whose legal form is a sole-trader form (60 ELF codes found in the GLEIF code list such as "Sole Proprietorship", "eenmanszaak", "Einzelunternehmen", "Entreprise individuelle", plus the registrant's free-text legal form mentioning an individual) are dropped even when the category looks fine. Brazilian/Latin-American "Empresa Individual de Responsabilidad Limitada" are dropped too (one-owner vehicles): deliberately over-cautious.
- **Structured company fields only.** No street lines, alternative names, e-mail or phone are output. Parents are shown (LEI, name, country) only when they pass the same check.
- **Measured** (5 Nov 2026, live GLEIF register, 3,000 records, 150 random records from each of 20 countries FR DE GB US IT ES NL IN BR JP CH LU PL SE CN AU CA ZA NO BE): **97.5 % kept (2,925), 2.5 % dropped (75)**: 73 sole proprietors by category (2.4 %) and 2 by the legal-form safety net (0.1 %). In the full register 132,791 of 3,485,407 LEIs (3.8 %) are sole proprietors; the share varies by country (sole proprietors per LEI of the country, counted on the live API: India 22.7 %, Poland 13.2 %, Brazil 5.3 %, Italy 4.8 %, Netherlands 3.2 %, Switzerland 0.6 %, Germany 0.6 %, China 0.4 %, France 0.2 %, USA 0.1 %, UK and Japan about 0 %).
- **Residual risks, stated honestly.** (1) A legal entity can carry a person's name (a company, a one-person SAS/GmbH, a medical practice SELARL, a foundation or a trust named after a family): it is a legal entity, so it stays, and its name and registered address are public company data. (2) Funds and trusts are returned. (3) The check relies on the category and legal form declared in the register; a mistake there is not detectable. (4) Registry numbers (`registrationNumber`) of companies are returned as published. You remain responsible for your own use of the data.
- **Nothing about you is stored.** The Actor keeps no state between runs and stores nothing about who calls it beyond the run's own dataset, key-value record and logs in your Apify account.

### Limits and disclaimer

- **Freshness**: GLEIF publishes the Golden Copy every day (the API reflects it); a company that has just obtained a LEI may appear after a few hours.
- **Quality**: the data is declared by the entities and validated by LEI issuers (see `corroborationLevel`); no warranty, check the official GLEIF record (`gleifUrl`) before relying on it.
- **Coverage**: only entities that have a LEI (about 3.5 million worldwide). Not every company has one.
- **Depth limits**: GLEIF serves at most 10,000 children of one LEI per query; a search returns up to your `maxResults` (max 10,000) records.
- **Speed**: GLEIF documents a limit of 60 requests per minute per user; the Actor spaces its calls accordingly (20 immediate, then 1 per second). Measured on 5 Nov 2026: 0.1 to 0.4 s per call; a search of 20 records takes about 1 s; 37 records with `includeParents` took 39 s (59 GLEIF calls, throttled); allow about 1 s per extra call beyond the first 20.
- **Source and licence**: [GLEIF API](https://www.gleif.org/en/lei-data/gleif-api) (documentation: [api.gleif.org/docs](https://api.gleif.org/docs)). LEI data is published under the **CC0 1.0** public domain dedication ([GLEIF LEI Data Terms of Use](https://www.gleif.org/en/meta/lei-data-terms-of-use): "The data available through the Access Service are provided under the CC0 licence"). The terms ask that you do not suggest that your service is provided or endorsed by GLEIF or a LOU; this Actor does not.
- Unofficial service, not endorsed by GLEIF.

### Pricing

Pay per event, no subscription:

| Event | Price | Per 1,000 |
|---|---|---|
| `lei-record`: one LEI record delivered | **0.004 USD** | **4 USD per 1,000 records** |
| Actor start (once per run) | 0.00005 USD | n/a |

Parents, parent chains and the legal-form labels are included in the record price. Records removed by the GDPR filter, filters or the cost cap are not delivered and not charged. Use the platform's **Maximum cost per run** to cap spend: the Actor reads it, stops cleanly and returns what it already delivered (the cap must allow at least one record).

### En français

Outil non officiel sur le registre public GLEIF des identifiants d'entités juridiques (LEI, données CC0) : recherche par nom, pays, forme juridique ou dates, consultation par LEI, société mère directe et ultime, filiales. Seules les personnes morales sont renvoyées : les entrepreneurs individuels (personnes physiques) sont systématiquement exclus (RGPD dès la conception).

# Actor input Schema

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

Pick one. "search" = use when you look for companies by name, country, legal form, status or dates (you do not have their LEI yet): returns matching LEI records. "lookup" = use when you already have one or more LEIs (20 characters) and want the full record, optionally with parents: returns one record per LEI. "subsidiaries" = use when you have a parent LEI and want the group entities that report it as their parent (direct or ultimate). Allowed values: search, lookup, subsidiaries. Default: search.

## `legalName` (type: `string`):

Search mode: company legal name to search, e.g. "TotalEnergies" or "Airbus SE". By default it matches the START of the legal name (see nameMatch), case-insensitive. Empty = no name filter.

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

Lookup and subsidiaries modes: list of LEIs, 20 characters each (18 letters or digits then 2 digits), e.g. \["529900FCMZ4LKXFD0R69"]. Up to 2000 per run; invalid check digits are reported in the run SUMMARY note, not charged.

## `nameMatch` (type: `string`):

Search mode: how legalName is matched. "prefix" = the legal name starts with your text (default, precise); "fulltext" = your words may appear anywhere in the record (names, other names, addresses; broader and noisier); "fuzzy" = tolerates typos and spelling variants (returns the closest names, at most about 20). Allowed values: prefix, fulltext, fuzzy. Default: prefix.

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

Search mode: ISO 3166-1 alpha-2 country codes of the legal address, as a list, e.g. \["FR", "DE"]. ANY of them matches. Empty = all countries.

## `legalForms` (type: `array`):

Search mode: GLEIF Entity Legal Form codes (4 characters), as a list, e.g. \["6CHY"] = French SAS, \["2HBR"] = German GmbH. The code and its label are returned in legalFormCode and legalFormLabel of every record. ANY of them matches.

## `entityStatuses` (type: `array`):

Search mode: keep only entities with these statuses. ACTIVE = the entity is operating, INACTIVE = it ceased to exist. Empty = both.

## `registrationStatuses` (type: `array`):

Search mode: keep only LEIs with these registration statuses. ISSUED = valid and renewed, LAPSED = not renewed in time, plus ANNULLED, PENDING_TRANSFER, PENDING_ARCHIVAL, DUPLICATE, RETIRED, MERGED. Empty = all.

## `categories` (type: `array`):

Search mode: restrict to these GLEIF entity categories. GENERAL = companies and other legal entities, FUND = funds, BRANCH = branches of a legal entity, RESIDENT_GOVERNMENT_ENTITY = public bodies, INTERNATIONAL_ORGANIZATION. Sole proprietors (natural persons) are never offered and never returned (GDPR by design). Empty = all five.

## `jurisdictions` (type: `array`):

Search mode: legal jurisdiction where the entity is registered, as a list of ISO 3166 codes with optional subdivision, e.g. \["FR", "US-DE"] (US-DE = Delaware). Differs from the address country for foreign-registered companies.

## `registrationNumber` (type: `string`):

Search mode: the entity's number in its national business registry, written exactly as the registry shows it (spaces included), e.g. "383 474 814" for a French SIREN. Returns the matching LEI record, if any.

## `lastUpdatedFrom` (type: `string`):

Search mode: only LEI records updated on or after this date. Format YYYY-MM-DD, example 2026-10-01. Use it to watch recent changes.

## `lastUpdatedTo` (type: `string`):

Search mode: only LEI records updated on or before this date. Format YYYY-MM-DD, example 2026-10-31.

## `renewalFrom` (type: `string`):

Search mode: only LEIs whose next renewal is due on or after this date. Format YYYY-MM-DD, example 2026-11-01. Useful to find LEIs about to lapse (lead generation, compliance).

## `renewalTo` (type: `string`):

Search mode: only LEIs whose next renewal is due on or before this date. Format YYYY-MM-DD, example 2026-12-31.

## `registeredFrom` (type: `string`):

Search mode: only LEIs first issued on or after this date. Format YYYY-MM-DD, example 2026-01-01. Use it to find newly registered entities.

## `registeredTo` (type: `string`):

Search mode: only LEIs first issued on or before this date. Format YYYY-MM-DD, example 2026-06-30.

## `sortBy` (type: `string`):

Search mode: order of the results. "default" = GLEIF's own order (empty input then lists the most recently updated records). Allowed values: default, lastUpdatedDesc, lastUpdatedAsc, registeredDesc, renewalAsc. Default: default.

## `subsidiaryLevel` (type: `string`):

Subsidiaries mode: "direct" = entities whose direct parent is the LEI you give; "ultimate" = entities whose ultimate parent (top of the group) is that LEI. Allowed values: direct, ultimate. Default: direct.

## `includeParents` (type: `boolean`):

true = add the direct and ultimate parent (LEI, name, country) of every record, or the reason GLEIF gives when none is reported. Costs 1 to 2 extra GLEIF calls per record (GLEIF allows 60 requests per minute), so keep maxResults small. Parents that are not legal entities are never shown. Default: false.

## `parentChain` (type: `boolean`):

true = also return parentChain, the list of parents from the direct parent up to the top of the group (max 10 levels). Implies includeParents. Slower: one GLEIF call per level. Default: false.

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

Maximum number of LEI records returned, integer 1-10000, default 20 (keep it small, e.g. 20; raise it only if the run SUMMARY says capped: true). Your run cost limit also applies.

## Actor input object example

```json
{
  "mode": "search",
  "legalName": "Airbus",
  "leis": [
    "529900FCMZ4LKXFD0R69"
  ],
  "countries": [
    "FR",
    "DE"
  ],
  "legalForms": [
    "6CHY"
  ],
  "entityStatuses": [
    "ACTIVE"
  ],
  "registrationStatuses": [
    "ISSUED"
  ],
  "categories": [
    "GENERAL",
    "FUND"
  ],
  "jurisdictions": [
    "US-DE"
  ],
  "registrationNumber": "383 474 814",
  "maxResults": 20
}
```

# Actor output Schema

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

Main fields of each LEI record: name, legal form, address country and city, status, renewal date.

## `parents` (type: `string`):

Direct and ultimate parent of each record (when parents were requested).

## `allFields` (type: `string`):

Every field of every record.

# 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 = {
    "legalName": "Airbus"
};

// Run the Actor and wait for it to finish
const run = await client.actor("shadow-tools/lei-company-lookup-gleif").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 = { "legalName": "Airbus" }

# Run the Actor and wait for it to finish
run = client.actor("shadow-tools/lei-company-lookup-gleif").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 '{
  "legalName": "Airbus"
}' |
apify call shadow-tools/lei-company-lookup-gleif --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,shadow-tools/lei-company-lookup-gleif"
        }
    }
}
```

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/4dHpLXytiybtPTKC4/builds/lGsOQ5xqTArETKHX9/openapi.json
