# UK Company Accounts Feed: Net Assets & Distress (`mastazee_data_lab/uk-company-accounts-feed`) Actor

Daily Companies House accounts, one row per filing: net assets, cash and employees vs last year, plus signals such as net assets turned negative.

- **URL**: https://apify.com/mastazee_data_lab/uk-company-accounts-feed.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 $7.00 / 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 Accounts Feed: Net Assets, Cash & Distress Signals

**Every day, Companies House publishes the accounts that UK companies filed electronically the day before. This Actor turns that file into one tidy row per filing: net assets, cash and employees with the prior year next to them, the change, and a short list of distress signals.** It reads the official, free Companies House bulk file, so there is no API key to get and nothing to scrape.

Use it to:

- **Spot trouble early.** Get the roughly 350 companies a day whose net assets *turned negative* in the accounts they just filed, or everyone who now reports net liabilities or cash down by more than half.
- **Watch customers, suppliers and borrowers.** Give a list of company numbers (up to 10,000) and get a row the day any of them files accounts.
- **Feed a CRM or credit file.** Schedule it Tuesday to Saturday in monitor mode and receive each new filing once.

> **Tested on 26 October 2026** against the real Companies House download site, on a Mac and on the Apify platform: the default input returned 359 rows from the 24 October file; the example input below returned 25; every filing of the 30 September month-end file (39,244 rows) was read once; and two back-to-back monitor runs returned 359 rows, then 0. Automated tests use real accounts saved as trimmed fixtures.

**This is not a turnover or profit feed.** Most UK companies file micro-entity or small-company accounts, which are a balance sheet only. In the files we measured, about **99% have net assets**, **89% average employees**, **41% cash**, but only **about 1% turnover and 2% profit or loss**. Those fields are filled only when the company tagged them and are `null` otherwise, never 0.

### Example input

```json
{
  "signals": ["net_assets_turned_negative"],
  "latestFiles": 1,
  "maxResults": 25
}
```

Every input is optional. With no input at all you get the same as this example without the 25-row limit: the filings in the latest daily file whose net assets turned negative (359 on 24 October), at most 500.

More examples:

```json
{ "companyNumbers": ["00445790", "SC123456"], "signals": [], "monitorMode": true, "stateKey": "my-customers" }
```

A row whenever either company files, scheduled each weekday.

```json
{ "signals": ["net_liabilities"], "minEmployees": 20, "dateFrom": "2026-10-19", "dateTo": "2026-10-24" }
```

Companies with at least 20 average employees and net liabilities, filed in one week. A date range can cover at most 14 days.

Clear the `signals` list (`"signals": []`) to receive every filing, not just those with a signal.

### Example output (one filing, trimmed)

```json
{
  "filing_id": "Prod223_4336_01082080_20260630",
  "company_number": "01082080",
  "company_name": "UPPER GARDEN FLATS LIMITED",
  "balance_sheet_date": "2026-06-30",
  "accounts_type": "small",
  "net_assets": -87,
  "net_assets_prior_year": 9638,
  "net_assets_change": -9725,
  "net_assets_change_pct": -100.9,
  "cash": 2844,
  "cash_prior_year": 17368,
  "cash_change_pct": -83.63,
  "current_assets": null,
  "average_employees": 4,
  "average_employees_prior_year": 5,
  "turnover": null,
  "profit_loss": null,
  "signals": ["net_assets_turned_negative", "net_liabilities", "cash_down_over_50pct"],
  "source_file": "Prod223_4336_01082080_20260630.html",
  "source_file_date": "2026-10-24",
  "source_url": "https://download.companieshouse.gov.uk/Accounts_Bulk_Data-2026-10-24.zip",
  "company_url": "https://find-and-update.company-information.service.gov.uk/company/01082080"
}
```

### Fields

| Field | Meaning |
|---|---|
| `filing_id` | The file name inside the daily zip, without `.html`. Unique per filing; used for deduplication |
| `company_number`, `company_name` | Companies House number (8 characters) and the name **as tagged in the accounts** (it can differ from today's register name) |
| `balance_sheet_date`, `period_start` | End and start of the accounting period the figures describe |
| `approved_date` | Date the directors approved the accounts, if tagged |
| `filing_date`, `filing_window_start`, `filing_window_end` | Companies House says each daily file holds the accounts registered the previous day (Tuesday's file: Saturday to Monday). `filing_date` is that day, or `null` for Tuesday files, where `filing_window_*` give the three days |
| `accounts_type` | `micro`, `small`, `full` or `dormant`, derived from the tagged accounting standard and dormant flag; `null` if not tagged. `full` means a standard other than the micro-entity or small-entity regime, not that the company is large |
| `accounts_filing_type`, `accounting_standard` | The raw tagged values behind it (for example `FilletedAccounts`, `FullAccounts`; `Micro-entities`, `SmallEntities`, `FRS102`) |
| `dormant` | The company's own dormant flag; `null` if not tagged |
| `currency` | Currency of the figures, almost always GBP |
| `net_assets`, `net_assets_prior_year` | Net assets (liabilities) at the balance sheet date and a year earlier. Negative means net liabilities |
| `net_assets_basis` | `net_assets` (the `NetAssetsLiabilities` tag) or `equity` (total equity, used when net assets is not tagged) |
| `net_assets_change`, `net_assets_change_pct` | Difference and percentage of the prior year's absolute value. `null` when either year is unknown or the prior year is 0 |
| `cash`, `cash_prior_year`, `cash_change`, `cash_change_pct` | Cash at bank and in hand, with the same comparison |
| `current_assets`, `current_liabilities`, `total_assets_less_current_liabilities` | Current-year balance sheet subtotals. `current_liabilities` is the creditors due within one year **as tagged**; it is `null` for about 6 in 10 filings and is never calculated |
| `average_employees`, `average_employees_prior_year` | Average number of employees (some filers report fractions) |
| `turnover`, `profit_loss` and their `_prior_year` | Only where the company tagged them (about 1-2% of filings). Otherwise `null` |
| `signals` | Any of the five signals below |
| `source_file`, `source_file_date`, `source_url` | The member and date of the daily file in the official Companies House download |
| `company_url` | The company's page on the official register (a link only; the Actor never fetches it) |

#### The five signals

| Signal | True when |
|---|---|
| `net_assets_turned_negative` | Net assets were 0 or more a year earlier and are below 0 now |
| `net_liabilities` | Net assets are below 0 |
| `cash_down_over_50pct` | Cash was above 0 a year earlier and has fallen by more than half |
| `dormant` | The company's own dormant flag is true |
| `first_accounts` | Figures are present but no prior-year figure of any kind and no prior period are tagged (normally a company's first accounts) |

A signal is only raised from figures actually in the file. Unknown values never trigger a signal. On the two days measured, per day: about 360 turned negative, 2,100-2,300 net liabilities, 730-800 cash down, 1,500-1,600 dormant and 1,500-1,600 first accounts.

### Monitor mode

Switch on `monitorMode` and schedule the Actor Tuesday to Saturday after 07:00 UK time (Companies House publishes at about 06:45 UTC). The Actor remembers the last daily file it finished and, on each run, processes only later files, at most 10 per run; the first run reads the latest file, or starts at `dateFrom`, and later runs never go back before that first file.

- **Each filing once.** The Actor remembers the ids of the filings it delivered, so a re-issued file or an overlapping day never produces duplicates. A corrected filing gets a new filing id from Companies House and is delivered as a new row.
- **One memory per monitor.** The memory is kept under your `stateKey` together with your filters (watchlist, signals, name, net assets and employee limits). Two monitors with different filters never hide each other's filings, even with the same `stateKey`. Changing dates, `maxResults` or the run time keeps the same memory.
- **Nothing lost, nothing charged twice.** The memory is saved after every batch of rows the platform stores, and only rows actually stored count as delivered. If `maxResults`, `maxRuntimeSeconds` or your spending limit stops a run, or the run is interrupted, the next run continues where it stopped; a daily file is only marked done once all of its matching filings were delivered.
- **One run at a time.** If a run of the same monitor is still going, a second run stops at once with status `skipped` and no rows. (The check is not atomic: two runs started within the same second could both proceed.)
- A repeat run with nothing new takes about a second. If the saved memory is unreadable, the run starts fresh and says why in the run summary.

### Data source and attribution

Source: the [Companies House Accounts Data Product](https://download.companieshouse.gov.uk/en_accountsdata.html), free daily files of accounts filed electronically. This Actor is unofficial and is not affiliated with Companies House.

Companies House states that it "imposes no rules or requirements on how the information on the public register is used". It also says that reusers are responsible for complying with applicable data protection, copyright and other legislation. **The data is not published under the Open Government Licence and this Actor does not claim it is.** You are responsible for your own use of it, including data protection law and third-party copyright.

To respect that, the Actor outputs **extracted facts only**: numbers, dates, flags, the company number and the company name. It **never outputs the accounts text, and never any director, signatory, accountant or auditor name**, even though those appear in the source files. Its parser reads a fixed list of tags and none of them is a person.

### Data limitations (please read)

- **Electronically filed accounts only.** Paper filings and accounts prepared under IFRS are not in the product. Companies House's own pages disagree about what share of filings is covered, so no coverage figure is claimed.
- **Reported figures, as tagged.** Filers sometimes tag figures with the wrong sign or scale. One real filing wrote 32.612 euros for 32,612; it is passed through unchanged (`currency` shows EUR). About 0.8% of filings that tag both net assets and total equity disagree in sign; `net_assets_basis` tells you which tag was used, and `NetAssetsLiabilities` is preferred.
- **Turnover and profit are rare** (about 1-2%) because micro and small companies file a balance sheet only. Cash is tagged in about 4 in 10 filings, current liabilities in about 4 in 10, employees in about 9 in 10.
- **Net assets are not summed.** If a filing tags only the components of equity and no total, `net_assets` is `null`.
- **One prior year only.** The comparison is with the previous year's figures printed in the same accounts.
- **The filing date is a window**, taken from Companies House's description of the daily files, not a timestamp in the file.
- **Skipped:** nested zips (Community Interest Company reports) and any plain-XBRL `.xml` files. They are counted in the run summary (`unsupported_members_skipped`).
- Companies House describes the product as "not supported". The format could change without notice.
- Dormant companies have net assets of 0 or a small number; a dormant flag and a net-assets signal can both be present.

### Pricing

Pay per event: **$7.00 per 1,000 rows** ($0.007 per filing row), plus Apify's standard tiny start fee. You are charged only for rows written to your dataset; filings that don't match your signals or filters cost nothing.

| How you use it | Rows | You pay (approx.) |
|---|---|---|
| Default run (latest file, net assets turned negative) | ~350 | ~$2.50 |
| Daily distress monitor, Tuesday to Saturday, for a month | ~7,500 | ~$50 a month |
| Month-end deadline day (busiest file of the month) | ~1,300 | ~$9 |
| Watchlist of a few hundred company numbers, monitor mode | a few a week | cents a month |

- **No double billing in monitor mode:** each filing is delivered to a monitor once.
- **Spending limits:** if you set a maximum cost per run, the Actor stops cleanly when it's reached, and the filings it didn't deliver come back on the next monitor run.
- **Narrow it to pay less:** `minEmployees`, `minNetAssets`/`maxNetAssets`, `nameContains` and `companyNumbers` all cut the rows (and the cost) before anything is written.

### Running time and memory

Measured on the Apify platform on 26 October 2026, with the real files:

| Run | Memory | Filings read | Rows | Time |
|---|---|---|---|---|
| Default input (latest file, net assets turned negative) | 1,024 MB | 11,002 | 359 | 109 s |
| Same, at 512 MB | 512 MB | 11,002 | 359 | 209 s |
| Every filing on a month-end deadline day (2026-09-30, 398 MB) | 1,024 MB | 39,244 | 1,324 | 636 s |
| Monitor repeat run (no new file) | 512 MB | 0 | 0 | 3 s |

Reading the files is CPU work, and Apify gives more CPU to more memory, so 1,024 MB finishes twice as fast as 512 MB for about the same platform cost. On a Mac, for comparison:

| Run | Download | Filings read | Rows | Time | Peak memory | Disk |
|---|---|---|---|---|---|---|
| Default input (latest file, net assets turned negative) | 83 MB | 11,002 | 359 | 21-33 s | 132-139 MB | 83 MB |
| Example input above (stops after 25 rows) | 83 MB | 1,421 | 25 | 16 s | 123 MB | 83 MB |
| Every filing on a month-end deadline day (2026-09-30) | 398 MB | 39,244 | 39,244 | 116 s | 148 MB | 398 MB |
| Monitor, first run / repeat run | 83 MB / none | 11,002 / 0 | 359 / 0 | 21 s / 1.2 s | 111 MB | 83 MB / 0 |

Each daily file is downloaded to a temporary folder, read one filing at a time and deleted before the next file, so only one file is ever on disk. The Actor runs at **1,024 MB** by default: it is twice as fast as 512 MB for about the same cost, and Apify gives about twice the memory as disk space, so month-end files (about 400-600 MB) fit with room to spare. 512 MB also works but a month-end file takes about 20 minutes. If a file doesn't fit, the run stops with a message asking for more memory.

### Troubleshooting

- **No rows?** The default only keeps filings whose net assets turned negative. Clear `signals` to see every filing, or widen `dateFrom`/`dateTo`.
- **"Companies House published no daily file in that date range":** the range holds only Sundays, Mondays, bank holidays or future dates. Files appear Tuesday to Saturday at about 06:45 UTC.
- **"published no accounts file in the last 14 days":** the download site is unreachable or has paused. Try later.
- **"The date range may cover at most 14 days":** split a longer period into several runs, or use monitor mode.
- **Status `skipped`:** another run of the same monitor was still running. Nothing was output or charged; run it again later.
- **Run says "stopped early":** `maxResults`, `maxRuntimeSeconds` or your spending limit was reached. In monitor mode the next run continues; otherwise raise the limit.
- **A company is missing:** its accounts may be on paper, in IFRS, or not yet registered. Companies House has a one-day lag.
- **Monitor mode returned nothing:** everything up to the latest file was already delivered to this `stateKey` and filter set. Use a new key to start over.

### Known restrictions

- A date range covers at most 14 days (about 10 daily files), and `latestFiles` is at most 10. A run never reads more than 10 daily files; a monitor that is further behind catches up over several runs.
- Companies House documents that daily files are removed after 60 days. A monitor idle for longer resumes 62 days back and warns that some days may be missing.
- Files are read one at a time, with at most 5 requests a second. Files over 1.5 GB are refused (the largest seen is 598 MB).
- Monitor memory keeps the latest 250,000 delivered filing ids per monitor (several weeks of unfiltered output).
- A watchlist is limited to 10,000 company numbers.
- Output is in the currency the filer used; there is no conversion.

# Actor input Schema

## `signals` (type: `array`):

Keep a filing only if it has at least one of these signals. net_assets_turned_negative: net assets were zero or more last year and are below zero now. net_liabilities: net assets are below zero. cash_down_over_50pct: cash fell by more than half. dormant: the company reports itself dormant. first_accounts: no prior-year figures in the file. Clear the list to get every filing.

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

Only return filings by these companies (8-character Companies House numbers such as 00445790 or SC123456; shorter numbers are zero-padded). Up to 10,000. With monitor mode on, you get a row the day any of them files accounts. Leave empty for the whole feed.

## `dateFrom` (type: `string`):

First daily file to read (YYYY-MM-DD). Leave empty to read only the most recent daily file. Companies House publishes Tuesday to Saturday; each file holds the accounts registered the previous day (Tuesday's: Saturday to Monday). A range may cover at most 14 days (about 10 daily files), counted up to 'To file date' or today.

## `dateTo` (type: `string`):

Last daily file to read (YYYY-MM-DD). Leave empty for today.

## `latestFiles` (type: `integer`):

When 'From file date' is empty: how many of the most recent daily files to read (1 = the latest only, at most 10). Each file is 50-600 MB.

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

Only companies whose name, as tagged in the accounts, contains this text (not case-sensitive).

## `minNetAssets` (type: `integer`):

Only filings with net assets of at least this amount, in the accounts' currency (usually GBP). Filings with no net assets figure are dropped when this is set.

## `maxNetAssets` (type: `integer`):

Only filings with net assets of at most this amount. Use 0 to find companies with net liabilities. Filings with no net assets figure are dropped when this is set.

## `minEmployees` (type: `integer`):

Only filings reporting at least this many average employees. Filings that do not report employees are dropped when this is set.

## `monitorMode` (type: `boolean`):

For scheduled runs: remember the last daily file processed and the filings already delivered (under the state key below and your filters), and on every run process only later files, at most 10 per run. Schedule it Tuesday to Saturday after 07:00 UK time.

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

Name of this monitor's memory when monitor mode is on. Each set of filters keeps its own memory under this key; a second run of the same monitor while one is still running stops without output.

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

Stop after this many rows. In monitor mode the next run continues where this one stopped.

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

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

## Actor input object example

```json
{
  "signals": [
    "net_assets_turned_negative"
  ],
  "latestFiles": 1,
  "monitorMode": false,
  "stateKey": "default",
  "maxResults": 500,
  "maxRuntimeSeconds": 1500
}
```

# Actor output Schema

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

One row per Companies House accounts filing: net assets, cash and employees with the prior year, changes, distress signals and official links.

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

Daily files found and read, filings read, rows output, filings already delivered in monitor mode, skipped members, warnings 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 = {
    "signals": [
        "net_assets_turned_negative"
    ],
    "maxResults": 500
};

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

# Run the Actor and wait for it to finish
run = client.actor("mastazee_data_lab/uk-company-accounts-feed").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 '{
  "signals": [
    "net_assets_turned_negative"
  ],
  "maxResults": 500
}' |
apify call mastazee_data_lab/uk-company-accounts-feed --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-accounts-feed"
        }
    }
}
```

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/ssQyrBMaaBpHgj9kc/builds/h6dk4jo7tUqidfkXC/openapi.json
