# Companies House Scraper - UK Company Data, Bulk Lookup, SIC (`neverempty/companies-house-scraper`) Actor

For KYB checks, B2B prospecting and credit teams: the whole official UK register, 5,689,367 companies in the 2026-09-01 snapshot, of which 5,171,600 are Active. Look up 50,000 company numbers per run or filter by SIC code, postcode, town and status. Official OGL data, no API key.

- **URL**: https://apify.com/neverempty/companies-house-scraper.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Lead generation, Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.11 / 1,000 company returneds

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Companies House Scraper - UK Company Data, Bulk Lookup, SIC

**For B2B lead lists, KYC and onboarding checks, credit risk and UK market sizing**: look up UK companies by **company number in bulk** (up to **50,000** per run), or find them by **SIC code (industry), registered office postcode, post town, name, status, company type and incorporation date**, from the official **Companies House Free Company Data Product**.

**The whole live UK register, counted.** The 2026-09-01 snapshot holds **5,689,367 companies** (read 2026-09-11, all 7 files): Active **5,171,600** · Active - Proposal to Strike off **401,947** · Liquidation **108,494** · In Administration **3,742**. By type: Private Limited Company **5,261,979** · Limited Partnership **61,003** · LLP **50,333** · Community Interest Company **44,829** · Overseas Entity **30,184** · PLC **4,506**. The default input returned **100 companies in 5 s**.

**It tells you where the register itself is empty**, instead of handing you blanks to guess at. **60,933** companies across nine company types have no registered office address at all in this data, and **231,523** carry "None Supplied" as their industry (`sicNoneSupplied: true`) — so a filter that returns nothing is never confused with an industry nobody recorded. Leading zeros a spreadsheet dropped are put back (`445790` → `00445790`).

One row per company: company number, name, status, company type, incorporation date, registered office address, SIC codes with descriptions, accounts category, next accounts and confirmation statement due dates (and whether they were overdue at the snapshot), mortgage charges, partners of limited partnerships, up to 10 previous names, and a link to the company's page on the live register.

No API key. No login. Companies House's own guidance says its search service is not meant for bulk downloads; this Actor reads the bulk snapshot Companies House publishes for exactly that purpose. Export as JSON, CSV or Excel.

### How fresh is the data?

This is a **monthly snapshot, not live data**. Companies House says the snapshot "is compiled up to the end of the previous month" and is updated "within 5 working days of the previous month end".

- The snapshot read on 2026-09-11 is dated **2026-09-01** and holds companies up to **31 August 2026** (the newest incorporation date in it is 31/08/2026; its files were last modified on 7 September 2026).
- Every row carries `snapshotDate` and `dataCompiledUpTo`, so you always know which month you are looking at.
- A company incorporated, renamed or struck off after that date is not reflected until the next snapshot. For a company's status today, open its `companiesHouseUrl`.

### What is (and is not) in the data

Measured on the 2026-09-01 snapshot (all 7 files read, 5,689,367 companies):

- **Only live companies.** No row has a dissolution date and no status is "Dissolved". Statuses: Active 5,171,600 · Active - Proposal to Strike off 401,947 · Liquidation 108,494 · In Administration 3,742 · Live but Receiver Manager on at least one charge 2,137 · Voluntary Arrangement 577 · smaller administration and receivership statuses. A dissolved company's number is reported as `not-in-snapshot` (free), never as a company.
- Company types include Private Limited Company 5,261,979 · Limited Partnership 61,003 · Limited Liability Partnership 50,333 · Community Interest Company 44,829 · Overseas Entity 30,184 · Public Limited Company 4,506.
- **Not in this data:** directors and officers, persons with significant control (owners), filing history, accounts figures (turnover, profit), email, phone and website. This Actor does not return them and does not guess them.
- **Nine company types have no registered office address at all in this data** (60,933 companies: Charitable Incorporated Organisation 40,416, Registered Society 10,811, Scottish Charitable Incorporated Organisation 7,923, Royal Charter Company 909, Investment Company with Variable Capital 712 in three kinds, Industrial and Provident Society 159, Protected Cell Company 3). A postcode or town filter can never match them. When you combine a postcode or town filter with one of these company types and nothing matches, the no-results row says so. Search them by type, name, SIC or date instead.
- 231,523 companies have "None Supplied" as their industry (`sicNoneSupplied: true`). Some older companies still carry 4-digit SIC 2003 codes; those are kept in `sicOtherText` and are not matched by the SIC filter.

### Input

| Field | What it does |
|---|---|
| `companyNumbers` | Company numbers to look up in bulk (up to 50,000 per run), e.g. `00445790`, `SC117120`, `IP10067R`. Leading zeros dropped by a spreadsheet are put back (`445790` → `00445790`, `SC5336` → `SC005336`). When numbers are given, the search fields are not used. Rows come back in the order you gave. |
| `name` | Words of the company name. Every word must start a word of the name (`tesc` finds TESCO); case and accents are ignored; LTD / LIMITED are left out of the comparison. |
| `includePreviousNames` | Also match former names (up to 10 per company). The former name that matched is in `matchedPreviousName`. |
| `sicCodes` | SIC 2007 codes or their first digits: `62020`, `6201`, `62` (all of division 62). A company matches when any of its SIC codes starts with one of these. |
| `postcodes` | Registered office postcodes: full (`SW1A 1AA`), sector (`SW1A 1`), district (`EC1V`, `M1`) or area (`M`, `EC`). A district ending in a digit also takes its lettered sub-districts: `EC1` = EC1A-EC1Y and `SW1` = SW1A-SW1Y, but **not** SW10-SW19. An area is exactly those letters: `M` is Manchester, not ME or MK. |
| `towns` | Post towns as written in the register (`LONDON`, `MANCHESTER`). A town written with a county (`HARLOW, ESSEX`) also matches `HARLOW`. |
| `companyStatuses` | Keep only these statuses (all live). |
| `companyTypes` | Keep only these company types, as Companies House writes them. |
| `incorporatedFrom` | Earliest incorporation date, `YYYY-MM-DD`. |
| `incorporatedTo` | Latest incorporation date, `YYYY-MM-DD`. |
| `sortBy` | `name` (the order of the register; stops as soon as enough companies are found), `newest` or `oldest` incorporated first (reads the whole snapshot, then returns the first companies in that order). |
| `maxResults` | The most companies a search returns (1-50,000, default 100). Not used for number lookups. |

A field left empty (a blank name, an empty list, a list of blanks) counts as not given. Without a company number and without any search field:

- **With no input at all** (or with nothing but the default Order, Maximum companies and previous-names settings, which Apify fills in when they are left out), the Actor runs an example search: SIC 62020 IT consultancy with a registered office in postcode district EC1V, 100 companies. Every row's `query` says it was the example search.
- **If you changed Order or Maximum companies**, it returns all live companies in that order and number, and `query` says "all live companies". For example `{ "sortBy": "newest", "maxResults": 500 }` returns the 500 most recently incorporated live companies.
- **Anything else** (for example `{ "companyNumbers": [] }`, a blank name, or a list left with an empty line) is not searched: one free `bad-input` row asks for a company number or a search field, and nothing is charged.

⚠️ In the Apify input form, deleting the example values (SIC 62020, EC1V) item by item, or with "Remove empty fields", removes those fields from the input altogether. The input is then the same as no input at all, so **the example search runs and its 100 companies are charged**. To search something else, type your own values in place of the examples.

Examples:

```json
{ "companyNumbers": ["00445790", "SC117120", "02557590"] }
```

```json
{ "sicCodes": ["41202"], "incorporatedFrom": "2026-08-01", "sortBy": "newest", "maxResults": 500 }
```

```json
{ "postcodes": ["M"], "companyStatuses": ["Liquidation"], "maxResults": 10000 }
```

```json
{ "name": "octopus energy", "includePreviousNames": true }
```

### Output

| Field | Meaning |
|---|---|
| `status` | `ok` for a company. Other values are free explanation rows (below). |
| `companyNumber`, `companyName` | Registration number (8 characters) and registered name. |
| `companyStatus`, `companyType` | As published by Companies House. |
| `incorporationDate` | `YYYY-MM-DD`. |
| `countryOfOrigin` | United Kingdom, or the home country of an overseas entity. |
| `registeredOfficeAddress` | The registered office in one line, plus `addressLine1`, `addressLine2`, `postTown`, `county`, `country`, `postcode`, `poBox`. `postcode` is written as the register writes it. The postcode filter also matches the 189 postcodes registered with a space in the wrong place or a trailing mark (`SW1 W 0LS`, `EC1 V2NX`, `BT 45 8LX`, `EC1V 2 NX`, `N4 1DY.`), for UK addresses and for Isle of Man, Jersey, Guernsey and Gibraltar addresses with their own letters (`IM1 1 AG`). A postcode with a character missing (`TN11 QU`), with a space between two digits of its district (`SW7 11ER`: SW7 or SW71?) or of another country is not guessed at and matches no postcode filter. |
| `careOfWithheld` | `true` when the register names who the post goes to: a care-of name, or an address field that contains "C/O", "CARE OF", "FAO", "ATTN", "ATTENTION" or another spelling of them, anywhere, read ignoring the marks and spaces between the letters ("C/-", "C\O", "C./O", "C//O", "CO/", "C-O", "FOA", "FTAO", "F.A .O", "ATT:" or "ATT-" or "ATT" before a name, "%" between spaces, and "C/O" glued to the next word). For example `WEWORK C/O LUISA NASCIMENTO`, `FAO ROB HAYES, ...`, `ATTN: THE MANAGER`, `C/- MR PAUL COLES`. "ATT" before a number or a building word (`ATT HOUSE FARM`, `THE ARCHIVE, ATT 520`) is kept as an address. That name is not returned, and neither is any field that holds such a marker (it is `null`). 25,029 companies have a care-of name, and 162,955 address fields carry such a marker (158,061 first lines, 4,754 second lines, 98 PO boxes, 27 counties, 15 post towns); 187,882 companies have `careOfWithheld: true`. Many of these are people's names. **A withheld field is withheld whole**, so a building or street written in the same field goes with it (`BRIDGEWATER HOUSE C/- APAM LTD` loses BRIDGEWATER HOUSE); 1,992 companies are left with no street line at all, only post town, county and postcode. |
| `sicCodes`, `sicDescriptions` | SIC 2007 codes and their descriptions (up to 5; one company in the register has 5 although the published layout says 4). |
| `sicOtherText`, `sicNoneSupplied` | Older SIC 2003 entries; "None Supplied". |
| `accountsCategory`, `accountingReferenceDay`, `accountingReferenceMonth`, `accountsNextDueDate`, `accountsLastMadeUpDate` | Accounts details. |
| `confirmationStatementNextDueDate`, `confirmationStatementLastMadeUpDate` | Confirmation statement dates. |
| `accountsOverdueAtSnapshot`, `confirmationStatementOverdueAtSnapshot` | `true` when the next due date is before `dataCompiledUpTo`; `null` when there is no due date. |
| `mortgageChargesTotal`, `mortgageChargesOutstanding`, `mortgageChargesPartSatisfied`, `mortgageChargesSatisfied` | Charges registered against the company. |
| `generalPartners`, `limitedPartners` | Limited partnerships only; `null` for every other type (never a made-up 0). |
| `previousNameCount`, `previousNames`, `matchedPreviousName` | Former names with the date each changed. |
| `companiesHouseUrl`, `dataUri` | The live register page and the URI published in the data. |
| `snapshotDate`, `dataCompiledUpTo`, `sourceFile` | Which snapshot and file the row came from. |
| `input`, `query`, `checkedAt`, `source`, `note` | What was asked, when, and from where. |

Explanation rows (never charged): `bad-input` (the input was rejected or gave nothing to search, not "no such company"), `not-in-snapshot` (a valid-looking number that is not among the live companies of this snapshot), `no-results` (the whole snapshot was read and nothing matched), `failed` (a file could not be read — nothing is reported as "not found" from a partial read), `incomplete` (some companies were returned, but part of the snapshot could not be read), `duplicate-input`, `not-looked-up` (over the per-run limit of numbers, or the run reached its maximum total charge before every company it found or searched for was delivered), `filters-ignored` (numbers and search fields were both given).

### How it works, and what it handles that simpler tools get wrong

- It reads the official bulk files while they download (7 zipped CSVs, 469 MB compressed, about 2.9 GB of CSV) instead of querying the search site one company at a time.
- **How long a run takes** (measured on Apify with the default 1 GB of memory on 2026-09-11): the default input returned 100 companies in 5 s, because a search in name order stops as soon as enough companies are found early in the register. A search whose matches are spread through the register, or rare, reads most or all of it: `{ "name": "tesco" }` took 185 s. Anything that needs the whole snapshot takes 3 to 6 minutes: 6 company numbers 190 s, 50,000 company numbers 277 s, Active companies newest first, 50,000 of them, 337 s. The most memory any measured run used was 620 MB (postcode district TN1, 2,566 companies; all live companies newest first, 50,000 of them, used 565 MB).
- A run whose timeout is shorter than a full read needs stops a minute before its limit and says which part of the snapshot was not searched, and that a longer timeout is needed. The default timeout is 1 hour.
- A download that breaks is resumed from the byte where it stopped, and only if the file is still the same version. If a file cannot be read, the run says exactly which part of the alphabet was not searched; it never reports a company as "not found" from a partial read, and never sorts a partial list.
- The CSV has real-world quirks that break naive parsers: a company record broken over two lines, names with escaped quotes (`"ONE BRITAIN ONE NATION" OBON COMMUNITY INTEREST COMPANY`), and one company with five SIC codes where the layout promises four. Each record is checked (number and URI must agree) before it is returned.
- Company numbers are not always "prefix + digits": 5,819 societies have numbers like `IP10067R` or `SP1847RS`. They are looked up as written.
- Postcode filters do what a person means: `SW1` does not include `SW10`-`SW19`, `M` does not include `ME` or `MK`, and `EC1` includes `EC1A`-`EC1Y`.
- Each company is returned and charged once per run. If the run reaches the maximum total charge you set before it has delivered what you asked for, a free `not-looked-up` row says so.

### Licence and attribution

Source: Companies House Free Company Data Product. Contains Companies House data.

Companies House's statement [Our public task, copyright and Crown copyright](https://www.gov.uk/government/publications/companies-house-accreditation-to-information-fair-traders-scheme/public-task-copyright-and-crown-copyright) says that material produced by Companies House is subject to Crown copyright and is made available under the [Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/) except where otherwise stated, that users "must credit Companies House as the source of the information", and that they "cannot reproduce the Crown insignia". Its [data products page](https://www.gov.uk/guidance/companies-house-data-products) says: "We impose no rules or requirements on how the information on the public register is used", and also: "You are responsible for complying with any applicable data protection, copyright and other legislation and regulations." Registered office addresses can be home addresses of individuals, so data protection law can apply to how you use these rows. When you publish these rows, credit Companies House as the source. This Actor is not affiliated with or endorsed by Companies House.

The registered office address is the address a company must publish on the public register. For many small companies it is an accountant's or formation agent's address, and for some it is a home address; that is how the register publishes it.

### Pricing

You pay per company returned. Explanation rows (rejected inputs, numbers not in the snapshot, failures, notes) are free.

### Support

Found a problem or need another field? Open an issue on the Issues tab and include the run ID.

# Actor input Schema

## `companyNumbers` (type: `array`):

Companies House registration numbers to look up in bulk, up to 50,000 per run, for example 00445790 (Tesco PLC), SC117120 or IP10067R. A number whose leading zeros were dropped by a spreadsheet (445790) is read as 00445790, and SC5336 as SC005336. When numbers are given, the search fields below are not used. The snapshot holds only live companies, so a dissolved company is reported as not in the snapshot (not charged).

## `name` (type: `string`):

Words of the company name, for example octopus energy. Every word must start a word of the name (tesc finds TESCO), case and accents are ignored, and LTD / LIMITED are left out of the comparison.

## `includePreviousNames` (type: `boolean`):

Also return companies whose former name (up to 10 kept in the register) matches the name words. The matching former name is in matchedPreviousName.

## `sicCodes` (type: `array`):

SIC 2007 codes or their first digits, for example 62020 (IT consultancy), 6201 or 62 (all of division 62), 41202 or 43. A company matches when any of its SIC codes starts with one of these. Old 4-digit SIC 2003 codes that some companies still carry are returned in sicOtherText but are not matched.

## `postcodes` (type: `array`):

Full postcodes (SW1A 1AA), sectors (SW1A 1), districts (EC1V, M1) or areas (M, EC). A district ending in a digit also takes its lettered sub-districts: EC1 means EC1A to EC1Y and SW1 means SW1A to SW1Y, but not SW10 to SW19. An area means exactly those letters: M is Manchester, not ME or MK.

## `towns` (type: `array`):

Post towns of the registered office as written in the register, for example LONDON, MANCHESTER, HARLOW. Case is ignored, and a town written with a county (HARLOW, ESSEX) also matches HARLOW.

## `companyStatuses` (type: `array`):

Keep only these statuses. The snapshot holds only live companies, so every status here is a live one; dissolved companies are not in the data.

## `companyTypes` (type: `array`):

Keep only these company types, as Companies House writes them.

## `incorporatedFrom` (type: `string`):

Earliest incorporation date, written YYYY-MM-DD, for example 2026-08-01.

## `incorporatedTo` (type: `string`):

Latest incorporation date, written YYYY-MM-DD.

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

Name order is the order of the register and stops as soon as enough companies are found. Newest or oldest incorporated first reads the whole snapshot (3 to 6 minutes with the default memory) and then returns the first companies in that order.

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

The most companies a search returns, up to 50,000. Not used for company number lookups (every number found is returned).

## Actor input object example

```json
{
  "includePreviousNames": false,
  "sicCodes": [
    "62020"
  ],
  "postcodes": [
    "EC1V"
  ],
  "sortBy": "name",
  "maxResults": 100
}
```

# Actor output Schema

## `results` (type: `string`):

One row per company, plus one free row for each input that was rejected, not in the snapshot, not searched, or could not be read.

# 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 = {
    "sicCodes": [
        "62020"
    ],
    "postcodes": [
        "EC1V"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/companies-house-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 = {
    "sicCodes": ["62020"],
    "postcodes": ["EC1V"],
}

# Run the Actor and wait for it to finish
run = client.actor("neverempty/companies-house-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 '{
  "sicCodes": [
    "62020"
  ],
  "postcodes": [
    "EC1V"
  ]
}' |
apify call neverempty/companies-house-scraper --silent --output-dataset

```

## MCP server setup

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