# UK Company Register Monthly Changes (`mastazee_data_lab/uk-company-register-changes`) Actor

New UK companies, strike-offs, liquidations, dissolutions and address, SIC and name changes from the Companies House monthly snapshot.

- **URL**: https://apify.com/mastazee_data_lab/uk-company-register-changes.md
- **Developed by:** [Mastazee Data Lab](https://apify.com/mastazee_data_lab) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 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.

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 Company Register Monthly Changes

**The UK company register as a monthly change feed.** Instead of downloading and searching a 5.7-million-row file, get the companies you care about as rows: who was just incorporated in your sector and area, who entered strike-off, liquidation, administration or receivership this month, who dropped off the register, who moved office or changed SIC code or name, and whose accounts just became overdue. Everything comes from the official Companies House monthly snapshot, which is free and needs no API key.

Use it to:

- **Find new-business leads.** Companies incorporated last month, filtered by SIC code (for example 62 for software), postcode area (EC, M, LS) and company type. Accountants, banks, software vendors, insurers and formation-agent competitors all start here.
- **Find distress signals.** Companies that entered strike-off, liquidation, administration or receivership since last month, or whose accounts have just gone overdue: leads for insolvency practitioners, debt purchasers and credit-risk teams, and an early warning for suppliers and landlords.
- **Monitor a patch.** Schedule it monthly with the monitor switch on: each month it delivers that month's events once and then does nothing until the next snapshot is out.

**Tested on 27 October 2026 on the Apify platform** against the real Companies House snapshots: `new` mode with the default input returned 500 companies (of 68,766 matches) in about 3 minutes; a `changes` run comparing September with October 2026 delivered 2,000 events in about 10 minutes, and three sampled events (a strike-off proposal, a liquidation and a name change) matched the public register exactly.

### Two modes

| Mode | What it does | Typical run |
|---|---|---|
| `new` (default) | One pass over the latest snapshot. Keeps companies incorporated in a window (default: last calendar month) and your filters. Newest first. Optional "accounts overdue" and "confirmation statement overdue" filters. | About 3 minutes |
| `changes` | Compares the latest snapshot with the previous month's and returns one row per event. | About 10 minutes when capped by `maxResults`; 20 to 30 minutes for a whole month (reads two 494 MB files) |

Events in `changes` mode (`event_type`):

| Event | Meaning |
|---|---|
| `new_company` | On the live register now, not in last month's file. The description says whether it is newly incorporated or was restored or re-registered |
| `entered_strike_off` | Status moved to "Active - Proposal to Strike off" |
| `entered_liquidation`, `entered_administration`, `entered_receivership`, `entered_voluntary_arrangement` | Status moved into that class (the many spellings the register uses are mapped; the raw status is kept) |
| `dissolved_or_removed` | In last month's file, not in this one: dissolved, struck off, converted or otherwise removed. The register file only holds live companies, so removal is inferred. The row shows last month's values |
| `registered_office_postcode_changed` | Registered office postcode differs; `previous_postcode` is filled |
| `sic_changed` | The set of SIC codes differs; `previous_sic_codes` is filled |
| `name_changed` | Company name differs; `previous_company_name` is filled |
| `accounts_became_overdue` | Accounts were due before the snapshot date and were not overdue on last month's snapshot (Active and strike-off companies only) |

A company can produce several rows (for example a liquidation and a postcode change). Volumes are large: in September to October 2026 the file showed about 88,000 strike-off proposals, 54,000 removals, 62,000 postcode changes and 59,000 newly overdue accounts. Pick events, add filters and set `maxResults`.

### Example input

New incorporations in software, in London's EC and WC postcode areas:

```json
{
  "mode": "new",
  "incorporationWindow": "last_month",
  "sicPrefixes": ["62"],
  "postcodes": ["EC", "WC"],
  "maxResults": 25
}
```

Monthly distress feed for one sector, delivered once per month:

```json
{
  "mode": "changes",
  "events": ["entered_strike_off", "entered_liquidation", "entered_administration", "dissolved_or_removed"],
  "sicPrefixes": ["41", "42", "43"],
  "maxResults": 5000,
  "onlyNewResults": true,
  "stateKey": "construction-distress"
}
```

Companies with overdue accounts, any age (set the window to `any`):

```json
{ "mode": "new", "incorporationWindow": "any", "accountsOverdue": true, "minOverdueDays": 90, "postcodes": ["M"], "maxResults": 1000 }
```

### Example output

One `changes` row (from the real September to October 2026 run, trimmed of empty fields):

```json
{
  "company_number": "16621446",
  "company_name": "1 FIRST STREET LTD",
  "event_type": "entered_strike_off",
  "event_description": "Status changed from 'Active' to 'Active - Proposal to Strike off'",
  "snapshot_date": "2026-10-01",
  "previous_snapshot_date": "2026-09-01",
  "status": "Active - Proposal to Strike off",
  "previous_status": "Active",
  "company_type": "Private Limited Company",
  "incorporation_date": "2025-08-01",
  "company_age_days": 426,
  "sic_codes": [{ "code": "62012", "description": "Business and domestic software development" }],
  "post_town": "LONDON",
  "postcode": "EC1V 2NX",
  "postcode_area": "EC",
  "postcode_district": "EC1V",
  "accounts_next_due": "2027-05-01",
  "confirmation_statement_next_due": "2026-08-14",
  "confirmation_statement_overdue_days": 48,
  "source_url": "https://find-and-update.company-information.service.gov.uk/company/16621446"
}
```

### Fields

| Field | Meaning |
|---|---|
| `company_number`, `company_name` | As on the register. For removed companies, the name from last month's file |
| `event_type`, `event_description` | One of the events above, or `new_company` / `company_record` in `new` mode (`company_record` when the window is "any date") |
| `snapshot_date`, `previous_snapshot_date` | The snapshot read, and the one it was compared with (`changes` mode only). A snapshot dated 2026-10-01 holds data to the end of September |
| `status`, `previous_status` | Raw register status. `previous_*` fields are filled only where the value changed (always, for removed companies) |
| `company_type`, `country_of_origin` | Raw register values |
| `incorporation_date`, `company_age_days` | ISO date; age in days on the snapshot date |
| `sic_codes`, `previous_sic_codes` | Codes with descriptions; previous codes as a list of codes |
| `address_line1`, `address_line2`, `post_town`, `county`, `country`, `postcode` | Registered office. Street lines are left out unless you switch `includeStreetAddress` on (off by default) |
| `postcode_area`, `postcode_district` | `EC` and `EC1A` for `EC1A 1BB`; null for foreign or malformed postcodes |
| `previous_postcode`, `previous_company_name`, `name_changed_on` | Filled by the matching event; `name_changed_on` comes from the former-names list when it matches |
| `previous_names` | Former names with the date each was changed |
| `accounts_category`, `accounts_next_due`, `accounts_last_made_up` | From the accounts block; blank or implausible dates are null |
| `accounts_overdue_days`, `confirmation_statement_overdue_days` | Days past the due date on the snapshot date; null when not overdue or unknown |
| `outstanding_charges` | Number of outstanding mortgages/charges; null when the file is blank |
| `source_url` | The company's page on the official Companies House service. The Actor only links to it and never fetches it |
| `snapshot_url` | The snapshot file the row came from |

### Monitoring

Turn on `onlyNewResults` and give each watch list a `stateKey`. The Actor remembers which snapshot (or month pair) it delivered for that key, in a named key-value store (`uk-company-changes-state`) in your Apify account.

- **Each query has its own memory.** The state key is your `stateKey` plus a fingerprint of the mode, events, filters and incorporation window, so two schedules with different filters can share a `stateKey` without overwriting each other. The run summary shows the key used (`state_key`).
- Re-running in the same month finds that out with one cheap check and returns nothing, without downloading anything. When the next monthly file appears, the next run delivers that month's rows.
- **Delivered rows are remembered after every batch the platform stores** (1,000 rows at a time). If a run stops at `maxResults`, hits its run-time limit, fails or is moved by Apify part-way, the next run in the same month delivers the rest without repeating (or charging for) rows already delivered.
- **One run per monitor at a time.** A run that starts while another run of the same monitor is still working stops at once with `status: skipped_locked`. The lock is a best-effort guard (two runs started in the same instant could both proceed), so don't schedule a monitor more often than its runs take.
- Corrupted saved state is replaced and the reason is shown in the run summary (`state_reset_reason`).

Companies House publishes within about five working days of month end, and the Actor looks at the real file addresses, so a weekly schedule with `onlyNewResults` on picks the new month up as soon as it exists.

### Data source and attribution

[Companies House Free Company Data Product](https://download.companieshouse.gov.uk/en_output.html) ("Basic Company Data"), a monthly snapshot of every live company on the UK register. No key or registration is needed. Contains public sector information from Companies House.

Licence: the data is not published under the Open Government Licence and this Actor does not claim it is. Companies House says it places no rules or requirements on how information on the public register is used, that it is not responsible for how you use it, and that you are responsible for complying with data protection, copyright and other law (see [Companies House data products](https://www.gov.uk/guidance/companies-house-data-products)). The Crown insignia may not be reproduced. **This Actor is unofficial and is not affiliated with or endorsed by Companies House.**

Personal data: the Actor outputs company facts only. The snapshot has no director, officer or shareholder data. Its care-of and PO box columns can contain people's names and are never read. Registered office addresses can be a director's home for small companies, so street lines are **off by default** (town and postcode only). Switch `includeStreetAddress` on only if your use is lawful, and apply your own data-protection checks before contacting anyone.

### Data limitations (please read)

- **It is a monthly snapshot.** A company incorporated on the 15th appears about three weeks later, and the worst case is about five weeks. This is not a daily new-company feed.
- **Removal is inferred.** The file holds live companies only, so `dissolved_or_removed` means "no longer in the file", which also covers conversions and other removals.
- **Status changes show end states.** A company that went from Active to strike-off to liquidation within one month shows as `entered_liquidation` only. Strike-off proposals are signals, not facts: many are withdrawn.
- **No directors, shareholders or contact details.** Not in the source.
- **Overdue means overdue on the snapshot date**, using the due dates in the file. Implausible due dates (before 1990) are treated as unknown.
- **Status labels are inconsistent at source** (for example "ADMINISTRATION ORDER", "RECEIVERSHIP", "Live but Receiver Manager on at least one charge"). They are mapped to the events above and the raw label is kept in `status`.
- **Companies House says the product "will not be supported".** The format or host could change; the Actor fails with a clear message if the header changes.
- **Results come in a fixed order**, so with `maxResults` you get the newest incorporations in `new` mode and the first events in company-name order in `changes` mode.
- **`new` mode needs the right window for overdue lists.** Recent incorporations are never overdue: use `incorporationWindow: any` with the overdue switches.

### Running time and cost

The file is a single compressed stream, so **every run reads the whole ~494 MB download** (two of them in `changes` mode). Measured on the Apify platform on 27 October 2026 at the default 1,024 MB:

| Run | Result | Time | Platform cost | Peak memory | Peak disk |
|---|---|---|---|---|---|
| `new`, default input | 500 of 68,766 matches | 3 min 13 s | about $0.008 | 94 MB | 0.49 GB |
| `new`, SIC 62 monitor, `maxResults` 2,000 | 2,000 of 6,730 matches | 2 min 47 s | about $0.006 | 100 MB | 0.49 GB |
| `changes`, all events, `maxResults` 2,000 | 2,000 events | 9 min 51 s | about $0.029 | 236 MB | 1.06 GB |

In `changes` mode most of the time (about 9 minutes) goes into indexing last month's file, whatever your filters; the comparison itself is fast. A `changes` run that reads the whole month (no `maxResults` cap reached) takes longer, roughly 20 to 30 minutes at 1,024 MB (estimated from the measured compare speed, not measured end to end). Apify gives CPU in proportion to memory, so running with 4,096 MB makes the indexing about four times faster for about the same compute cost. Disk space also grows with memory: at 1,024 MB the run had 2.15 GB free and used 1.06 GB at most; the Actor checks free disk before downloading and stops with a clear message if there is not enough.

**Volume note:** with no filters, a month has far more events than any one run should deliver (about 4 in every 100 companies change in some way). Use `events`, `sicPrefixes` and `postcodes` to keep runs to what you need; `maxResults` is capped at 200,000 per run.

### Troubleshooting

- **"No Companies House snapshot was found".** The download service did not answer for the last four months of file names. Check https://download.companieshouse.gov.uk/en_output.html and try again.
- **`status: no_previous_snapshot`.** The month before the snapshot is not online (older files stay online about a year). Choose a more recent `snapshotMonth`.
- **`status: already_delivered`.** The monitor already delivered this month for that state key and filters. Use a new `stateKey` to start over.
- **No rows in `new` mode with overdue filters.** See the note above: set `incorporationWindow` to `any`.
- **"format changed".** Companies House changed the file's columns; report it and the Actor will be updated.
- **Run took longer than expected.** `changes` mode reads two large files; raise `maxRuntimeSeconds` (a run that hits it outputs what it found and says `partial`).

### Known restrictions

- Up to 200,000 rows per run. The run holds them in memory (about 0.5 GB at the maximum).
- `snapshotMonth` accepts 2015-01 or later, but Companies House keeps only the more recent files online (about a year was confirmed); an unpublished month gives a clear error.
- `changes` mode compares consecutive monthly snapshots only (the month named by `snapshotMonth`, or the latest, and the month before it).
- Postcode filters understand UK areas and districts (EC, EC1A); foreign postcodes cannot be matched.

# Actor input Schema

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

'New companies' lists companies incorporated in a window (one pass over the latest snapshot, a few minutes). 'Changes' compares the latest snapshot with the previous month and returns events such as strike-off, liquidation or dissolution; it reads two snapshots and takes much longer.

## `snapshotMonth` (type: `string`):

Month of the Companies House snapshot to read, as YYYY-MM (for example 2026-10). Leave empty for the latest published snapshot. In 'Changes' mode this is the newer of the two months.

## `incorporationWindow` (type: `string`):

Which incorporation dates to keep. 'Last month' is the calendar month before the snapshot month (the snapshot dated 2026-10-01 holds data to 30 September, so 'last month' is September). Use 'Any date' for overdue-accounts lists.

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

First incorporation date to keep, as YYYY-MM-DD. Only used when the window is 'Custom range'.

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

Last incorporation date to keep, as YYYY-MM-DD. Only used when the window is 'Custom range'.

## `events` (type: `array`):

Which events to return in 'Changes' mode. Leave empty for all events. A month typically has about 88,000 strike-off proposals, 54,000 dissolutions and 62,000 postcode changes, so pick events and set filters.

## `sicPrefixes` (type: `array`):

Keep companies with a SIC code starting with any of these, for example 62 (computer programming and consultancy) or 47910. In 'Changes' mode a company matches if its old or new codes match.

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

Registered office postcode areas (EC, M, LS) or districts (EC1A, M1). A district such as M1 does not match M11. In 'Changes' mode the old or the new postcode may match.

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

Keep companies whose type contains any of these words (not case-sensitive), for example "private limited", "llp", "community interest", "limited partnership".

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

Keep companies whose current status contains any of these words, for example "liquidation" or "strike off". Leave empty for every status.

## `nameContains` (type: `string`):

Keep companies whose name (or, in 'Changes' mode, old name) contains this text, not case-sensitive.

## `accountsOverdue` (type: `boolean`):

Only companies whose accounts were overdue on the snapshot date (Active or proposed-to-strike-off companies). Recent incorporations are never overdue, so set the window to 'Any date'.

## `confirmationStatementOverdue` (type: `boolean`):

Only companies whose confirmation statement was overdue on the snapshot date. Set the window to 'Any date' or a custom older range.

## `minOverdueDays` (type: `integer`):

With the overdue filters (and the 'accounts became overdue' event): ignore items overdue by fewer days than this.

## `includeStreetAddress` (type: `boolean`):

Off by default: many small companies register at a director's home, so only town and postcode are output unless you switch this on. Switch it on only if your use of street addresses is lawful (e.g. B2B marketing to the company, not to a person). Care-of names and PO boxes are never output.

## `onlyNewResults` (type: `boolean`):

For scheduled runs. Remembers (per state key) which monthly snapshot was already delivered, so re-running in the same month returns nothing and costs almost nothing. If a run stopped at 'Maximum results', the next run delivers the rest.

## `stateKey` (type: `string`):

Name for this monitor's memory. Use a different key for each watch list.

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

Stop after this many rows. In 'New companies' mode you get the newest incorporations first.

## `maxRuntimeSeconds` (type: `integer`):

Stop reading after this long and output what was found. The run summary says if it stopped early.

## Actor input object example

```json
{
  "mode": "new",
  "incorporationWindow": "last_month",
  "accountsOverdue": false,
  "confirmationStatementOverdue": false,
  "minOverdueDays": 1,
  "includeStreetAddress": false,
  "onlyNewResults": false,
  "stateKey": "default",
  "maxResults": 500,
  "maxRuntimeSeconds": 3300
}
```

# Actor output Schema

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

One row per new company or per register event (strike-off, liquidation, dissolution, address, SIC or name change, newly overdue accounts), with official links.

## `runSummary` (type: `string`):

Snapshot months read, companies scanned, matches and event counts, rows output, timings, peak memory and disk, state key and stop reason.

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

// Run the Actor and wait for it to finish
const run = await client.actor("mastazee_data_lab/uk-company-register-changes").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 = { "maxResults": 500 }

# Run the Actor and wait for it to finish
run = client.actor("mastazee_data_lab/uk-company-register-changes").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 '{
  "maxResults": 500
}' |
apify call mastazee_data_lab/uk-company-register-changes --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mastazee_data_lab/uk-company-register-changes"
        }
    }
}
```

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/WYYZgLsTsaFaFUMUe/builds/T8fIFpLIHkSkzDWxs/openapi.json
