# Company Registry Lookup: UK Companies House and LEI Data (`pracadata/company-registry-lookup`) Actor

Look up, search, match and monitor legal entities: every live UK company (Companies House) and every LEI worldwide in one English schema. Lookup by number or LEI, name search, name matching with a score, weekly change feed. Legal persons only. API and AI-agent (MCP) ready.

- **URL**: https://apify.com/pracadata/company-registry-lookup.md
- **Developed by:** [Lucas Huber Pissaia](https://apify.com/pracadata) (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 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.

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

## Company Registry Lookup: UK Companies House and LEI Data

### What does it do?

Looks up, searches, matches and monitors **legal entities** in a ready-made snapshot of **every live UK company** (Companies House, about 5.7 million companies) and **every legal entity with an LEI worldwide** (about 3.1 million LEI records), linked in one clean English schema: when a UK company has an LEI, you get both on the same row. Five modes:

- **`lookup`**: UK company number or LEI → the entity (status, legal form, incorporation date, city, industry, LEI status).
- **`search`**: a name → the most similar entities, with a score.
- **`filter`**: every entity matching country, status, industry (NACE), legal form and incorporation date. Example: active UK software companies incorporated this year.
- **`match`**: your list of names (a supplier list, a CRM export) → the best candidate for each name, with a score, the company number and the LEI.
- **`changes`**: the **weekly change feed**: new entities, renamed, status changes, companies that left the register, LEIs that lapsed.

It answers in seconds from a snapshot: no API key, no rate limit, nothing to scrape. Use it as an API, schedule it, or call it as an MCP tool from an AI agent (see "Use with AI agents (MCP)").

**Data last updated: 27 October 2026** (UK snapshot of 1 October 2026; LEI Golden Copy of 26 October 2026; the `RUN_SUMMARY` of every run carries both dates). LEI refreshed weekly, UK monthly.

**Try before you pay:** a free **sample** of about 100,000 entities (about 1% of the registry, stratified by country and legal form) with the same schema, plus the LEI ↔ UK links, is on Hugging Face: <https://huggingface.co/datasets/pracadata/legal-entities-registry>. Check the schema and the quality there, then come back for the whole registry, lookup, search, matching and the change feed.

### Legal persons only (read this first)

This Actor is built for **know-your-business checks, supplier and CRM reconciliation, and entity resolution**, not for lead generation:

- **No people.** Sole proprietors are removed from the LEI data (category `SOLE_PROPRIETOR`, and every ISO 20275 legal form that is a sole trader). There are **no officers, directors, shareholders, persons with significant control, e-mails or phone numbers**, and there never will be.
- **No street addresses.** City, region and, for the UK, only the postcode area (`SW1A`, not `SW1A 1AA`). Many small companies are registered at a home address.
- **UK: live companies only.** The Companies House bulk file only has live companies. A dissolved company leaves it; `changes` reports it as `removed_from_source`.

If you need directors or contact data, this is not the right tool.

### Why use it?

- **UK company number and LEI on one row.** The link comes from the LEI record itself (registration authority Companies House + company number), not from name guessing.
- **Fast and predictable.** A lookup of 3 IDs takes seconds; there is no per-minute quota as with registry APIs.
- **Name matching with a score.** Legal suffixes (Ltd, Limited, PLC, Inc, GmbH…) and punctuation are normalised; you set `min_score`.
- **A change feed nobody else keeps.** Registries publish the current state. This Actor diffs snapshots every week and keeps the history.
- **Clean, documented fields.** English column names, harmonised `status`, ISO 20275 legal-form codes, NACE Rev. 2 next to the UK SIC codes.

### What data can it return?

| Mode | One row is | Main fields |
|---|---|---|
| `lookup`, `filter` | one entity | `entity_uid`, `lei`, `register_id`, `name`, `country`, `jurisdiction`, `status`, `status_raw`, `legal_form_raw`, `legal_form_elf`, `legal_form_label_en`, `entity_category`, `incorporation_date`, `seat_city`, `seat_region`, `seat_postcode_area`, `industry_codes`, `nace_rev2`, `accounts_next_due`, `confirmation_statement_next_due`, `charges_outstanding`, `previous_names`, `partnership_risk`, `lei_registration_status`, `lei_next_renewal_date`, `source`, `source_snapshot_date`, `source_url`, `licence` (and `input_id` in `lookup`) |
| `search` | one candidate for one of your names | the entity fields + `input_name`, `match_score`, `match_rank` |
| `match` | your name with its best candidate | the entity fields + `input_name`, `match_score` |
| `changes` | one change of one field | `change_week`, `change_type`, `entity_uid`, `name`, `field`, `old_value`, `new_value`, `previous_snapshot_date`, `source_snapshot_date` |

`entity_uid` is `GB-CH:<company number>` for UK companies and `LEI:<lei>` for LEI records with no live UK company (other countries, and UK companies that are no longer live).

#### Input examples

Each example was run against the data of 27 October 2026; row counts are exact for that build, and the cost is rows × the price of the event on the Pricing tab, which is authoritative.

Look up three entities by UK company number and LEI (the default input; 3 rows):

```json
{ "mode": "lookup", "ids": ["00445790", "00102498", "HWUPKR0MPOU8FGXBT394"] }
```

3 rows: Tesco PLC, BP p.l.c. and Apple Inc., in about a second. Cost: 3 `entity-row`.

Match a supplier list to entities (one row per name that has a candidate):

```json
{ "mode": "match", "names": ["Tesco plc", "BP P.L.C.", "Apple Inc"], "min_score": 0.9 }
```

3 rows, all with score 1.0: `GB-CH:00445790`, `GB-CH:00102498` and `LEI:HWUPKR0MPOU8FGXBT394` (Apple Inc., US). Cost: 3 `match-row`.

Active UK companies in computer programming (NACE 62) incorporated in September 2026 (5,152 match; this example returns the first 100, in a fixed order; raise `max_rows` to get them all):

```json
{ "mode": "filter", "countries": ["GB"], "status": ["active"], "nace_prefix": "62", "incorporated_from": "2026-09-01", "incorporated_to": "2026-09-30", "max_rows": 100 }
```

100 rows, about a second. Cost: 100 `entity-row`; all 5,152 would be 5,152.

UK companies that left the register since 12 October 2026 (the change feed starts with the first two consecutive snapshots, so a run before that returns 0 rows and costs nothing):

```json
{ "mode": "changes", "countries": ["GB"], "changes_since": "2026-10-12", "change_types": ["removed_from_source"], "max_rows": 10000 }
```

Cost: 1 `change-row` per change.

#### Output example (lookup)

Real output of the first default ID (abridged to the main fields):

```json
{ "input_id": "00445790", "entity_uid": "GB-CH:00445790", "source": "companies_house", "country": "GB", "register_id": "00445790",
  "registration_authority_id": "RA000585", "lei": "2138002P5RNKC5W2JZ46", "name": "TESCO PLC", "legal_form_raw": "Public Limited Company",
  "legal_form_elf": "B6ES", "status": "active", "status_raw": "Active", "incorporation_date": "1947-11-27", "seat_city": "WELWYN GARDEN CITY",
  "seat_postcode_area": "AL7", "nace_rev2": "47.11", "lei_registration_status": "ISSUED", "source_snapshot_date": "2026-10-01", "licence": "CH s.47 CDPA approval; CC0-1.0" }
```

### Use with AI agents (MCP)

The Apify MCP server lets an AI agent find this Actor, read its input schema and call it as a tool (`search-actors`, `fetch-actor-details`, `call-actor`, `get-dataset-items`; the run's `maxTotalChargeUsd` goes in `callOptions`). Running Actors needs an Apify account.

```
https://mcp.apify.com?tools=pracadata/company-registry-lookup
```

- **Claude (Desktop or web):** Settings → Connectors → Add custom connector, paste the URL, sign in to Apify.
- **Cursor, VS Code and other `mcpServers` clients:** `{ "mcpServers": { "apify": { "url": "https://mcp.apify.com?tools=pracadata/company-registry-lookup" } } }`; without a browser, add `"headers": { "Authorization": "Bearer <APIFY_TOKEN>" }`.

**What an agent should know.** "Does this company exist and is it active?" → `lookup` with the company number or LEI. "Which company is this name?" → `match` (one row per name, cheapest). "Find companies like…" → `search` or `filter`. Always set `max_rows` and a small maximum charge per run. Read `status`, and `source_snapshot_date` for how recent the row is.

| Question | Input | Rows |
|---|---|---|
| "Is Tesco PLC active, and what is its LEI?" | `lookup`, `ids` \["00445790"] | 1 |
| "Match these 50 supplier names to UK companies" | `match`, `names` \[50 names], `countries` \["GB"] | ≤ 50 |
| "New UK fintech companies this month" | `filter`, `countries` \["GB"], `nace_prefix` "64", `incorporated_from` first day of the month | varies; cap with `max_rows` |
| "Which of my counterparties' LEIs lapsed this week?" | `changes`, `change_types` \["lei_lapsed"] | varies |

### Pricing

This Actor uses **pay per event**. The Pricing tab is authoritative:

| Event | What you are charged for |
|---|---|
| `entity-row` | each entity returned by `lookup` (ID found), `search` or `filter` |
| `match-row` | each of your names in `match` that returned a candidate at or above `min_score` |
| `change-row` | each row of the change feed |

**Not charged:** IDs that are not found (`RUN_SUMMARY.not_found` lists them) and names with no candidate. Rows are charged before they are delivered, in batches, and the run stops at your *maximum charge per run*: you never get a row you were not charged for, and never pay for a row you did not get (`RUN_SUMMARY.charged`, `stopped_by_spending_limit`).

### Source and attribution

- **LEI data:** Contains LEI data from the Global Legal Entity Identifier Foundation (GLEIF), available under CC0 1.0 (<https://www.gleif.org/en/meta/lei-data-terms-of-use>). This Actor is **not provided, endorsed, sponsored or authorised by GLEIF** or any LEI issuing organisation, and has no special relationship with them. The data has been filtered and transformed.
- **UK company data:** Source: Companies House, Free Company Data Product (BasicCompanyData) (<https://download.companieshouse.gov.uk/en_output.html>). Information on the public register is made available under Companies House approvals issued in accordance with section 47 of the Copyright, Designs and Patents Act 1988. **Companies House is not responsible for this Actor.** Care-of names, street addresses and partner counts are removed; postcodes are reduced to the outward code.
- **Legal forms:** ISO 20275 Entity Legal Forms code list, as published by GLEIF.

### Privacy

The data describes **legal persons**. Sole proprietors are excluded, and no column describes a natural person. A company's registered name can contain a person's name, and limited and Scottish partnerships are flagged with `partnership_risk = true` for that reason. Do not use the data to identify, profile or contact individuals. Removal requests and data-protection (UK GDPR) questions: `lucashpissaia@gmail.com`; removals apply from the next weekly build.

### Licence and terms

- **Unofficial.** Derived work, not an official register extract. For legal or regulatory decisions, confirm with the registry.
- **Use:** your own checks, analysis and products built on the results. Do not resell the raw rows in volume as a substantially similar dataset or API.
- **No warranty:** provided as is, from public sources, with the limitations in this README.
- **Withdrawal:** if a source restricts reuse, the Actor may be withdrawn. Takedown requests: `lucashpissaia@gmail.com`.

### Known limitations

- **UK snapshot is monthly**, so a company incorporated or dissolved this month appears next month. `source_snapshot_date` says which snapshot a row is from.
- **Dissolved UK companies** are not in the UK file; they remain visible only through an LEI, if they had one.
- **LEI coverage** is what entities registered: most companies in the world have no LEI.
- **Name matching is lexical** (normalised names, Jaro-Winkler and token overlap): no transliteration, no trading names, no addresses. Check scores below 0.95.
- **`nace_rev2`** comes from the first UK SIC code only, and only for UK companies.
- **Speed of `search` and `match`.** A name that is spelled exactly like a registered name (after normalising case, accents, punctuation and legal suffixes) answers instantly; a name with a typo is compared against millions of names and takes a few seconds at the default 1 GB of memory (a list of 100 names takes about 1 to 6 minutes, depending on how many have typos). Rows are delivered and charged block by block, so a long run never loses what it has already done. For lists of several hundred names, split them into runs or raise the memory in the run options (CPU grows with memory).
- **Name matching uses the current legal name only** (not previous or trading names). The first letters must be right: the score is Jaro-Winkler on the normalised name, so a typo in the first characters lowers the score a lot. Ties on score go to the candidate with the same legal suffix as your name (Inc with Inc), then active entities, then entities with an LEI.
- **`changes`**: the feed starts when two consecutive snapshots of a source exist; `name` is the entity's current name and is empty if it left the source; with `countries`, entities that left the LEI file have no country and only show up without that filter.
- **No officers, owners, addresses or contacts**, by design.

### FAQ and support

**How fresh is the data?** LEI weekly, UK monthly; see `RUN_SUMMARY` and "Data last updated".

**Can I get everything?** Yes, here: `filter` returns up to 100,000 rows per run and you can narrow by country, status, industry, legal form and incorporation date to page through the registry. The free dataset on Hugging Face is only a ~100,000-entity sample; lookup, search, matching and the change feed are only here.

**Can I use it from an AI agent?** Yes, as an MCP tool. See "Use with AI agents (MCP)".

Found a problem or need another field? Use the Issues tab.

# Actor input Schema

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

What to do. `lookup`: return the entity for each ID in `ids` (UK company number, LEI or `entity_uid`). `search`: entities whose name is similar to each text in `names`, best first. `filter`: every entity that matches the filters below (at least one filter is required (it does not take a list of IDs: use `lookup` for that)). `match`: for each name in `names`, the single best candidate with `match_score`, or nothing if no candidate reaches `min_score`. `changes`: rows of the change feed since `changes_since`. Default: lookup.

## `ids` (type: `array`):

`lookup` only. UK company numbers (8 characters; `445790` is padded to `00445790`; Scottish `SC…`, Northern Irish `NI…`, LLP `OC…` and others as printed), LEIs (20 characters) or `entity_uid` values (`GB-CH:00445790`, `LEI:HWUPKR0MPOU8FGXBT394`). Up to 1,000 per run. An LEI linked to a UK company returns the UK row with the LEI filled in. IDs that are not found are listed in `RUN_SUMMARY.not_found` and are not charged. To get entities by criteria instead of by ID, use `filter` (which does not take a list of IDs).

## `names` (type: `array`):

`search` and `match` only. Company names as you have them (`Tesco plc`, `BP P.L.C.`, `apple inc`). Case, punctuation and common legal suffixes (Ltd, Limited, PLC, Inc, LLP, GmbH, SA…) are normalised before comparing. Up to 1,000 names per run.

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

Optional, every mode except `lookup`. Two-letter ISO country codes of the registry or jurisdiction (`GB`, `US`, `DE`…). For LEI records it is the country of the legal jurisdiction.

## `status` (type: `array`):

Optional, `search`, `match` and `filter`. `active`, `inactive`, `in_liquidation`, `in_administration`, `dissolved`, `unknown`. UK rows are live companies by definition (dissolved UK companies leave the source file).

## `nace_prefix` (type: `string`):

Optional, UK companies only. NACE Rev. 2 code or prefix, with or without the dot: `62` (computer programming and consultancy), `62.01`, `6201`. Derived from the company's first UK SIC 2007 code.

## `legal_form_elf` (type: `array`):

Optional. ISO 20275 Entity Legal Form codes, for example `H0PO` (UK private limited company). See the README for how UK company categories map to ELF codes.

## `incorporated_from` (type: `string`):

Optional. Only entities incorporated (created) on or after this date, YYYY-MM-DD.

## `incorporated_to` (type: `string`):

Optional. Only entities incorporated on or before this date, YYYY-MM-DD (inclusive).

## `only_with_lei` (type: `boolean`):

If true, return only entities that have an LEI. Default: false.

## `min_score` (type: `number`):

`search` and `match` only. Similarity between 0 and 1 (Jaro-Winkler on the normalised name, plus token overlap). Candidates below it are not returned and not charged. Default 0.9; 0.85 finds more, with more false positives.

## `search_limit` (type: `integer`):

`search` only. Maximum candidates returned per name, best first. Default 5.

## `changes_since` (type: `string`):

`changes` only. First week (YYYY-MM-DD; moved back to its Monday). Default: the latest week in the data.

## `change_types` (type: `array`):

`changes` only. Any of `new`, `removed_from_source`, `status_change`, `renamed`, `legal_form_change`, `industry_change`, `seat_city_change`, `lei_linked`, `lei_lapsed`. No value means all.

## `max_rows` (type: `integer`):

Maximum number of rows returned (1 to 100,000; default 1,000). Rows are charged one by one, so this is also your cost cap. If more rows match, the rest is not returned and `RUN_SUMMARY.capped_by_max_rows` is true. `filter` can return up to 100,000 rows per run, so the whole registry is reachable here; run it again with narrower filters (country, status, industry, incorporation date) to page through a bigger result.

## Actor input object example

```json
{
  "mode": "lookup",
  "ids": [
    "00445790",
    "HWUPKR0MPOU8FGXBT394"
  ],
  "names": [
    "Tesco plc"
  ],
  "countries": [
    "GB"
  ],
  "status": [
    "active"
  ],
  "nace_prefix": "62",
  "legal_form_elf": [
    "H0PO"
  ],
  "incorporated_from": "2026-01-01",
  "incorporated_to": "2026-09-30",
  "only_with_lei": false,
  "min_score": 0.9,
  "search_limit": 5,
  "changes_since": "2026-10-12",
  "change_types": [
    "new",
    "removed_from_source"
  ],
  "max_rows": 10
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset with the returned rows. The view that applies depends on the input field `mode`

## `files` (type: `string`):

Key-value store with RUN_SUMMARY

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

RUN_SUMMARY: mode, applied filters, rows returned and charged, IDs not found, snapshot dates of each source, data build date, and whether the maximum charge stopped the 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 = {
    "ids": [
        "00445790",
        "00102498",
        "HWUPKR0MPOU8FGXBT394"
    ],
    "max_rows": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("pracadata/company-registry-lookup").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 = {
    "ids": [
        "00445790",
        "00102498",
        "HWUPKR0MPOU8FGXBT394",
    ],
    "max_rows": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("pracadata/company-registry-lookup").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 '{
  "ids": [
    "00445790",
    "00102498",
    "HWUPKR0MPOU8FGXBT394"
  ],
  "max_rows": 10
}' |
apify call pracadata/company-registry-lookup --silent --output-dataset

```

## MCP server setup

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

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/KFkgWaywiHtbWxiO8/builds/0Khp31h7WYXBaS9zv/openapi.json
