# GLEIF LEI Lookup & Validator API – KYB Company Registry (`opentenders/gleif-lei-scraper`) Actor

GLEIF API lookup for the global LEI registry: search by company name, validate LEI lists in bulk, filter by country, category, status or last update. Legal name, addresses, LEI status, renewal date, BIC, direct and ultimate parent. Daily change monitoring for KYB. No API key. From $1 per 1,000.

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

## Pricing

from $1.00 / 1,000 entity founds

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 & Validator API – KYB Company Registry Scraper

Validate LEIs in bulk and look up companies in the **global Legal Entity Identifier registry (GLEIF)** through the official GLEIF API, the official open register of 3 million legal entities worldwide, by **company name, list of LEIs, country, category, entity status, LEI registration status or last update date**. One flat row per entity: legal name and other names, legal and headquarters address, jurisdiction, legal form, registration authority and registered number, BIC, LEI status (issued, lapsed, retired…), renewal date, last update, and optionally the **direct and ultimate parent** from GLEIF relationship data.

Built for **KYB and compliance teams, banks and fintechs onboarding counterparties, fund administrators, procurement and credit analysts, and data teams** that need to validate thousands of LEIs or monitor a market for changes every day.

### Why this one

- **Official GLEIF API, no key, no account.** Golden Copy data, refreshed daily; every row carries `goldenCopyDate`.
- **Batch validation.** Paste thousands of LEIs; they are fetched 200 per request. LEIs that do not exist come back in one error row so your pipeline sees them, without being charged.
- **Change monitoring built in.** `updatedAfter` uses GLEIF's own `registration.lastUpdateDate`, so a daily schedule with yesterday's date and a country (or query) returns only entities whose LEI record changed: new registrations, lapses, renewals, address or name updates.
- **Red flags at a glance.** `registrationStatus` = `LAPSED` means the entity stopped renewing its LEI; `entityStatus` = `INACTIVE` means it was merged or dissolved.
- **Corporate structure on demand.** `includeParents` adds the direct and ultimate parent (LEI and legal name) from GLEIF Level 2 data.

### Pricing

Pay per entity returned, no subscription:

| Event | Price |
|---|---|
| Entity found (`entity`) | **$1.00 per 1,000** entities |
| Entity with direct and ultimate parent (`entity-with-parents`) | **$1.50 per 1,000** entities |

Each entity is charged once, in one event or the other. Error rows, LEIs not found, empty runs and run starts are never charged. Apify's free plan ($5 monthly credit) covers 5,000 lookups per month.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `query` | string | | Full-text search over legal and other names, e.g. `siemens`, `banco do brasil`. |
| `leis` | array | | Exact LEIs to look up (20 characters), any number. |
| `country` | string | | ISO-2 country of the legal address, e.g. `BR`, `DE`, `US`. |
| `category` | string | any | `GENERAL`, `FUND`, `BRANCH`, `SOLE_PROPRIETOR`, `RESIDENT_GOVERNMENT_ENTITY`, `INTERNATIONAL_ORGANIZATION`. |
| `entityStatus` | string | any | `ACTIVE` or `INACTIVE`. |
| `registrationStatus` | array | `[]` | `ISSUED`, `LAPSED`, `RETIRED`, `ANNULLED`, `MERGED`, `DUPLICATE`, `PENDING_TRANSFER`, `PENDING_ARCHIVAL`, `CANCELLED`, `TRANSFERRED`. |
| `updatedAfter` | string | | `YYYY-MM-DD`. Only records updated on or after this date. |
| `includeParents` | boolean | `false` | Fetch direct and ultimate parent (two extra requests per entity). |
| `maxItems` | integer | `100` | Stop after this many entities. |
| `minResults` | integer | | Monitoring only: fail the run if fewer entities are returned. |

At least one filter is required.

Validate a counterparty list with parents:

```json
{ "leis": ["5299000J2N45DDNE4Y28", "529900T8BM49AURSDO55", "W38RGI023J3WT1HWRP32"], "includeParents": true }
```

Daily monitor: every Brazilian fund whose LEI record changed since yesterday:

```json
{ "country": "BR", "category": "FUND", "updatedAfter": "2026-10-25", "maxItems": 5000 }
```

Lapsed LEIs in Portugal (entities that stopped renewing):

```json
{ "country": "PT", "registrationStatus": ["LAPSED"], "maxItems": 1000 }
```

### Output

```json
{
    "lei": "529900T8BM49AURSDO55",
    "legalName": "Ubisecure Oy",
    "otherNames": [],
    "entityStatus": "ACTIVE",
    "category": "GENERAL",
    "subCategory": null,
    "legalFormId": "DKUW",
    "jurisdiction": "FI",
    "registeredAs": "2399234-6",
    "registrationAuthorityId": "RA000188",
    "legalAddress": "Vaisalantie 6",
    "legalCity": "ESPOO",
    "legalRegion": "FI-18",
    "legalCountry": "FI",
    "legalPostalCode": "02130",
    "hqAddress": "Vaisalantie 6",
    "hqCity": "ESPOO",
    "hqRegion": "FI-18",
    "hqCountry": "FI",
    "hqPostalCode": "02130",
    "bic": [],
    "creationDate": null,
    "expirationDate": null,
    "expirationReason": null,
    "successorLei": null,
    "registrationStatus": "ISSUED",
    "initialRegistrationDate": "2014-06-12T00:00:00Z",
    "lastUpdateDate": "2026-06-09T15:12:35Z",
    "nextRenewalDate": "2027-06-28T18:34:06Z",
    "managingLou": "5299000J2N45DDNE4Y28",
    "corroborationLevel": "FULLY_CORROBORATED",
    "directParentLei": "213800N7JPQ8TFAN3F37",
    "directParentName": "UBISECURE HOLDINGS LIMITED",
    "ultimateParentLei": "213800N7JPQ8TFAN3F37",
    "ultimateParentName": "UBISECURE HOLDINGS LIMITED",
    "url": "https://search.gleif.org/#/record/529900T8BM49AURSDO55",
    "goldenCopyDate": "2026-10-26T08:00:00Z",
    "scrapedAt": "2026-10-26T15:02:11.000Z"
}
```

Parent fields are `null` unless `includeParents` is on or when GLEIF holds no parent record (reporting exception or top of the group). Missing data is `null`, never invented. Error rows look like `{ "error": true, "errorType": "LEI_NOT_FOUND" | "NO_RESULTS" | "INVALID_INPUT", "message": "..." }`.

### Use it from code

```bash
curl -X POST "https://api.apify.com/v2/acts/opentenders~gleif-lei-scraper/run-sync-get-dataset-items?format=json" \
  -H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" \
  -d '{"leis":["5299000J2N45DDNE4Y28"],"includeParents":true}'
```

Works with the Apify API, clients, MCP server, Make, Zapier, n8n and Google Sheets integrations.

### Limitations

- Legal entities only; GLEIF contains no personal data.
- Legal form and registration authority are returned as GLEIF codes (`legalFormId`, `registrationAuthorityId`); the code lists are published by GLEIF.
- Parents exist only where the child reports them to GLEIF (Level 2 data); many entities report an exception instead.
- Requests run two at a time with 200 records each, so 10,000 entities take about a minute; with parents, allow a few minutes per thousand.

### FAQ

**Is this allowed?** Yes. GLEIF publishes LEI data as open data free of charge through its public API, without registration.

**How do I check whether a LEI is still valid?** Look at `registrationStatus` (`ISSUED` = valid) and `nextRenewalDate`. `LAPSED` means the registration was not renewed.

**Can I search by other identifiers (BIC, ISIN)?** Not yet; use `query` with the company name. Open an issue if you need it.

**Something broke?** Open an issue with the run ID; the actor fails with the exact GLEIF response when the API changes.

# Actor input Schema

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

Full-text search over legal and other names (GLEIF <code>filter\[fulltext]</code>), e.g. <code>siemens</code>, <code>banco do brasil</code>. Combine with country/category to narrow.

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

Exact 20-character LEIs, one per line, up to thousands. Each is fetched in batches of 200; LEIs not found are reported in one error row (not charged).

## `country` (type: `string`):

Two-letter country code of the legal address, e.g. <code>BR</code>, <code>DE</code>, <code>US</code>.

## `category` (type: `string`):

GLEIF entity category.

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

Whether the legal entity itself is active or inactive (merged, dissolved). Empty = any.

## `registrationStatus` (type: `array`):

Empty = any. <code>ISSUED</code> = valid and renewed; <code>LAPSED</code> = not renewed (a KYB red flag).

## `updatedAfter` (type: `string`):

Only records whose LEI registration was updated on or after this date (status changes, renewals, address or name changes). Set it to yesterday in a daily schedule, together with a country or query, to monitor changes.

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

Also fetch the direct parent and ultimate parent entity (LEI and name) from GLEIF relationship data. Two extra requests per entity; charged as a separate, higher-priced event.

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

Stop after this many entities. Caps your cost.

## `minResults` (type: `integer`):

Optional. Fail the run if fewer entities are returned.

## Actor input object example

```json
{
  "query": "siemens",
  "category": "",
  "entityStatus": "",
  "registrationStatus": [],
  "includeParents": false,
  "maxItems": 100
}
```

# Actor output Schema

## `results` (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 = {
    "query": "siemens"
};

// Run the Actor and wait for it to finish
const run = await client.actor("opentenders/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 = { "query": "siemens" }

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

```

## MCP server setup

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