# UK Company Growth Signals: Companies House + LinkedIn (`fractionalhqforyou/uk-company-growth-signals`) Actor

Rank UK companies by Companies House filings and optional LinkedIn headcount changes. Get a 0-100 score, dated evidence and research angles. Free demo; bring a Companies House API key for live records.

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

## Pricing

from $30.00 / 1,000 companies

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Company Growth Signals: Companies House + LinkedIn

Turn a UK company list into a shortlist you can explain. Combine Companies House filings with optional LinkedIn headcount snapshots, then sort the companies by a published 100-point rubric. Each row includes the figures and source link behind the score.

Use it to choose which prospects deserve research this month. Filing activity is a lead signal; it does not prove revenue growth, a funding round or buying intent.

### See the result first

Leave the API key blank and run the Actor. You get three fictional companies without external requests or Actor event charges. The growth example includes a fictional previous headcount snapshot; your first live run has no previous snapshot.

| Fictional company | Score | Band | Appointments | SH01 filings | Headcount change |
| --- | --- | --- | --- | --- | --- |
| DEMO ROBOTICS LIMITED | 90 | GROWING | 2 | 2 | 8 |
| DEMO PRINT AND PACKAGING LIMITED | 45 | STEADY | 1 | 0 | 2 |
| DEMO HIGHLAND HAULAGE LIMITED | 0 | QUIET | 0 | 0 | Not available |

These are actual outputs from the built-in fictional demo, not customer results. Open the dataset to inspect every reason, then export the rows as JSON, CSV or Excel.

### Cost of a real run

$0.03 per matched company checked. A 20-company run costs $0.60 in this Actor's events; checking that list weekly for four weeks costs $2.40. Unmatched names and failed company lookups have no event charge.

Optional LinkedIn reads use `harvestapi/linkedin-company` on your account and add that Actor's charges. Your plan must permit those runs. Switch `linkedinLookup` off for register-only research. Check the Pricing tab and your Apify plan for current platform or standby usage costs.

### What it reads

For each company it pulls the profile, every officer on the register including the ones who resigned, and the filing history back to the start of your lookback window (six months by default). From those it counts:

- Board appointments in the window, from `appointed_on` on the officer list and the AP01 to AP04 filings
- Resignations in the window, from `resigned_on` and the TM01 and TM02 filings
- Share allotments (SH01), with the nominal capital stated on the form
- A registered office move (AD01) and a change of name (CERTNM and the other change-of-name types)
- Company age from the incorporation date
- Whether the accounts and the confirmation statement are on time

When `linkedinLookup` is on, it also runs the LinkedIn Company Details Scraper (`harvestapi/linkedin-company`) for each company and reads the employee count and follower count. The headcount is stored under your `watchKey`, so the next run with the same key reports the change since last time.

### The rubric

Eight lines feed the score and they add up to exactly 100.

| Signal | Points | How it scores |
|---|---|---|
| New share capital | 25 | One SH01 in the window scores 15. Two or more score 25. |
| Board appointments | 20 | One appointment scores 10, two score 15, three or more score 20. |
| Headcount growth | 20 | Against the last snapshot: up 10 percent or more scores 20, up 5 percent scores 14, any rise scores 8. |
| Company age | 10 | Under 3 years scores 10, under 6 scores 6, under 10 scores 3. |
| Filings on time | 10 | Accounts and confirmation statement both not overdue. |
| Registered office moved | 5 | An AD01 in the window. |
| Name changed | 5 | A change-of-name filing in the window. |
| Board stability | 5 | Appointments equal or exceed resignations in the window. More resignations than appointments scores 0 and says who left. |

55 or more is GROWING. 30 to 54 is STEADY. Below 30 is QUIET.

Two things follow from the table. A first run with a new watch key has no previous headcount to compare against, so the headcount line cannot fire and the most any company can score is 80. And a company can be genuinely growing without any of these signals showing on the register, so a QUIET score means the public record is quiet, not that the company is.

### 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, add a REST API key. Paste it into `apiKey` and Apify stores it as a secret. It never reaches the log or the dataset.

Run with no key at all and you get three sample rows in demo mode, one in each band, scored by the same rubric as real ones. Nothing is charged and nothing leaves the container.

### How to run it

```json
{
  "apiKey": "your-companies-house-key",
  "companies": "09446231\nOctopus Energy Limited\nExample Trading Ltd https://www.linkedin.com/company/example-trading",
  "linkedinLookup": true,
  "watchKey": "saas-targets",
  "lookbackMonths": 6
}
```

A company number is looked up directly. A name is searched and accepted only when the top hit is the same name once case, punctuation and LTD versus LIMITED are ignored; anything else comes back unmatched with the top three candidates attached, so you make the call rather than the Actor guessing. A LinkedIn company URL after the name or number is used as-is for the LinkedIn lookup, which skips LinkedIn's own name search and its chance of picking the wrong company.

Leave `companies` empty and fill in `searchQuery`, `sicCode` or `postcodePrefix` instead, and every company the register returns for that search is scored, up to `maxResults`.

Run it monthly with the same `watchKey` and every run after the first carries the headcount change. Different lists get different keys and never touch each other.

### What comes back

One row per company. The Overview table shows the score, the band, the counts and the LinkedIn status so you can sort on the score column and start at the top.

| Field | What it holds |
|---|---|
| `input`, `matched` | The line you gave and whether a company was found. |
| `company_name`, `company_number`, `status`, `date_of_creation` | As registered. |
| `growth_score`, `growth_band` | 0 to 100, and GROWING, STEADY or QUIET. |
| `appointments_in_window`, `appointed_names` | Officers appointed since `lookback_from`. |
| `resignations_in_window`, `resigned_names` | Officers who resigned in the window. |
| `share_allotments_in_window`, `share_allotment_capital`, `latest_allotment_date` | SH01 count, the nominal capital on the forms, and the newest one. |
| `office_moved_in_window`, `name_changed_in_window` | With the dates. |
| `company_age_years` | To one decimal. |
| `accounts_overdue`, `confirmation_overdue` | With the next due dates. |
| `headcount`, `headcount_previous`, `headcount_change`, `headcount_change_pct` | From LinkedIn, and the change since the last snapshot under this watch key. |
| `followers`, `linkedin_url`, `linkedin_name` | From LinkedIn. |
| `linkedin_status`, `linkedin_error` | `ok`, `not_found`, `off`, or `unavailable` with the reason. |
| `reasons` | Every rubric line that fired, with its numbers and points. |
| `pitch_angles` | Up to three sentences written from this row's own numbers. |
| `companies_house_url`, `checked_at`, `previous_checked_at` | Where to verify it, and when. |
| `candidates`, `error` | For unmatched names, the possible companies; for failed lookups, why. |

A pitch angle looks like this:

> DEMO ROBOTICS LIMITED filed 2 share allotments with Companies House since 2026-03-07, recording new shares issued; the filing does not establish how much funding was raised.

> DEMO ROBOTICS LIMITED added 8 people on LinkedIn since 2026-06-07, from 38 to 46.

The `OUTPUT` record in the key-value store carries the summary: how many companies landed in each band, the ten highest scores with their first pitch angle, how many LinkedIn lookups were unavailable, and one line you can drop into Slack.

### Honest limits

- The nominal capital on an SH01 is the face value of the shares, not the money paid for them. Three pounds of nominal capital can be a large round at a premium. The count of allotments is the signal; the figure is context.
- The officer list and the filing history are read from the public register, which lags. An appointment made last week may not be on it yet.
- The LinkedIn employee count is what LinkedIn shows, which is people who list the company on their profile, not payroll. When a company only carries a range, the bottom of the range is used and `headcount_is_range_floor` is true.
- When `linkedinLookup` is on and the wrapped Actor cannot run, the row still scores from the register and `linkedin_status` says `unavailable` with the error. The headcount line simply does not fire.
- Searching LinkedIn by name can land on the wrong company with a similar name. Give the LinkedIn URL on the input line when you have it, and check `linkedin_name` against `company_name` when you do not.
- None of this is a judgement about the company. It describes what the public record showed on the day it was read.

### Use it from an AI agent

Every part of this Actor is reachable from an AI agent, because I also run it as an MCP server. The endpoint is `https://fractionalhqforyou--uk-company-growth-signals.apify.actor/mcp` and the tool is `find_uk_growth_signals`, which takes the same input and returns the rows and the summary in one call. Agent runs are charged the same per-event price. When a client cannot take a raw endpoint, load `apify/actors-mcp-server` with `fractionalhqforyou/uk-company-growth-signals` in its Actor list.

### Help with your first run

Open an issue on this Actor with the run ID and the result you expected. Remove API keys and private records before sharing. Built by [Fractional HQ](https://fractionalhq.uk), independent design and automation.

# Actor input Schema

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

Enter one item 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. Add a linkedin.com/company URL after the name or number, separated by a space, to skip the LinkedIn name search. 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. This is optional. Filters the search.

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

For example M1, EC2 or BS1. This is optional. Filters the search by registered office location.

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

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

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

The key is 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.

## `linkedinLookup` (type: `boolean`):

Runs harvestapi/linkedin-company for each matched company and reads employee count and follower count. That run is billed to your own Apify account on top of this Actor's price. When it cannot run, the row still scores from the register with linkedin\_status set to unavailable.

## `watchKey` (type: `string`):

Names the saved headcount snapshot this run compares against. Use the same key every month for the same list and you get the headcount change since last time. Use a different key and you start a fresh baseline.

## `lookbackMonths` (type: `integer`):

How far back to count board appointments, resignations, share allotments, office moves and name changes.

## Actor input object example

```json
{
  "maxResults": 20,
  "includeDissolved": false,
  "linkedinLookup": true,
  "watchKey": "default",
  "lookbackMonths": 6
}
```

# Actor output Schema

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

One row per company: growth score 0-100 and band, the counted signals from the register (appointments, resignations, share allotments, office move, name change, filing hygiene, age), LinkedIn headcount and followers with the change since the last snapshot, plain-sentence reasons and up to three pitch angles. Unmatched names carry matched:false and a candidates list.

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

The OUTPUT record: companies checked, how many landed in each band, the top 10 with their first pitch angle, how many LinkedIn lookups were unavailable, the unmatched inputs and the charged count.

# 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-company-growth-signals").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-company-growth-signals").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-company-growth-signals --silent --output-dataset

```

## MCP server setup

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

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/eT8mCddEizi8N9Bw0/builds/5IdiQ5MLpbWDcqvyL/openapi.json
