# UK Companies House Scraper — Company Status, SIC & Address (`northbell/companies-house-search`) Actor

UK companies by name or company number from Companies House: status, type, incorporation date, registered office, SIC codes, accounts and confirmation deadlines. Run it again or on a schedule to see status and address changes since the last run. Companies only. No login.

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

## Pricing

from $0.80 / 1,000 companies

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?

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

## UK Companies House Scraper — Company Status, SIC & Address

Give it UK company names or company numbers and get one clean row per company from the Companies House register: **status, company type, incorporation date, registered office, SIC codes, previous names and the next accounts and confirmation-statement deadlines**. **$1.00 per 1,000 companies**, no login, no API key.

Run it again — or put it on a schedule — and every row also tells you **what changed since the last run**: `statusChanged` (for example `active` to `liquidation` or `dissolved`), a changed registered office, a changed name, a new proposal to strike off, and whether the company is new to your list. A company page shows only today's picture; this keeps the previous one for you.

### What you get

| Field | What it is |
|---|---|
| `companyNumber`, `name`, `url` | the company, with the link to its Companies House page |
| `status`, `statusDetail` | the register's status in lower case: `active`, `dissolved`, `liquidation`, `closed`, `converted / closed`, `registered`, `open`… and the extra line the company page can show next to it, for example `Active proposal to strike off` (`status` stays `active`, so a filter on it keeps working) |
| `companyType`, `incorporatedOn` | for example `Private limited Company`, `Public limited Company`, `Limited liability partnership`, `UK establishment`, and the date it was incorporated (or registered / opened) |
| `dissolvedOn` | the date shown for a company that is dissolved, closed, removed or converted |
| `registeredOffice` | the registered office address as one line |
| `sicCodes`, `primarySicCode` | the SIC codes with their descriptions, and the first code on its own |
| `previousNames` | earlier names with `from` and `to` dates |
| `accountsNextDue`, `accountsNextMadeUpTo`, `accountsLastMadeUpTo`, `accountsOverdue` | accounts deadline, the period they cover, the last period filed, and Companies House's own overdue warning |
| `confirmationNextDue`, `confirmationNextStatementDate`, `confirmationLastStatementDate`, `confirmationOverdue` | the same for the confirmation statement |
| `parentCompanyNumber` | for a UK establishment, the number of the overseas company it belongs to |
| `query`, `queryType`, `rank`, `matchedPreviousName` | which input line found it, `name` or `number`, its position in the search results, and the old name (or names, separated by `·`) that matched when the match was on a previous name |
| `isNew`, `firstSeenAt`, `previousObservedAt` | whether this company is new to your history, when you first saw it, and when you last read it |
| `previousStatus`, `statusChanged` | the status at your previous run, and `true` / `false` whether it changed (`null` on the first run) |
| `statusDetailChanged`, `previousStatusDetail` | `true` when the line next to the status appeared, disappeared or changed (for example a strike-off proposal starts); `previousStatusDetail` is the old line, `null` if there was none |
| `nameChanged`, `previousName`, `registeredOfficeChanged`, `previousRegisteredOffice` | the same for the name and the registered office; the previous value is filled only when it changed |
| `detailsRead`, `observedAt` | whether the company page was read, and when the row was collected |

### Run it again and again

- **On a schedule** — save your input as a task and add a **Schedule**: the same companies every week. Send each run to Google Sheets, Slack or email with an integration on the task.
- **Watch for changes** — Keep the same input on the schedule. Each run is its own dataset with the date it ran, so the series builds up run by run and you can compare one day with the last.
- **In bulk** — Put every name or company number in **Company names or numbers** in one run.

### Use it for

- **Supplier and customer watchlists** — schedule it daily and filter on `statusChanged` and `statusDetailChanged` to catch a company going into liquidation, being dissolved or being put forward for strike-off
- **Cleaning a company list** — turn names from a CRM or spreadsheet into company numbers, registered offices, types and status
- **Due-diligence prep** — SIC codes, age, previous names and overdue accounts or confirmation statements in one table
- **Prospecting** — filter by SIC code, company type, incorporation date or location in the address, then export to Sheets, your CRM or BI tool

### Input

```json
{ "queries": ["Tesco PLC", "Monzo", "00445790", "SC045551"], "maxResultsPerQuery": 20, "includeDetails": true }
```

- **Company names** return up to `maxResultsPerQuery` companies, in Companies House's own search order.
- **Company numbers** (`00445790`, `SC045551`, `OC300001`, also `445790` without the leading zeros) return exactly that company.
- Up to 200 lines per run.
- **includeDetails** on (default) opens every company's page for SIC codes, type, previous names and deadlines. Off, the run is much faster and keeps only what the search list shows.

Changes are remembered per company number in a named key-value store in your Apify account, so the second run of the same Actor already shows what changed. Schedule it (Apify → Schedules) for a daily check.

### Pricing

**$1.00 per 1,000 companies**, plus $0.01 per run. Error rows (a number that does not exist, a name with no results) are free. A row whose company page could not be read (`detailsRead: false`) is free too. The $0.01 run-start fee is the one charge every run pays, even one that returns nothing.

### Notes

- **Companies only.** The Actor reads the public company overview and the search list. It does not read or output officers, directors, persons with significant control or any other people.
- **Addresses are as registered.** `registeredOffice` is the address on the register. For a very small company or a sole trader this can be a private address; Companies House publishes it and the Actor returns it unchanged.
- **The search is Companies House's own and it is loose.** It also matches previous names and near-misses, so check `name` and `rank`. When the match was on an old name, `matchedPreviousName` shows which one.
- **Status wording.** With *Read each company page* on, `status` is the text on the company page and `statusDetail` is the line next to it, if any (so far seen: `Active proposal to strike off`; it is `null` for most companies). With it off, `status` comes from the search list, which shows the main states only: **the list does not show a proposal to strike off, so such a company shows as plain `active` with `statusDetail: null`** — leave *Read each company page* on when you watch for that. A few kinds of entry (some overseas companies and UK establishments) have `status: null` in list-only mode. The list also shows no incorporation date for dissolved companies. Switching between the two modes between runs does not create false changes: `statusDetailChanged` is `null` unless both runs read the company page.
- **Fields filled only in some cases.** `companyType`, `sicCodes`, `previousNames` and the accounts and confirmation fields are `null` unless the company page was read. When it was read, `sicCodes` and `previousNames` are `[]` if the page lists none, which is common for UK establishments, overseas companies, limited partnerships, LLPs and societies. The accounts and confirmation dates and their overdue flags are `null` when the page has no such block. `parentCompanyNumber` is only filled for UK establishments. `matchedPreviousName` is only filled when a name search matched an old name. `previousName` and `previousRegisteredOffice` are only filled when that value changed. Some entry types have no registered office on the register and some no status: registered and provident societies, Royal Charter companies and charitable incorporated organisations. LLPs, overseas entities, UK establishments and overseas companies have no SIC codes on their page.
- **Speed.** Requests go one at a time with short pauses. Measured on 9 Oct 2026 from a desktop PC: about 125 companies took about 10 seconds in list-only mode and 127 companies about 100 seconds with company pages read (roughly 0.8 seconds each), so a run of 1,000 companies with pages takes about 14 minutes. Raise the run timeout for big lists.
- **Dates.** `incorporatedOn` is the date the register labels incorporated, registered, formed or opened; `dissolvedOn` is the date it labels dissolved, closed, removed or converted. All dates are ISO (`YYYY-MM-DD`).
- **One row per company per run.** If the same company is found by two lines of your input it appears once, under the first.
- The data is what the register shows at `observedAt`. It is not legal advice and not an official certificate.

More company data from northbell: [Company Lookup by Domain](https://apify.com/northbell/company-lookup-by-domain), [LinkedIn Company Growth Scraper](https://apify.com/northbell/linkedin-company-growth-scraper), [LEI / GLEIF Lookup](https://apify.com/northbell/lei-gleif-lookup).

### For AI agents

`{"queries": ["Tesco PLC"], "maxResultsPerQuery": 3}` returns up to 3 rows with status, type, registered office and SIC codes. `{"queries": ["00445790"]}` returns that one company. Rows have `type`: `company` or `error`. To monitor, run the same input on a schedule and read `statusChanged` and `statusDetailChanged`.

# Actor input Schema

## `queries` (type: `array`):

One per line. A company name (Companies House search, which also matches previous names) or a company number such as 00445790, SC045551 or OC300001. A number reads that exact company; leading zeros are added if a spreadsheet dropped them.

## `maxResultsPerQuery` (type: `integer`):

How many search results to return for each company name, in Companies House's own order (20 per page). Does not apply to company numbers, which always return one company. Raise it to list every company with a similar name.

## `includeDetails` (type: `boolean`):

On (default): opens every company's page to add SIC codes, company type, previous names, accounts and confirmation-statement deadlines, and any status detail such as a proposal to strike off. Off: much faster, but keeps only what the search list shows (name, number, status in its short form, dates, registered office); the list does not show a strike-off proposal.

## Actor input object example

```json
{
  "queries": [
    "Tesco PLC"
  ],
  "maxResultsPerQuery": 20,
  "includeDetails": true
}
```

# Actor output Schema

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

Status, company type, incorporation date, registered office, SIC codes, filing deadlines and status changes since the last 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 = {
    "queries": [
        "Tesco PLC"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("northbell/companies-house-search").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 = { "queries": ["Tesco PLC"] }

# Run the Actor and wait for it to finish
run = client.actor("northbell/companies-house-search").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 '{
  "queries": [
    "Tesco PLC"
  ]
}' |
apify call northbell/companies-house-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,northbell/companies-house-search"
        }
    }
}
```

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/7DzsULt2ovAZeRNDh/builds/EtkUWQ8e8I8r27L8E/openapi.json
