# UK Companies House Scraper (`axiomworks/uk-companies-house-scraper`) Actor

Extract UK Companies House company data by name search, company number or profile URL: name, number, status, type, incorporation date, registered address, SIC codes, previous names and officers with roles and appointment dates. Filter by status or SIC. No login.

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

## Pricing

from $1.79 / 1,000 results

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

**Returns:** one row per company with companyName, companyNumber, status, type, incorporatedOn, registeredAddress, sicCodes, officers, previousNames, and sourceUrl.
**Input:** `{"searchQueries":["tesco"],"maxItems":5}`
**Best for:** company verification, targeted company lists, and checking historical registered names.

```json
{"id":"00445790","companyName":"TESCO PLC","companyNumber":"00445790","status":"Active","type":"Public limited Company","incorporatedOn":"27 November 1947","incorporatedOnIso":"1947-11-27","registeredAddress":"Tesco House, Shire Park, Kestrel Way, Welwyn Garden City, United Kingdom, AL7 1GA","sicCodes":["47110 - Retail sale in non-specialised stores with food, beverages or tobacco predominating"],"officers":[{"name":"TAYLOR, Christopher Jon","role":"Secretary","status":"Active","appointedOn":"14 April 2025","appointedOnIso":"2025-04-14"}],"officerCount":74,"previousNames":[{"name":"TESCO STORES (HOLDINGS) LIMITED","period":"27 Nov 1947 - 14 Dec 1981"}],"sourceUrl":"https://find-and-update.company-information.service.gov.uk/company/00445790"}
```

Collect public UK company search results and company profiles from the Companies House Find and Update service. Supply company name searches, exact company numbers, or both. Each result represents one company, identified by its Companies House number. The Actor can also collect the public officer appointment list linked from each profile. It uses the public website and does not require a Companies House login.

### What does UK Companies House Scraper do?

UK Companies House Scraper searches the public company register by keyword or opens known company numbers directly. It reads the company overview page for the registered name, company number, current status, legal type, incorporation date, registered office address, and SIC descriptions. When officer collection is enabled, it visits the officers tab and follows its page links until the available appointment pages have been read. It returns a structured company record in the run's default dataset.

A name search can match the current name or a previous name. The Actor returns the current registered name from the company profile, so a match may not contain the keyword you searched. This distinction matters when reviewing historical names or checking whether a company changed its name. A company number is a more precise input because the number is the stable register identifier. If both input lists are supplied, exact company numbers are processed first, then search results.

The Actor reads public website pages without a login and is not affiliated with Companies House. Each record includes its profile URL. Register content changes over time, so later runs may show new details.

### What data can you get?

| Field | Meaning |
| --- | --- |
| `id` | Stable company number used as the record identifier. |
| `companyName` | Current registered company name on the profile. |
| `companyNumber` | Companies House number, including leading zeroes or letter prefixes. |
| `status` | Status shown on the company overview, such as Active or Dissolved. |
| `type` | Company type as shown on the overview, when available. |
| `incorporatedOn` | Human-readable incorporation date from the overview, when available. |
| `incorporatedOnIso` | The same date in `YYYY-MM-DD` format when it can be parsed. |
| `registeredAddress` | Registered office address shown on the overview, when available. |
| `sicCodes` | SIC activity code descriptions listed on the overview. |
| `pscs` | Persons with significant control (name, status, notified and ceased dates, nature of control), only when `includePscs` is true. |
| `pscCount` | Active PSC count reported by the register, only when `includePscs` is true. |
| `officers` | Public officer appointment entries when `includeOfficers` is true. |
| `officerCount` | Number of officer appointments reported on the officers page, when collected. |
| `previousNames` | Earlier registered names with the displayed period plus ISO `from` and `to` dates. |
| `nextAccountsMadeUpTo` | Period end date of the next accounts, ISO date. |
| `nextAccountsDueBy` | Filing deadline for the next accounts, ISO date. |
| `lastAccountsMadeUpTo` | Period end date of the last filed accounts, ISO date. |
| `nextConfirmationStatementDate` | Next confirmation statement date, ISO date. |
| `confirmationStatementDueBy` | Filing deadline for the next confirmation statement, ISO date. |
| `lastConfirmationStatementDate` | Date of the last confirmation statement, ISO date. |
| `dissolvedOn` | Dissolution date for dissolved companies, ISO date; null otherwise. |
| `correspondenceAddress`, `overseasAddress` | Overseas entities only: UK correspondence address and the address in the place of incorporation; null for other company types. |
| `incorporatedIn`, `registrationNumber`, `legalForm`, `parentRegistry` | Overseas companies and entities only: home country, home registry number (null when the register shows N/A), legal form and parent registry; null otherwise. |
| `sourceUrl` | URL of the company profile that supplied the record. |

Each officer entry can include a name, role, status, appointment date, resignation date, nationality, month and year of birth, and country of residence. Some values are absent from the public page, so those properties can be `null`. Officer entries are nested inside the parent company record. The run's item limit counts companies, not the number of officers contained in a company. When officer collection is disabled, `officers` is an empty array and `officerCount` is `null`.

Some company types do not publish every field. For example, a branch entry can have an address and status while lacking an incorporation date or SIC codes. In those cases, optional text fields are `null` and `sicCodes` is an empty array. The Actor does not invent values to fill gaps. `sourceUrl` and `id` remain available for every returned company.

### How to use

Open the Actor input form and enter search terms in `searchQueries`, exact eight-character identifiers in `companyNumbers`, or public profile links in `companyUrls`. Set `maxItems` to the maximum number of company records needed. Leave `includeOfficers` enabled if appointments are part of your workflow. Run the Actor and read the resulting dataset. The dataset can be downloaded in the formats offered by Apify or accessed through the API.

For an exploratory search, start with a short, distinctive company name and a small item limit. Search results can include current names and matches on historical names, so inspect `companyName` and `companyNumber` before treating a result as the organization you intended. If you already know the number, use `companyNumbers` to avoid ambiguity. Multiple searches can find the same company; the Actor keeps one record per company number within a run.

The scraper makes sequential requests at least one second apart. It applies status and SIC filters before fetching officers, avoiding officer-page requests for excluded companies. Officer pagination can extend a run. The run stops at `maxItems`. Empty searches return zero items with a warning. Missing profiles are skipped, never inserted as error records.

### Input

| Field | Type | Default | How to use it |
| --- | --- | --- | --- |
| `searchQueries` | Array of strings | Empty | Company names or keywords to search. Supply this or `companyNumbers`. |
| `companyNumbers` | Array of strings | Empty | Exact eight-character Companies House numbers. Supply this or `searchQueries`. |
| `companyUrls` | Array of strings | Empty | Public Companies House company profile URLs; can be mixed with numbers and searches. |
| `statuses` | Array of strings | Empty | Keep profiles with an exact status match, ignoring case. |
| `sicCodePrefixes` | Array of strings | Empty | Keep profiles with a SIC code starting with any supplied numeric prefix. |
| `includeOfficers` | Boolean | `true` | Read every available public officers page for each company. |
| `includePscs` | Boolean | `false` | Also read the persons-with-significant-control pages and add `pscs` and `pscCount` to each company. |
| `maxItems` | Integer | `50` | Maximum company records to return, from 1 to 10000. |
| `proxyConfiguration` | Proxy settings | Proxy off | Configure Apify Proxy for site requests. The Actor also attempts a proxy fallback after a block response. |

The console prefill shows `tesco` as an example search and a small item limit. Prefill values help demonstrate the form; API callers should supply their own search terms, numbers, or URLs. At least one target list must have a nonempty value. Company numbers must have eight letters or digits. Leading zeroes matter, so pass identifiers as strings rather than JSON numbers. Filters apply to both direct lookups and search results; an empty filter includes all values.

```json
{
  "searchQueries": ["tesco"],
  "includeOfficers": true,
  "maxItems": 5,
  "proxyConfiguration": { "useApifyProxy": false }
}
```

To retrieve known companies, replace `searchQueries` with `companyNumbers`, for example `"companyNumbers": ["00445790", "09384423"]`. You can provide both lists in one run. Exact numbers are handled first, while duplicates found later in search results are ignored. A small `maxItems` can therefore fill entirely from the exact number list.

You may also paste a profile link in `companyUrls`. For an active retail list, use `"statuses": ["Active"]` and `"sicCodePrefixes": ["47"]` with a relevant search term. The Actor checks these filters against the profile it actually opens. It reads subsequent search pages until it has enough matching companies, finds no new results, or reaches the page guard. Each accepted company still uses one dataset row.

### Output

The following example is based on a public profile observed during development. Register details can change, and a fresh run may return different officer entries. The shortened `officers` array illustrates the nested shape; the Actor returns all parsed entries from available officer pages when enabled.

```json
{
  "id": "00445790",
  "companyName": "TESCO PLC",
  "companyNumber": "00445790",
  "status": "Active",
  "type": "Public limited Company",
  "incorporatedOn": "27 November 1947",
  "incorporatedOnIso": "1947-11-27",
  "registeredAddress": "Tesco House, Shire Park, Kestrel Way, Welwyn Garden City, United Kingdom, AL7 1GA",
  "sicCodes": ["47110 - Retail sale in non-specialised stores with food, beverages or tobacco predominating"],
  "officers": [
    {
      "name": "TAYLOR, Christopher Jon",
      "role": "Secretary",
      "status": "Active",
      "appointedOn": "14 April 2025",
      "resignedOn": null,
      "nationality": null,
      "dateOfBirth": null,
      "countryOfResidence": null
    }
  ],
  "officerCount": 74,
  "previousNames": [{"name": "TESCO STORES (HOLDINGS) LIMITED", "period": "27 Nov 1947 - 14 Dec 1981", "from": "1947-11-27", "to": "1981-12-14"}],
  "sourceUrl": "https://find-and-update.company-information.service.gov.uk/company/00445790"
}
```

A company number provides a stable record key across runs. The `id` and `companyNumber` fields are intentionally equal. The company profile is the source for top-level details, and the linked officers pages supply the nested appointments. `officerCount` reflects the count displayed by the officers page, while the `officers` array contains the appointment entries parsed from its available pages. These values can differ if the site changes while a run is in progress.

For verification workflows, an advanced hidden input named `__verifySnapshots` can save source text for the first ten returned records under the `SNAPSHOTS` key in the default key-value store. It is intended for checking extracted fields against the public pages. Ordinary users can rely on the record's `sourceUrl` and need not enable snapshots.

### How much does it cost?

This Actor is charged per result added to the dataset. A company that appears in more than one search is pushed once, so duplicates within a run do not create additional result events. `maxItems` is the upper bound on company result events for a run. A run with no matching companies pushes no result records. For the current charging details, see the Actor's Pricing tab on Apify. The Pricing tab is the source for current terms because they can change.

The `includeOfficers` setting affects how many public pages the Actor visits, but officer entries are part of a company result rather than separate dataset rows. An officer list with many pages can increase run duration. Set the item limit to the number of company profiles you actually need and disable officer collection when your work only needs profile facts.

### Use with AI agents (MCP)

Apify's MCP server can expose this Actor as a tool to an AI agent. Configure a server with the Actor's Store path in the `tools` parameter:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?tools=axiomworks/uk-companies-house-scraper"
    }
  }
}
```

An agent can then run a company name search and inspect the structured output. Give the agent an exact company number when you have one, and ask it to cite `sourceUrl` when using the result in a report. Useful prompts include “Find up to five companies matching Tesco and show their company numbers and statuses” and “Retrieve company 00445790 with officers and summarize the registered address and SIC description.” The agent should treat a name search as candidate discovery, since matches on previous names may have a different current name.

The first input fields are the search targets, followed by the options agents most often need. The descriptions explain what values to provide and the item limit. An agent calling the Actor through an API must pass at least one target list; console prefill examples are not automatically submitted by every integration. A result is evidence from the public page at run time, not a permanent statement about the company.

### Integrations and API

Apify provides clients and an HTTP API for starting an Actor run and reading its dataset. Replace the example API token placeholder with a token managed by your own environment. Never put a real token into shared source code or reports. The examples below show the input shape; adapt the response handling to your application.

Python example:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("axiomworks/uk-companies-house-scraper").call(run_input={
    "companyNumbers": ["00445790"],
    "includeOfficers": True,
    "maxItems": 1,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["companyNumber"], item["status"], item["sourceUrl"])
```

JavaScript example:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('axiomworks/uk-companies-house-scraper').call({
  searchQueries: ['tesco'],
  maxItems: 5,
  includeOfficers: false,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const item of items) process.stdout.write(`${item.companyNumber}: ${item.companyName}\n`);
```

cURL example:

```bash
curl -X POST \
  'https://api.apify.com/v2/acts/axiomworks~uk-companies-house-scraper/run-sync-get-dataset-items' \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  --data '{"companyNumbers":["00445790"],"maxItems":1,"includeOfficers":false}'
```

The synchronous API route suits short requests. For larger searches, start an asynchronous run and read its dataset afterward. Join records by `companyNumber`, the register identifier.

### FAQ

**Why is a search result name different from the keyword?** A search can match a previous company name. The Actor returns the current name from the profile page and keeps the stable company number as its identifier. Review the source page when the match is surprising.

**Why is an incorporation date or SIC list empty?** Some register entries do not expose those fields on their overview page. The Actor preserves the missing value as `null` or an empty array. It does not infer an incorporation date from another field.

**What does `maxItems` count?** It counts company records pushed to the dataset. It does not count search pages, officer pages, or nested officer entries. If fewer matching profiles are available, the dataset contains fewer records.

**Can I search several terms at once?** Yes. Supply several strings in `searchQueries`. The Actor processes them in order and removes companies already emitted by an earlier query or an exact number input.

**Can I paste profile links?** Yes. Put public company overview URLs in `companyUrls`. The Actor extracts the eight-character company number and rejects URLs outside the Companies House profile path.

**How are filters applied?** `statuses` matches the profile status without regard to case. `sicCodePrefixes` matches the start of any SIC code on the profile. If both are supplied, both must match before a company is output.

**Does the Actor need a login?** No. It reads public company overview and officers pages. If the site challenges or throttles a request, the Actor waits and retries. After a block response on a direct connection, it also attempts to retry through Apify Proxy when available.

**Why might a run take longer with officers enabled?** A single company can have several officers pages. The Actor reads the available pages sequentially at a modest request rate to avoid flooding the site.

### Is it legal to scrape UK Companies House?

Companies House publishes these company and officer details on public pages. Whether a particular use is permitted depends on your purpose, jurisdiction, applicable law, and the site's current terms. Review those conditions for your own workflow, especially if you plan to republish or combine personal information about officers. The Actor only accesses pages available without a login and does not solve access challenges. It is an independent tool and is not affiliated with Companies House.

### Feedback

If a field is missing or a page layout changes, provide the company number, the affected field, and the relevant run details in the Actor's Apify feedback channel. Include a public source page when possible, and avoid sharing private credentials. Concrete examples help distinguish a parser issue from an optional field that the register did not publish. If you observe a repeated company number in a dataset, or a record beyond your requested `maxItems`, include that run as well so the issue can be reproduced.

# Actor input Schema

## `searchQueries` (type: `array`):

Company names or keywords to search, e.g. \["tesco","bp"]. Matches current and previous names; 20 results per page, in register order, each opened as a full profile. Use at least one of searchQueries, companyNumbers or companyUrls. A search with no hits returns nothing (run still succeeds). maxItems is shared across all searches.

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

Exact Companies House numbers, e.g. \["00445790","SC123456"]. Up to 8 characters: digits (zero-padded, so "445790" works) or a 2-letter prefix (SC, NI, OC, LP) plus digits. Processed before searches; the most precise input. Unknown numbers are skipped with a warning, not failed.

## `companyUrls` (type: `array`):

Full https profile URLs, e.g. \["https://find-and-update.company-information.service.gov.uk/company/00445790"]. Same effect as companyNumbers. Any other host or path fails the run immediately with a message naming the bad URL.

## `statuses` (type: `array`):

Keep only companies whose status equals one of these (case-insensitive), e.g. \["Active"] or \["Dissolved","Liquidation"]. Empty = any status. Excluded companies do not count toward maxItems; if every match is excluded the run succeeds with 0 items and says so.

## `sicCodePrefixes` (type: `array`):

Keep only companies having a SIC code that starts with one of these 1-5 digit prefixes, e.g. \["47","62"] (47 = retail). Non-digit values fail the run. Empty = any SIC code. Excluded companies do not count toward maxItems.

## `includeOfficers` (type: `boolean`):

true (default) adds the full officers list (name, role, appointment and resignation dates) to each company at one extra request per 35 officers. false is faster and returns officers \[] and officerCount null. Set false for large company lists.

## `includePscs` (type: `boolean`):

false (default) skips them. true adds pscs (persons with significant control: name, status, notified/ceased dates, nature of control, nationality) and pscCount, one extra request per PSC page. Exempt companies return an empty list.

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

Maximum company records returned across all numbers, URLs and searches combined, 1-10000, default 50. Filtered-out companies do not count. Keep small (e.g. 5) for a quick test; each record is one billable result.

## `proxyConfiguration` (type: `object`):

Apify Proxy settings, e.g. {"useApifyProxy": false}. Off by default because the site works without it; if a request is blocked or throttled (403/429) the Actor retries through Apify Proxy automatically. Set useApifyProxy true to use it from the start.

## Actor input object example

```json
{
  "searchQueries": [
    "tesco"
  ],
  "companyNumbers": [
    "00445790"
  ],
  "companyUrls": [],
  "statuses": [],
  "sicCodePrefixes": [],
  "includeOfficers": true,
  "includePscs": false,
  "maxItems": 5,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Structured company profiles

# 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 = {
    "searchQueries": [
        "tesco"
    ],
    "companyNumbers": [
        "00445790"
    ],
    "includeOfficers": true,
    "maxItems": 5,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("axiomworks/uk-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 = {
    "searchQueries": ["tesco"],
    "companyNumbers": ["00445790"],
    "includeOfficers": True,
    "maxItems": 5,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("axiomworks/uk-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 '{
  "searchQueries": [
    "tesco"
  ],
  "companyNumbers": [
    "00445790"
  ],
  "includeOfficers": true,
  "maxItems": 5,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call axiomworks/uk-companies-house-scraper --silent --output-dataset

```

## MCP server setup

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