# UK Companies House Enrichment for Lead Lists and KYB (`fractionalhqforyou/uk-companies-house-enrichment`) Actor

Enriches UK companies from the official Companies House API: status, incorporation date, SIC labels, registered address, accounts dates, active officers, PSCs and latest filings. Feed it names or numbers, or search by keyword, SIC code and postcode. Bring your own free key; no proxies, no browser.

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

## Pricing

$20.00 / 1,000 company enricheds

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?

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

## UK Companies House Enrichment

Every UK limited company has a public record: when it was formed, whether it is still trading, who runs it, who owns it, where it is registered and what it last filed. Companies House gives all of that away through a free API. The catch is that the API hands it back as six different endpoints, half of them paginated, with a rate limit that bites the moment you point a loop at it.

I built this Actor because I kept rebuilding the same glue every time a lead list needed a company number, a director name or a "still active?" column. Give it a list of names or numbers, or a search, and it hands back one flat row per company that you can drop straight into a sheet, a CRM or the next Actor in your chain.

### What it does

You can feed it a list or point it at a search.

With a list, you paste company names or numbers, one per line. A number is looked up directly. A name is searched, and the hit is only accepted when the top result is the same name once case, punctuation and LTD versus LIMITED are ignored. If the top result is anything else, the row comes back as `matched: false` with the top 3 candidates attached, and you make the call rather than the Actor guessing on your behalf.

With a search, you give a keyword that must appear in the company name, a 5-digit SIC code, a postcode prefix for the registered address, or any mix of those, capped at whatever result count you set. That is how you get "every software company registered in G1" without typing a single name.

Each company comes back as one row. The profile part covers whether it is active or dissolved, what kind of company it is, when it was incorporated and under which jurisdiction, every SIC code it declares with a plain-English label for the main one, the registered office split into address columns, the last and next dates for accounts and for the confirmation statement, and whether it carries charges or an insolvency history. There is a link to the company's public page on every row. Switch on the options and you also get the officers who have not resigned, the persons with significant control who have not ceased, and the five most recent filings.

Everything is read from the official Companies House REST API. Nothing is scraped, and there is no proxy or browser in the loop.

### What you need

A Companies House API key. It is free and takes about two minutes: register at https://developer.company-information.service.gov.uk/, create an application and add a REST API key. Paste it into the `apiKey` field; Apify stores it as a secret and it never appears in the log or the dataset.

Run the Actor with no key and you get three sample rows in demo mode, nothing charged, so you can see the shape before you connect anything.

### How to run it

A list of companies, with officers and owners:

```json
{
  "apiKey": "your-companies-house-key",
  "companies": "09876543\nSC123456\nExample Software Ltd\nAcme Widgets",
  "includeOfficers": true,
  "includePSC": true,
  "includeFilings": false
}
```

A search instead of a list:

```json
{
  "apiKey": "your-companies-house-key",
  "searchQuery": "software",
  "sicCode": "62012",
  "postcodePrefix": "G1",
  "maxResults": 50
}
```

The `OUTPUT` record in the key-value store holds a summary: how many inputs were processed, how many matched, how many events were charged and which inputs came back unmatched.

### Output fields

| Field | What it holds |
|---|---|
| `input` | the line you gave, or `search:` plus the query |
| `matched` | true when a company was found and enriched |
| `company_number`, `company_name` | as registered |
| `status`, `type`, `date_of_creation`, `jurisdiction` | active, dissolved, liquidation and so on; ltd, plc, llp and so on |
| `sic_codes`, `sic_code_primary`, `sic_label_primary` | all SIC codes, the first one, and its label from the Companies House SIC list |
| `address_line_1`, `address_line_2`, `locality`, `region`, `postal_code`, `country` | the registered office, one column each |
| `registered_address` | the same address on one line |
| `accounts_last_made_up_to`, `accounts_next_due` | accounts dates |
| `confirmation_statement_last_made_up_to`, `confirmation_statement_next_due` | confirmation statement dates |
| `has_charges`, `has_insolvency_history` | booleans from the profile |
| `officers`, `officer_count` | active officers only: name, role, appointed\_on, nationality, country\_of\_residence, occupation (when enabled) |
| `psc_names` | current persons with significant control (when enabled) |
| `filings` | the five latest filing-history entries: date, type, category, description (when enabled) |
| `companies_house_url` | the company's public page |
| `candidates` | for an unmatched name, up to 3 possible companies with number, status and address |
| `error` | why a row could not be enriched, or null |
| `checked_at` | when the run happened |

### Pricing

Pay per event: one `company-enriched` charge per company that comes back matched. An unmatched name, an unknown number or a search that finds nothing costs no event. Officers, PSCs and filings are extra API calls behind the scenes but they never add a charge; the price is per company, whatever you switch on.

### Limits

- Searches return active companies only. Switch on includeDissolved to see dissolved and liquidated ones too. A postcode prefix is enforced on the registered office address, so a loose address match cannot leak in.

### Pair it with a workflow

If you run n8n, my free templates on https://n8n.io/creators/fractional-hq take a list like this Actor's output and turn it into lead scoring, outreach drafts and follow-ups without another tool in the chain.

### Built by Fractional HQ

I run Fractional HQ, a one-man studio for design and automation. I do not write code by hand: I architect, review and hold the standard while AI agents do the typing. That method runs my own estate, seven brands, a Postgres operations system, more than 100 scheduled jobs, published n8n templates, Zapier Silver certified.

Want this wired into your CRM and outreach, or built and handed over working? Get in touch: https://fractionalhq.uk/brief

# Actor input Schema

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

One per line. A company number (for example 09876543 or SC123456) is looked up directly. A name is searched and only accepted when the top hit is the same name; otherwise you get the top 3 candidates and matched:false. Leave empty to use the search below instead.

## `searchQuery` (type: `string`):

Used when the list above is empty. Every company whose name contains this text, up to the maximum below. Combine with a SIC code and postcode prefix to narrow it.

## `sicCode` (type: `string`):

A 5-digit UK SIC 2007 code, for example 62012 for business and domestic software development. Optional. Filters the search.

## `postcodePrefix` (type: `string`):

For example M1, EC2 or BS1. Optional. Filters the search by registered office location.

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

Cap on companies returned by a search. Each company returned is one charged event.

## `apiKey` (type: `string`):

Free. Register at https://developer.company-information.service.gov.uk/ and create a REST API key. Apify stores it as a secret. Without it the Actor runs in demo mode: 3 sample rows, nothing charged.

## `includeDissolved` (type: `boolean`):

Searches return active companies only by default. Switch on to include dissolved and liquidated ones.

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

Name, role, appointment date, nationality, country of residence and occupation for every officer who has not resigned.

## `includePSC` (type: `boolean`):

Names of the current PSCs (owners and controllers) on the register.

## `includeFilings` (type: `boolean`):

The 5 most recent filing-history entries: date, type, category and description.

## Actor input object example

```json
{
  "maxResults": 20,
  "includeDissolved": false,
  "includeOfficers": true,
  "includePSC": false,
  "includeFilings": false
}
```

# Actor output Schema

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

One row per company: profile fields, SIC codes with a label, flattened registered address, accounts and confirmation-statement dates, officers, PSC names, latest filings and a link to the Companies House page. Unmatched names carry matched:false and a candidates list.

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

The OUTPUT record: how many inputs were processed, how many matched, how many were charged, and the unmatched names.

# 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 = {
    "companies": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("fractionalhqforyou/uk-companies-house-enrichment").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 = { "companies": "" }

# Run the Actor and wait for it to finish
run = client.actor("fractionalhqforyou/uk-companies-house-enrichment").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 '{
  "companies": ""
}' |
apify call fractionalhqforyou/uk-companies-house-enrichment --silent --output-dataset

```

## MCP server setup

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

```

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/BCTwkjlAwMWoPi9gv/builds/xIrK7rKdetL4cAeMa/openapi.json
