# GLEIF LEI Lookup: Company Ownership, Parents & Subsidiaries (`frenchdatalab/lei-lookup-corporate-ownership`) Actor

Find the LEI of any company (name, LEI, registration number, ISIN, BIC) with its direct and ultimate parent, list every subsidiary of a group, or search 3.4M entities by country, city, LEI issue or renewal date. Official GLEIF data (CC0).

- **URL**: https://apify.com/frenchdatalab/lei-lookup-corporate-ownership.md
- **Developed by:** [French Data lab](https://apify.com/frenchdatalab) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 entities

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

## GLEIF LEI Lookup: Company Ownership, Parents & Subsidiaries

Look up any company in the **global LEI system (3.4 million legal entities, 200+ countries)** and get its official identity **with its direct and ultimate parent company**, list **every subsidiary of a group**, or **search the register** by country, city, legal form, LEI issue date or renewal date.

Official GLEIF data, free to reuse (CC0). No scraping.

### What can you do with it?

- 🔎 **Find the LEI of a list of companies.** Paste names (`BNP Paribas`, `Siemens AG`, `Tesla, Inc.`), LEIs, national registration numbers (SIREN, HRB…), ISINs or BIC codes. You get one row per input, in the same order, with a match score.
- 🏢 **KYC / AML / supplier due diligence.** Legal name, registered address, legal form, registration number and authority, LEI status (valid or lapsed), and **who owns the entity**: direct parent, ultimate parent, or the official reason why no parent is reported (owned by natural persons, no known controller…).
- 🌳 **Map a corporate group.** Give the LEI of a parent company and get all its subsidiaries, level by level, in every country: TotalEnergies SE returns 219 entities; filter them by country, city or status.
- 🎯 **Prospecting.** Entities that **got an LEI in the last 7 days** (new funds, SPVs, companies starting to trade or borrow), entities whose **LEI has lapsed**, or whose **renewal is due** in the next 30 days. Ideal for LEI registration agents, banks, brokers and B2B data teams.
- 💹 **Securities data.** ISIN → issuer, and optionally the list of ISINs issued by each entity.

### Why this Actor?

| | This Actor | Typical LEI lookups |
|---|---|---|
| Direct **and** ultimate parent, with names, in every result | ✅ | ❌ or extra runs |
| Reason when no parent is reported (natural persons, no known person…) | ✅ | ❌ |
| Whole corporate group, all levels, filterable | ✅ | ❌ direct children at best |
| Company-name matching | ✅ legal forms understood (AG = Aktiengesellschaft, S.A. = SA…), group head preferred over namesake subsidiaries, brands and acronyms (LVMH) | ⚠️ first text hit, often a fund or a branch |
| Registration number, ISIN and BIC look-ups | ✅ SIREN/SIRET formats handled | ❌ |
| LEI check digits verified, typos reported | ✅ not charged | ❌ charged or silent |
| No cap on search results | ✅ cursor pagination (the API stops at 10,000 otherwise) | ⚠️ |
| Legal form and registration authority in plain words | ✅ "société par actions simplifiée", "Commercial Register — Local Court Pinneberg" | ❌ codes like 6CHY, RA000320 |

### Input

**Look up** (one result per input, in order; inputs not found come back with `found: false` and are **not charged**):

| Field | Example |
|---|---|
| `companyNames` | `["TotalEnergies SE", "Siemens AG", "Tesla, Inc."]` |
| `leis` | `["529900S21EQ1BO4ESM68"]` |
| `registrationNumbers` | `["542051180", "HRB 42243"]` |
| `isins` | `["FR0000120271"]` |
| `bics` | `["BNPAFRPP"]` |

**Corporate group**: `groupParentLeis` (e.g. `["529900S21EQ1BO4ESM68"]`) and `directSubsidiariesOnly`.

**Search the register** (any combination):

| Field | Description | Example |
|---|---|---|
| `countries` | ISO codes of the legal address | `["FR", "DE"]` |
| `cities` / `postalCodes` | Exact city names / postal codes (districts like "Lyon 2eme" included) | `["Lyon"]` |
| `nameContains` | Words that must appear in the legal name | `"capital"` |
| `categories` | Companies, funds, branches, sole proprietors, government entities… | `["GENERAL"]` |
| `legalForms` | ISO 20275 ELF codes | `["6CHY"]` (French SAS), `["2HBR"]` (GmbH) |
| `leiStatuses` | `ISSUED`, `LAPSED`, `RETIRED`… | `["LAPSED"]` |
| `activeOnly` | Exclude dissolved entities (default `true`) | `true` |
| `registeredWithinDays` / `registeredSince` / `registeredUntil` | LEI issue date | `7` |
| `renewalDueWithinDays` | LEI renewal between today and today + N days | `30` |
| `parentCompaniesOnly` | Only entities with subsidiaries | `true` |

**Options**: `includeSubsidiaryCounts` (number of direct subsidiaries and of group entities), `includeIsins` (up to 100 ISINs + total count per entity), `maxResults`.

Examples:

```json
{ "companyNames": ["BNP Paribas", "Deutsche Bank", "LVMH"] }
```

→ BNP PARIBAS (FR), DEUTSCHE BANK AKTIENGESELLSCHAFT (DE) and LVMH MOET HENNESSY LOUIS VUITTON (FR): the group heads, not one of their namesake subsidiaries.

```json
{ "countries": ["FR"], "cities": ["Lyon"], "leiStatuses": ["LAPSED"] }
```

→ active companies in Lyon whose LEI has lapsed.

```json
{ "countries": ["DE"], "renewalDueWithinDays": 30, "categories": ["GENERAL"] }
```

→ German companies whose LEI must be renewed in the next 30 days (soonest first).

### Output

Real example (`companyNames: ["TotalEnergies Bitumen Deutschland GmbH"]`):

```json
{
    "found": true,
    "lei": "529900695SG4TLQD6O26",
    "legalName": "TotalEnergies Bitumen Deutschland GmbH",
    "entityStatus": "ACTIVE",
    "leiStatus": "ISSUED",
    "category": "GENERAL",
    "legalFormCode": "2HBR",
    "legalForm": "Gesellschaft mit beschränkter Haftung",
    "registrationNumber": "HRB 598 ME",
    "registrationAuthority": "Commercial Register — Local Court Pinneberg",
    "address": "Industriegebiet Süd",
    "postalCode": "25541",
    "city": "Brunsbüttel",
    "country": "DE",
    "entityCreationDate": "1989-02-16",
    "leiIssuedDate": "2014-01-20",
    "nextRenewalDate": "2027-02-16",
    "daysUntilRenewal": 137,
    "corroborationLevel": "FULLY_CORROBORATED",
    "directParentLei": "529900S21EQ1BO4ESM68",
    "directParentName": "TotalEnergies SE",
    "directParentCountry": "FR",
    "ultimateParentLei": "529900S21EQ1BO4ESM68",
    "ultimateParentName": "TotalEnergies SE",
    "ultimateParentCountry": "FR",
    "hasSubsidiaries": false,
    "ownership": "Subsidiary of TotalEnergies SE (FR)",
    "gleifUrl": "https://search.gleif.org/#/record/529900695SG4TLQD6O26",
    "dataAsOf": "2026-10-02",
    "query": "TotalEnergies Bitumen Deutschland GmbH",
    "queryType": "name",
    "matchType": "exact",
    "matchScore": 100,
    "otherMatches": []
}
```

Other fields: `otherNames`, `jurisdiction`, `region`, headquarters address (`hqAddress`, `hqCity`…), `lastUpdateDate`, `managingLou`, `bics`, `mics`, `openCorporatesId`, `spGlobalIds`, `conformityFlag`, `expirationDate` / `expirationReason`, `successorLei` / `successorName`, `directParentException` / `ultimateParentException`, and in group mode `groupParentLei`, `groupParentName`, `groupRelation` ("direct subsidiary", "indirect subsidiary (level 2)"…).

**Match types** for names: `exact` (same name; same legal form when you give one), `close` (same name with another legal form, or a small typo), `partial`, `group head` (brand or acronym: the parent shared by the entities carrying that name). `otherMatches` lists companies with the same name in other countries.

**Why no parent?** When an entity reports no parent, the official reason is given:

| Code | Meaning |
|---|---|
| `NATURAL_PERSONS` | Controlled by one or more natural persons |
| `NO_KNOWN_PERSON` | No known person or entity controls it (e.g. widely held listed company) |
| `NON_CONSOLIDATING` | The controlling entity does not consolidate it in its accounts |
| `NON_PUBLIC` / `LEGAL_OBSTACLES` / `CONSENT_NOT_OBTAINED`… | Parent exists but its disclosure is restricted |

### Notes

- Ownership data is what entities report to the LEI system (accounting consolidation, IFRS / US GAAP). It is official and widely used for KYC, but not a beneficial-owner (UBO) register.
- Sole proprietors (natural persons) are only returned in searches when you select that category.
- GLEIF allows 60 requests per minute: name look-ups take 1–5 seconds each, searches and groups return several thousand entities per minute. `includeSubsidiaryCounts` and `includeIsins` add one request per entity.

### Pricing

Pay per entity returned. Inputs that are not found are free. Set a maximum cost per run and the Actor stops exactly there.

### Source & licence

LEI data from the **Global Legal Entity Identifier Foundation (GLEIF)** Golden Copy, published under **CC0 1.0** (free reuse, including commercial). This Actor is independent: it is **not affiliated with or endorsed by GLEIF**. Data is provided as published by the LEI issuers.

# Actor input Schema

## `companyNames` (type: `array`):

Find the LEI of each company. Legal-form words (SA, SE, GmbH, Inc., Ltd…) and accents are handled; each result has a matchType (exact / close / partial) and a matchScore. Companies with the same name are listed in otherMatches.

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

20-character Legal Entity Identifiers, e.g. 529900S21EQ1BO4ESM68. Check digits are verified: typos are reported, not charged.

## `registrationNumbers` (type: `array`):

Company register numbers as used in each country: French SIREN or SIRET (542051180), German HRB 42243, UK Companies House number, etc.

## `isins` (type: `array`):

Securities identifiers (e.g. FR0000120271): returns the issuer.

## `bics` (type: `array`):

8 or 11 characters, e.g. BNPAFRPP: returns the bank.

## `groupParentLeis` (type: `array`):

Lists every subsidiary of these companies, level by level (e.g. 529900S21EQ1BO4ESM68 = TotalEnergies SE). The search filters below (countries, cities, active only…) narrow the subsidiaries returned.

## `directSubsidiariesOnly` (type: `boolean`):

Only the first level (entities whose direct parent is the company).

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

2-letter ISO codes of the legal address: FR, DE, GB, US, LU, IE… In look-up mode, used to choose between companies with the same name.

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

Exact city names (case-insensitive), e.g. "Paris", "Frankfurt am Main", "London".

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

Exact postal codes, e.g. "75008", "60311".

## `nameContains` (type: `string`):

Every word must appear in the legal name, e.g. "capital partners".

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

Leave empty for all except sole proprietors (natural persons, only returned when selected here). GENERAL = companies and other legal entities.

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

ISO 20275 codes, e.g. 6CHY (French SAS), 2HBR (German GmbH), H0PO (UK private limited company), XTIQ (Delaware corporation). Full list: gleif.org > Entity Legal Forms.

## `leiStatuses` (type: `array`):

Leave empty for all. LAPSED = the entity did not renew its LEI on time (its data is no longer re-verified each year).

## `activeOnly` (type: `boolean`):

Exclude entities that no longer exist (dissolved, merged…).

## `registeredWithinDays` (type: `integer`):

New LEIs = newly created or newly regulated companies, investment funds, SPVs. Great for scheduled runs (e.g. 7 = every week).

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

YYYY-MM-DD

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

YYYY-MM-DD

## `renewalDueWithinDays` (type: `integer`):

Entities whose LEI must be renewed between today and today + N days (sorted by renewal date).

## `parentCompaniesOnly` (type: `boolean`):

Only entities that have at least one subsidiary.

## `includeSubsidiaryCounts` (type: `boolean`):

Adds directSubsidiaries and groupSubsidiaries to entities that have subsidiaries (one or two extra API calls each: slower).

## `includeIsins` (type: `boolean`):

Adds the securities (ISINs) issued by each entity: up to 100 codes + the total count (one extra API call per entity: slower).

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

Maximum number of entities returned (charged).

## Actor input object example

```json
{
  "companyNames": [
    "TotalEnergies SE",
    "Siemens AG",
    "Tesla, Inc."
  ],
  "directSubsidiariesOnly": false,
  "activeOnly": true,
  "parentCompaniesOnly": false,
  "includeSubsidiaryCounts": false,
  "includeIsins": false,
  "maxResults": 50
}
```

# Actor output Schema

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

No description

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

No description

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

No description

# 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 = {
    "companyNames": [
        "TotalEnergies SE",
        "Siemens AG",
        "Tesla, Inc."
    ],
    "maxResults": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("frenchdatalab/lei-lookup-corporate-ownership").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 = {
    "companyNames": [
        "TotalEnergies SE",
        "Siemens AG",
        "Tesla, Inc.",
    ],
    "maxResults": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("frenchdatalab/lei-lookup-corporate-ownership").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 '{
  "companyNames": [
    "TotalEnergies SE",
    "Siemens AG",
    "Tesla, Inc."
  ],
  "maxResults": 50
}' |
apify call frenchdatalab/lei-lookup-corporate-ownership --silent --output-dataset

```

## MCP server setup

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

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/YB3WYCwJD9hgi5ECm/builds/lIfeNnsTf8kJCclKw/openapi.json
