Gov.UK Business Scraper
Pricing
from $1.00 / 1,000 premium (without api key)s
Gov.UK Business Scraper
Scrape UK Companies House data + auto-enrich with PSC (Persons with Significant Control / beneficial ownership). Filter by SIC code, industry, location, status & date. The only Apify actor with full PSC enrichment. No monthly fee pay per event only.
Pricing
from $1.00 / 1,000 premium (without api key)s
Rating
5.0
(11)
Developer
Techforce Global
Maintained by CommunityActor stats
2
Bookmarked
26
Total users
4
Monthly active users
12 days ago
Last modified
Categories
Share
UK Companies House Scraper — Advanced Company Search + PSC / Beneficial Ownership Enrichment, No API Key Needed
Query the official UK Companies House register with the full Advanced Search filter set — name includes/excludes, status, type, subtype, location, incorporation and dissolution date ranges, and 730 selectable SIC codes — then get Persons with Significant Control (PSC) / beneficial ownership attached to every company automatically. You don't need a Companies House API key (bring your own for a cheaper rate), you don't need to handle the register's rate limits, and results can go straight into Slack, Notion, Airtable, Sheets, Jira or your CRM through an MCP connector.
ℹ️ This is official register data, not a scrape. The Actor calls the government's own
api.company-information.service.gov.ukendpoints — Advanced Search for the company list, then the PSC endpoint per company. That's why the fields match Companies House exactly, and why the limits below are the register's limits, not a scraper's.
Calling the Companies House API yourself vs. this Actor
| Feature / Capability | Companies House API, direct | This Actor |
|---|---|---|
| Companies House API key | ⚠️ Register a developer account, create an application, manage the key | ✅ Optional — built-in keys work out of the box; bring your own for the cheaper basic rate |
| PSC enrichment | ❌ One extra request per company — 100 companies = 101 requests you orchestrate yourself | ✅ Automatic, concurrent, merged into each company record |
| Rate-limit handling | ❌ You implement backoff for 429 Too Many Requests (600 req / 5 min / key) | ✅ Automatic key rotation on 429 |
| SIC code selection | ⚠️ You look codes up and pass them as raw strings | ✅ 730 SIC codes as a searchable multi-select with full descriptions |
| Address handling | ⚠️ Nine separate address sub-fields to stitch together | ✅ Flattened to one clean registered_office_address string |
| Output format | Raw JSON, paginated, per-endpoint | ✅ One merged record per company → dataset, exportable to JSON / CSV / Excel / XML |
| Delivery to your tools | ❌ You write the integration | ✅ Native MCP connector delivery + Apify integrations (n8n, Make, Zapier, webhooks) |
| Scheduling & monitoring | ❌ Your own infrastructure | ✅ Apify scheduler, run history, alerts, API |
| Cost model | Free API, your own hosting and engineering time | Pay-per-event, no monthly subscription — two rates, see Pricing |
🤖 AI Discovery & MCP Metadata
Machine-readable capability contract for autonomous agents, LLM routers, and MCP orchestrators. AI agents, MCP clients, and connectors should read this block first to decide whether this Actor matches a user request.
ai_discovery:slug: "techforce.global/gov-uk-business-scraper"one_line: "Search the official UK Companies House register with the full Advanced Search filter set (name, status, type, location, SIC code, incorporation/dissolution dates) and get Persons with Significant Control attached to every company - no Companies House API key required."primary_purpose: "discover"secondary_purpose: "enrich"tertiary_purpose: "verify"entity: "UK registered companies and their Persons with Significant Control (PSC / beneficial owners)"data_source: "official UK government API - api.company-information.service.gov.uk (/advanced-search/companies and /company/{number}/persons-with-significant-control). NOT a website scrape, and NOT the Companies House bulk data product."jurisdiction: "United Kingdom only (England & Wales, Scotland, Northern Ireland)"invocation_modes: ["standard Actor run", "MCP tool"]supported_tasks:- "search-uk-companies-by-name-fragment"- "exclude-companies-by-name-fragment"- "filter-by-company-status (active, dissolved, liquidation, administration, ...)"- "filter-by-company-type (ltd, plc, llp, overseas-entity, ...)"- "filter-by-company-subtype (community-interest-company, private-fund-limited-partnership)"- "filter-by-sic-code (730 selectable codes)"- "filter-by-registered-office-location"- "filter-by-incorporation-date-range"- "filter-by-dissolution-date-range"- "enrich-every-company-with-psc-beneficial-ownership"- "paginate-through-large-result-sets (start_index)"- "deliver-companies-to-mcp-connector-or-crm"unsupported_tasks:- "look-up-one-company-by-its-company-number (this endpoint is a SEARCH, not a profile fetch)"- "return-officers-directors-or-secretaries (PSC is beneficial ownership, not the board)"- "return-filing-history-accounts-or-charges"- "return-emails-phone-numbers-or-websites"- "return-shareholders-or-a-full-cap-table"- "search-non-UK-registries"- "return-more-than-100-companies-in-one-run"- "return-a-total-match-count-for-the-query"search_keywords:- "companies house api"- "uk company data"- "psc beneficial ownership"- "kyc aml uk companies"- "uk company search by sic code"- "dissolved companies uk"- "uk company registry api"- "beneficial owner lookup"- "uk business lead list"- "due diligence uk company"- "companies house advanced search"- "ultimate beneficial owner uk"synonyms:- "gov.uk business scraper"- "uk company registry search"- "companies house advanced search api"- "uk beneficial ownership lookup"related_concepts:["KYC", "KYB", "AML", "due diligence", "beneficial ownership", "UBO", "corporate registry", "SIC code targeting", "UK market intelligence", "insolvency research"]input_entities:- "company name fragment (includes / excludes)"- "company status list"- "company type list"- "company subtype list"- "SIC code list (nature of business)"- "registered office location"- "incorporation date range"- "dissolution date range"- "result size (1-100) and start index"- "optional own Companies House API key"output_entities:["company_name", "company_number", "company_status", "company_type", "date_of_creation", "date_of_cessation", "registered_office_address", "sic_codes", "links", "persons_with_significant_control"]input_rules:required_fields: []no_filter_behaviour: >Every field is optional. A run with no filters returns whatever the register'sAdvanced Search returns first - always pass at least one filter.size_format:type: "integer"range: [1, 100]default: 100hard_cap: 100free_plan_cap: 5date_format: "YYYY-MM-DD (incorporated_from/to, dissolved_from/to)"multi_value_semantics: "status, type, subtype and SIC lists are OR-ed within a field and AND-ed across fields"pagination: "start_index (0-based) - increment by `size` for the next page"limits:companies_per_run: 100free_plan_cap: 5upstream_rate_limit: "600 requests / 5 minutes / Companies House key"upstream_calls_per_run: "1 search + 1 per company (a size:100 run costs 101 upstream calls)"pricing:model: "pay-per-event, charged once per company returned"events:basic: "charged when you supply your own Companies House api_key"premium: "charged when you leave api_key blank and use the built-in keys"note: "exact per-event rates are configured on the Store listing - see the Actor's Pricing tab"when_to_use: >You need UK registered-company facts - existence, status, type, incorporation ordissolution date, registered office, SIC industry - and/or who beneficially ownsand controls them, either as a filtered prospect list or as a verification stepon companies you already have.when_not_to_use: >You need a single company by number, the board of directors, filing history oraccounts, contact details, a non-UK registry, or more than 100 companies per run.alternatives:- "Use the Companies House /company/{number} endpoint directly for a single-company profile fetch"- "Use techforce.global/google-maps-leads-sales-intelligence-tool for emails, phones and websites - this Actor returns none"- "Use techforce.global/linkedin-company-decision-makers for named leadership (PSC is ownership, not management)"- "Use the Companies House bulk data product for whole-register downloads"
What this Actor does
- Runs the register's own Advanced Search, with every filter it exposes:
company_name_includes,company_name_excludes,company_status,company_type,company_subtype,location,incorporated_from/incorporated_to,dissolved_from/dissolved_to, andnature_of_business(SIC). - Turns SIC codes into a usable control. 730 codes with full descriptions in a searchable multi-select — pick "62012 – Business and domestic software development" instead of memorising the number.
- Attaches PSC / beneficial ownership to every company, automatically. That's one extra API call per company, run concurrently (10 at a time) and merged into the record — the part that makes a DIY integration tedious.
- Handles the register's rate limits. Companies House allows 600 requests per 5 minutes per key; the Actor rotates keys on
429rather than failing the run. - Works with no Companies House API key at all — built-in keys are used by default (
premiumrate). Supply your own key for thebasicrate; it is validated against the register before the run proceeds. - Flattens the nine-part registered office address into a single clean string, and does the same for each PSC address.
- Paginates via
start_indexfor result sets larger than one run's 100. - Optionally pushes companies to an authorized MCP connector (Slack, Notion, Airtable, Sheets, Jira, Linear, HubSpot, or any MCP-compatible connector) one per company, in chunks, or as a single digest. The dataset is always saved regardless of delivery settings.
ℹ️ PSC is ownership, not management. Persons with Significant Control are the people or entities who own or control the company (>25% shares, >25% voting rights, right to appoint/remove directors, or significant influence). They are frequently not the directors. For named leadership, pair with LinkedIn Decision Makers.
When to use it — and when not to
| Scenario | Fit |
|---|---|
| KYB / KYC / AML: who ultimately owns and controls this UK company? | ✅ Strong (the core use case) |
| Due diligence before a contract, investment or partnership | ✅ Strong — status, age, ownership in one record |
Verifying a UK company actually exists and is active | ✅ Strong |
| Building a UK prospect list by SIC industry + location + company age | ✅ Strong |
| Finding newly incorporated companies in a sector (VC / investor research) | ✅ Strong — incorporated_from + SIC |
| Insolvency / restructuring research: dissolved or liquidated companies by date and sector | ✅ Strong — company_status + dissolved_from/to |
| Cross-checking a lead list you already have against the register | ✅ Strong — loop company_name_includes |
| Registered Overseas Entities (the UK's foreign-owned-property register) | ✅ Supported — company_type: registered-overseas-entity |
| Feeding a compliance record into Notion / Airtable / a CRM | ✅ Strong (deliveryMode: "perCompany") |
| One specific company, by company number | ❌ This is a search endpoint — filter by name, or call /company/{number} directly |
| Directors, officers, company secretaries | ❌ PSC ≠ the board — use the Companies House officers endpoint |
| Filing history, accounts, charges, mortgages | ❌ Not returned |
| Emails, phone numbers, websites | ❌ Never returned — the register doesn't publish them |
| Shareholder lists / full cap table | ❌ PSC only covers controllers above the statutory thresholds |
| Non-UK companies | ❌ UK register only |
| More than 100 companies in one run | ⚠️ Hard cap of 100 — paginate with start_index |
| A count of how many companies match your filters | ❌ Not exposed — you see the page you asked for |
⚡ Execution Rules (Avoid Common Agent Failures)
- Nothing is required — and that's the biggest trap. Every field is optional, so an empty input runs a filter-less search and returns an arbitrary first 100 companies from the register. Always pass at least one filter.
sizeis capped at 100 in code as well as in the schema, and free Apify plans are capped at 5 companies per run, whatever you ask for. That is a successful run, not a failure.- This is a search, not a lookup. There is no
company_numberinput. To target one company, filter oncompany_name_includesand match the number in the output — or call the register's/company/{number}endpoint directly. - Use
start_indexto paginate, incrementing bysize. There is no total-match count in the output, so page until a run comes back with fewer thansizeitems. persons_with_significant_control: []is ambiguous. It means either the company has no PSCs on file (exempt, or asuper-securerecord) or the PSC request failed. A failed PSC fetch logs a warning and yields an empty list — check the run log before reporting "no beneficial owners".- Individual and corporate PSCs carry different fields. Individuals get
name,nationality,country_of_residence,date_of_birth,address,links. Corporate and legal-person PSCs getname,kind,identification,natures_of_control,notified_on,ceased/ceased_on,address,links.natures_of_controlis present only on corporate/legal-person records — see Output Contract. - A bad
api_keyends the run cleanly, not with a failure. An invalid key exits with the status messagePlease enter a valid API key— an agent that only checks run status will read that as success with zero items. Check the status message. - A non-200 from the search also ends the run with zero items, logging the status and body. The run status is not the error signal here; the log and the item count are.
- Mind the upstream rate limit. Companies House allows 600 requests per 5 minutes per key, and a
size: 100run costs 101 requests (1 search + 100 PSC). Back-to-back large runs will hit429; the Actor rotates keys, but keys are finite. Space out big jobs, or supply your own key. - Multi-value filters are OR within a field, AND across fields.
company_status: ["active","liquidation"]means either status; adding a SIC code narrows it further. - Dates are
YYYY-MM-DDstrings, and they are not validated by the Actor — a malformed date is passed straight to the register and rejected there. dissolved_from/dissolved_toonly make sense with a dissolved-type status. Combining them withcompany_status: ["active"]returns nothing.locationmatches the registered office, which is often an accountant's or agent's address — not where the business trades.registered_office_addressis a single joined string, not an object. Nine register sub-fields (care_of, po_box, premises, address_line_1/2, locality, region, postal_code, country) are merged with", ". Parse accordingly.sic_codesmay be absent entirely on some records — don't assume the key exists.links.company_profileis a relative path (/company/12118284). Prefix withhttps://find-and-update.company-information.service.gov.ukfor a browsable URL.- PSC data includes personal data — names, nationality, country of residence and month/year of birth of real people. See Compliance before you store it.
deliveryModedefaults toperCompany, notnone. With a connector selected, a 100-company run makes 100 connector calls. Usesummaryorchunkedfor a digest.
dependencies:- rule: "no field is required"on_violation: "an empty input returns an arbitrary first page of the register - always pass a filter"- rule: "size is clamped to 100 in code, and to 5 on free Apify plans"note: "the schema maximum and the code cap agree at 100"- rule: "there is no company_number input"on_violation: "agents looking up one company by number must use company_name_includes or the register's own /company/{number} endpoint"- rule: "empty persons_with_significant_control does not prove there are no PSCs"on_violation: "reporting 'no beneficial owners' when the PSC request actually failed"- rule: "natures_of_control is present only on corporate / legal-person PSC records"on_violation: "a KYC pipeline keyed on natures_of_control silently drops every individual owner"- rule: "an invalid api_key exits with a status message, not a failed run"on_violation: "an agent that only checks run status reads a key failure as an empty result"- rule: "a non-200 search response ends the run with zero items and a logged error"on_violation: "same failure mode - read the log and the item count, not just the status"- rule: "one run costs 1 + N upstream Companies House requests against a 600 / 5 min / key budget"on_violation: "429 Too Many Requests; the Actor rotates keys, then returns partial or empty PSC data"- rule: "delivery requires mcpConnector AND mcpTool"on_violation: "delivery step is skipped with a warning; the dataset is still written in full"- rule: "mcpArguments must reference {message} for the rendered template to appear anywhere"on_violation: "message body is empty; the tool is still called"- rule: "mcpConnector only resolves when the Actor runs on the Apify platform"on_violation: "local runs log 'APIFY_MCP_PROXY_URL is not set' and skip delivery; the dataset is unaffected"authentication:actor_input: "optional - your own Companies House API key (api_key, stored as a secret) for the cheaper basic rate"platform: "Apify API token required for API / SDK / MCP invocation"target_site: "official Companies House API; built-in keys are used when you supply none"
📥 Input Contract
.actor/input_schema.json is authoritative — if any table on this page disagrees with the schema files, the schema files win.
Parameters
| Field | Type | Required | Default | Allowed Values / Format | Example |
|---|---|---|---|---|---|
api_key | string (secret) | ⬜ No | "" → built-in keys | Your own Companies House API key — switches billing to the basic rate | "a1b2c3…" |
company_name_includes | string | ⬜ No | — | Free text matched inside the company name | "Intelligence" |
company_name_excludes | string | ⬜ No | — | Free text excluded from the company name | "Holdings" |
company_status | array | ⬜ No | — | 11 values — see below | ["active"] |
company_type | array | ⬜ No | — | 27 values — see below | ["ltd","plc"] |
company_subtype | array | ⬜ No | — | community-interest-company, private-fund-limited-partnership | ["community-interest-company"] |
nature_of_business | array | ⬜ No | — | 730 SIC codes, searchable multi-select | ["62012"] |
location | string | ⬜ No | — | Registered office locality / town | "London" |
incorporated_from | string | ⬜ No | — | YYYY-MM-DD | "2020-01-01" |
incorporated_to | string | ⬜ No | — | YYYY-MM-DD | "2024-12-31" |
dissolved_from | string | ⬜ No | — | YYYY-MM-DD | "2022-01-01" |
dissolved_to | string | ⬜ No | — | YYYY-MM-DD | "2024-12-31" |
size | integer | ⬜ No | 100 | 1–100; free plans capped at 5 | 50 |
start_index | integer | ⬜ No | 0 | ≥ 0 — offset for pagination | 100 |
Empty strings and null values are dropped before the request, so an unused filter costs nothing.
company_status — all 11 values
| Value | Meaning |
|---|---|
active | Trading / on the register |
dissolved | Struck off and dissolved |
liquidation | In liquidation |
administration | In administration |
receivership | In receivership |
insolvency-proceedings | Insolvency proceedings under way |
voluntary-arrangement | Company voluntary arrangement |
open | Open (used for some entity types) |
closed | Closed (used for some entity types) |
converted-closed | Converted or closed |
removed | Removed from the register |
company_type — all 27 values
| Value | Meaning |
|---|---|
ltd | Private Limited Company |
plc | Public Limited Company |
llp | Limited Liability Partnership |
limited-partnership | Limited Partnership |
private-unlimited | Private Unlimited Company |
private-unlimited-nsc | Private Unlimited Company without Share Capital |
private-limited-guarant-nsc | Private Limited by Guarantee without Share Capital |
private-limited-guarant-nsc-limited-exemption | …with 'Limited' exemption |
private-limited-shares-section-30-exemption | Private Limited, s.30 'Limited' exemption |
old-public-company | Old Public Company |
overseas-company | Overseas Company |
registered-overseas-entity | Overseas Entity (UK property ownership register) |
uk-establishment | UK Establishment Company |
unregistered-company | Unregistered Company |
charitable-incorporated-organisation | Charitable Incorporated Organisation |
scottish-charitable-incorporated-organisation | Scottish CIO |
registered-society | Registered Society |
industrial-and-provident-society | Industrial and Provident Society |
assurance-company | Assurance Company |
investment-company-with-variable-capital | ICVC |
protected-cell-company | Protected Cell Company |
european-public-limited-liability-company-se | European Public Limited Liability Company (SE) |
eeig | European Economic Interest Grouping |
further-education-or-sixth-form-college-corporation | FE / Sixth Form College Corporation |
royal-charter | Royal Charter Company |
scottish-qualifying-partnership | Scottish Qualifying Partnership |
converted-or-closed | Converted or Closed |
SIC codes (nature_of_business)
730 codes are selectable, each labelled code – description in the Console dropdown. Frequently used ones:
| SIC | Sector |
|---|---|
62012 | Business and domestic software development |
62020 | Information technology consultancy activities |
62090 | Other information technology service activities |
63110 | Data processing, hosting and related activities |
64999 | Financial intermediation not elsewhere classified |
68209 | Other letting and operating of own or leased real estate |
70229 | Management consultancy activities other than financial management |
73110 | Advertising agencies |
41100 | Development of building projects |
47910 | Retail sale via mail order houses or via Internet |
86900 | Other human health activities |
56101 | Licenced restaurants |
Pass several codes to OR them together.
Examples
KYB / due diligence — verify one company and its owners
{"company_name_includes": "Techforce Global","company_status": ["active"],"size": 10,"deliveryMode": "none"}
B2B prospecting — active London software companies incorporated since 2020
{"company_status": ["active"],"company_type": ["ltd"],"nature_of_business": ["62012", "62020"],"location": "London","incorporated_from": "2020-01-01","size": 100,"deliveryMode": "none"}
Insolvency research — financial firms dissolved 2022–2024
{"company_status": ["dissolved"],"nature_of_business": ["64999"],"dissolved_from": "2022-01-01","dissolved_to": "2024-12-31","size": 100,"deliveryMode": "none"}
Distress monitoring — companies currently in liquidation or administration
{"company_status": ["liquidation", "administration", "receivership"],"location": "Manchester","size": 100,"deliveryMode": "none"}
Overseas Entities holding UK property
{"company_type": ["registered-overseas-entity"],"company_status": ["active"],"size": 100,"deliveryMode": "none"}
Page 3 of a large result set, on your own API key (cheaper basic rate)
{"api_key": "<your-companies-house-api-key>","company_status": ["active"],"nature_of_business": ["41100"],"size": 100,"start_index": 200,"deliveryMode": "none"}
MCP Delivery Configuration (Optional)
Delivery pushes company records into your own tools. It never contacts a company or a person.
| Parameter | Type | Default | Description |
|---|---|---|---|
mcpConnector | string | "" | Authorized MCP connector on your Apify account (Slack, Notion, Airtable, Sheets, Jira, Linear, HubSpot, …). Leave empty for dataset-only runs. |
deliveryMode | enum | perCompany | perCompany (one call per company) · chunked (split large sets across calls) · summary (one call with everything) · none. |
mcpTool | string | "" | Tool name on the connector: create_page, send_message, create_record, create_issue. Run once with a connector selected — the log lists the connector's available tools. |
mcpArguments | object | {} | Arguments passed to the tool. String leaves support {placeholders}. |
mcpMessageTemplate | string | "" | Template rendered and exposed to mcpArguments as {message}. |
Per-company placeholders: {companyName}, {companyNumber}, {companyStatus}, {companyType}, {companySubtype}, {dateOfCreation}, {dateOfCessation}, {address}, {sicCodes}, {profileUrl} (the browsable Companies House URL), {pscCount}, {pscNames}, {pscs} (a bulleted list with control and nationality), {company} (a formatted multi-line block), {message}.
Summary / chunked placeholders: {companyCount}, {pscTotal}, {filters} (a readable summary of the filters used), {companies}, {part}, {partCount}, {message}.
One Airtable record per company, ready for a compliance review:
{"company_status": ["active"],"nature_of_business": ["64999"],"size": 100,"mcpConnector": "<your-authorized-airtable-connector>","deliveryMode": "perCompany","mcpTool": "create_record","mcpArguments": {"fields": {"Company": "{companyName}","Number": "{companyNumber}","Status": "{companyStatus}","Incorporated": "{dateOfCreation}","Registered office": "{address}","SIC": "{sicCodes}","PSC count": "{pscCount}","Beneficial owners": "{pscNames}","Register": "{profileUrl}"}}}
One Slack digest per run:
{"company_status": ["liquidation", "administration"],"location": "Manchester","size": 100,"mcpConnector": "<your-authorized-slack-connector>","deliveryMode": "summary","mcpTool": "send_message","mcpArguments": { "channel": "#uk-credit-risk", "text": "{message}" },"mcpMessageTemplate": "⚠️ {companyCount} UK companies in distress ({filters}) — {pscTotal} PSCs on file:\n\n{companies}"}
One Notion page per company, with the ownership block inline:
{"company_name_includes": "Techforce","size": 50,"mcpConnector": "<your-authorized-notion-connector>","deliveryMode": "perCompany","mcpTool": "notion-create-pages","mcpArguments": {"parent": { "page_id": "<your-page-id>" },"pages": [{"properties": { "title": "{companyName} ({companyNumber})" },"content": "Status: {companyStatus} · Incorporated {dateOfCreation}\n{address}\n{profileUrl}\n\nPersons with Significant Control ({pscCount}):\n{pscs}"}]}}
A long result set split across Notion sub-pages instead of one oversized call:
{"company_status": ["active"],"nature_of_business": ["41100"],"size": 100,"mcpConnector": "<your-authorized-notion-connector>","deliveryMode": "chunked","mcpTool": "notion-create-pages","mcpArguments": {"parent": { "page_id": "<your-page-id>" },"pages": [{"properties": { "title": "UK construction companies — part {part}/{partCount}" },"content": "{companies}"}]}}
📤 Output Contract & Data Structure
Storage: Apify Dataset — one JSON object per company, with its PSCs nested.
Pagination: limit & offset on the dataset items endpoint (separate from the input's start_index, which pages the register).
Duplicates: one record per company per run. Across paged runs, dedupe on company_number.
Company record
| Field | Type | Nullable / optional | Meaning |
|---|---|---|---|
company_name | string | no | Registered company name, as held on the register |
company_number | string | no | Companies House number — the canonical dedupe key (letters are meaningful: SC… Scotland, NI… Northern Ireland, OC… LLP, OE… Overseas Entity) |
company_status | string | no | active, dissolved, liquidation, administration, … |
company_type | string | no | ltd, plc, llp, registered-overseas-entity, … |
company_subtype | string | ⚠️ often absent | community-interest-company / private-fund-limited-partnership where applicable |
kind | string | no | Always search-results#company — a register artifact, not useful data |
links | object | no | { "company_profile": "/company/12118284" } — a relative path |
date_of_creation | string | no | Incorporation date, YYYY-MM-DD |
date_of_cessation | string | ⚠️ only when dissolved | Dissolution date, YYYY-MM-DD |
registered_office_address | string | no | Nine register sub-fields joined with ", " — not an object |
sic_codes | array of string | ⚠️ may be absent | SIC codes on the register for this company |
persons_with_significant_control | array of object | never null, often [] | PSC records — see below, and rule 5 above |
PSC record — individuals
| Field | Type | Meaning |
|---|---|---|
name | string | Full name of the person |
nationality | string | Declared nationality |
country_of_residence | string | Declared country of residence |
date_of_birth | object | { "month": 3, "year": 2000 } — month and year only, as the register publishes it |
address | string | Correspondence address, joined into one string |
links | object | { "self": "/company/…/persons-with-significant-control/individual/…" } |
⚠️ Individual PSC records do not carry
natures_of_controlornotified_on. Those fields are kept only on corporate and legal-person records. A KYC pipeline that keys onnatures_of_controlwill silently skip every human owner — read the count and names instead, and followlinks.selfon the register if you need the exact control thresholds for a person.
PSC record — corporate entities and legal persons
| Field | Type | Meaning |
|---|---|---|
name | string | Registered name of the controlling entity |
kind | string | corporate-entity-person-with-significant-control / legal-person-… |
identification | object | legal_form, legal_authority, country_registered, place_registered, registration_number — use registration_number to hop up the ownership chain |
natures_of_control | array of string | e.g. ownership-of-shares-75-to-100-percent, voting-rights-25-to-50-percent, right-to-appoint-and-remove-directors |
notified_on | string | Date the PSC was notified to the register |
ceased / ceased_on | boolean / string | Whether control has ceased, and when |
address | string | Registered address, joined into one string |
links | object | Register link to the PSC record |
A super-secure-person-with-significant-control record (protected individuals) carries a name placeholder only — no personal details are published.
Example dataset item
{"company_name": "AMERICAN EXPRESS LIMITED","company_number": "12118284","company_status": "dissolved","company_type": "ltd","kind": "search-results#company","links": { "company_profile": "/company/12118284" },"date_of_cessation": "2019-11-05","date_of_creation": "2019-07-23","registered_office_address": "Dsf 4133 Redwood Avenue, Unit 1021, Los Angeles, 90066, United Kingdom","sic_codes": ["01110"],"persons_with_significant_control": [{"name": "Florian Haftman","nationality": "British","country_of_residence": "United States","date_of_birth": { "month": 3, "year": 2000 },"address": "Dsf, 4133 Redwood Avenue, Unit 1021, Los Angeles, 90066, United Kingdom","links": {"self": "/company/12118284/persons-with-significant-control/individual/RznLYZ9hwosE-cOdZnvhD1_1Gh4"}}]}
Building a browsable link
links.company_profile is relative. Prefix it:
url = "https://find-and-update.company-information.service.gov.uk" + item["links"]["company_profile"]
The connector delivery does this for you and exposes it as {profileUrl}.
What a successful run looks like
{"status": "SUCCEEDED","defaultDatasetId": "<datasetId>","stats": { "itemCount": 100 }}
itemCount: 0 with SUCCEEDED is a valid empty result — and also what you get from an invalid api_key or a non-200 from the register. Distinguish them from the run's status message and log:
| Log / status message | Meaning |
|---|---|
No companies found matching the criteria | Genuinely nothing matched — loosen the filters |
Please enter a valid API key (status message) | Your api_key was rejected by the register |
Failed to fetch companies. Status: 4xx/5xx | The register rejected or failed the search (often a malformed date) |
429 Too Many Requests with key … | Rate limit hit; the Actor rotated to another key |
Failed to fetch PSCs for <number>. Status: … | That company's PSC list is empty because of a failure, not because it has none |
Free plan detected — capping results to 5 companies per run. | Free-plan cap applied |
▶️ Invocation & Integration
Lifecycle: Discover → Understand → Configure → Execute → Retrieve → Validate. Authenticate every call with Authorization: Bearer <APIFY_TOKEN>.
Apify Console
Open the Actor → Input tab → set at least one filter (name, status, type, SIC, location or a date range) → set Size → (optional) paste your own Companies House API Key for the cheaper rate → (optional) pick an MCP connector, tool and template → Start → export from the Dataset tab (JSON, CSV, Excel, XML).
Model Context Protocol (MCP)
claude mcp add --transport http apify \"https://mcp.apify.com?tools=techforce.global/gov-uk-business-scraper"
Python (apify-client)
import osfrom apify_client import ApifyClientclient = ApifyClient(os.getenv("APIFY_TOKEN"))PROFILE_BASE = "https://find-and-update.company-information.service.gov.uk"run = client.actor("techforce.global/gov-uk-business-scraper").call(run_input={"company_status": ["active"],"company_type": ["ltd"],"nature_of_business": ["62012", "62020"], # software development + IT consultancy"location": "London","incorporated_from": "2020-01-01","size": 100, # ceiling; free plans stop at 5"deliveryMode": "none",})items = client.dataset(run["defaultDatasetId"]).list_items().itemsprint(f"{len(items)} companies")for company in items:pscs = company.get("persons_with_significant_control") or []# [] can also mean the PSC request failed - check the run log before concluding.owners = ", ".join(p.get("name", "") for p in pscs) or "(none on file)"print(f'{company["company_number"]} {company["company_name"]}\n'f' incorporated {company["date_of_creation"]} · {company["company_status"]}\n'f' {PROFILE_BASE}{company["links"]["company_profile"]}\n'f' PSCs ({len(pscs)}): {owners}')
Paginating past 100 — the register is paged with start_index, not the dataset:
all_items, start = [], 0while True:run = client.actor("techforce.global/gov-uk-business-scraper").call(run_input={"company_status": ["active"],"nature_of_business": ["41100"],"size": 100,"start_index": start,"deliveryMode": "none",})page = client.dataset(run["defaultDatasetId"]).list_items().itemsall_items.extend(page)if len(page) < 100: # short page = last page; there is no total count to checkbreakstart += 100# Each page costs 101 upstream Companies House calls against 600 / 5 min / key.
JavaScript / TypeScript (apify-client)
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('techforce.global/gov-uk-business-scraper').call({company_status: ['dissolved'],nature_of_business: ['64999'],dissolved_from: '2022-01-01',dissolved_to: '2024-12-31',size: 100,deliveryMode: 'none',});const { items } = await client.dataset(run.defaultDatasetId).listItems();// Corporate PSCs expose natures_of_control; individuals do not.const corporateOwners = items.flatMap((c) =>(c.persons_with_significant_control ?? []).filter((p) => p.natures_of_control).map((p) => ({company: c.company_name,owner: p.name,control: p.natures_of_control,ownerCompanyNumber: p.identification?.registration_number,})),);console.log(`${corporateOwners.length} corporate control relationships`);
cURL — synchronous run (returns items directly; 300s limit)
curl -X POST \-H 'Content-Type: application/json' \-H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \-d '{"company_status":["active"],"location":"London","nature_of_business":["62012"],"size":50,"deliveryMode":"none"}' \'https://api.apify.com/v2/acts/techforce.global~gov-uk-business-scraper/run-sync-get-dataset-items'
cURL — asynchronous with a spend cap (recommended for production)
# 1. Start execution with a hard spend limitcurl -X POST -H 'Content-Type: application/json' \-H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \-d '{"company_status":["active"],"nature_of_business":["41100"],"size":100,"deliveryMode":"none"}' \'https://api.apify.com/v2/acts/techforce.global~gov-uk-business-scraper/runs?maxTotalChargeUsd=1.00'# 2. Pollcurl -H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \'https://api.apify.com/v2/actor-runs/<runId>'# 3. Retrieve when SUCCEEDEDcurl -H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \'https://api.apify.com/v2/datasets/<DATASET_ID>/items?clean=true&format=json'
Workflow tools
n8n (HTTP Request node), Make, Zapier and webhooks all work through the standard Apify API endpoints above — or skip the glue entirely and let the Actor deliver into your tool with mcpConnector.
⚠️ Autonomous Agent Error Handling & Resolution Matrix
| Error Code | Detection Condition | Underlying Cause | Deterministic Agent Action |
|---|---|---|---|
AUTH_INVALID | HTTP 401 from Apify | Missing or malformed APIFY_TOKEN | Abort & Prompt User: request a valid Apify API token. |
RATE_LIMITED | HTTP 429 from Apify | Apify API rate / concurrency limits | Retry: exponential backoff (2s, 4s, 8s). |
SYNC_TIMEOUT | HTTP 408 on the sync endpoint | Run exceeded the 300s synchronous ceiling | Reconfigure: use async POST /runs + polling. |
CH_KEY_INVALID | SUCCEEDED, 0 items, status message Please enter a valid API key | The api_key you supplied was rejected by Companies House | Modify Input: fix or remove api_key (removing it falls back to built-in keys at the premium rate). |
NO_FILTERS | 100 seemingly unrelated companies | Every field is optional; nothing was filtered | Modify Input: pass at least one filter. |
EMPTY_RESULTS | SUCCEEDED, 0 items, log No companies found matching the criteria | Filters genuinely match nothing | Modify Input: loosen filters — drop location, widen the date range, remove a SIC code. |
CONTRADICTORY_FILTERS | 0 items with several filters set | e.g. company_status: ["active"] combined with dissolved_from | Modify Input: remove the incompatible filter. |
CH_SEARCH_FAILED | SUCCEEDED, 0 items, log Failed to fetch companies. Status: 4xx/5xx | The register rejected the query (often a malformed YYYY-MM-DD date) or was unavailable | Modify Input / Retry: validate the date format, then retry. |
CH_RATE_LIMITED | Log 429 Too Many Requests with key … | 600 req / 5 min / key exhausted — a size:100 run costs 101 | Wait & Retry: pause ≥ 5 minutes, lower size, or supply your own api_key. |
PSC_FETCH_FAILED | Log Failed to fetch PSCs for <number> | That company's PSC call failed; the field is [] because of the failure | Do not conclude "no owners". Re-run for those company numbers. |
PSC_EMPTY_AMBIGUOUS | persons_with_significant_control: [], no warning in the log | Company genuinely has no PSCs on file (exempt, or super-secure) | Accept, and record it as "none on file", not "none exist". |
PSC_NO_CONTROL_FIELD | natures_of_control missing on a PSC | Individual PSC records don't carry it — only corporate / legal-person ones do | Fix Expectation: use links.self on the register for a person's control detail. |
FREE_PLAN_CAP | itemCount stops at 5, log shows the upgrade banner | Free Apify plan caps the run at 5 companies | Prompt User: upgrade for full-volume runs. |
SIZE_CLAMPED | Fewer items than requested with size > 100 | size is hard-capped at 100 | Modify Input: request ≤ 100 and paginate with start_index. |
NO_TOTAL_COUNT | Agent wants to know how many matched | The register's total is not exposed in the output | Fix Expectation: page until a short page returns. |
WRONG_GRANULARITY_SINGLE | User wanted one company by number | This is a search endpoint with no company_number input | Re-route: filter on company_name_includes, or call the register's /company/{number} directly. |
WRONG_ENTITY_OFFICERS | User wanted directors / officers | PSC is beneficial ownership, not the board | Re-route: Companies House officers endpoint, or LinkedIn Decision Makers for named leadership. |
NO_CONTACT_DATA | No email / phone / website in any item | The register does not publish them | Re-route: Google Maps Business Leads. |
NO_FILINGS_OR_ACCOUNTS | No filing history, accounts or charges | Not part of Advanced Search or the PSC endpoint | Fix Expectation: use the register's filing-history endpoints. |
NON_UK_QUERY | User asked about a non-UK company | UK register only | Abort & Prompt User: UK entities only (incl. Overseas Entities that own UK property). |
ADDRESS_NOT_OBJECT | Code does address.locality and gets undefined | registered_office_address is a single joined string | Fix Code: parse the string, or take the whole line. |
RELATIVE_LINK | A saved URL 404s | links.company_profile is a relative path | Fix Code: prefix https://find-and-update.company-information.service.gov.uk. |
DELIVERY_SKIPPED | Log no tool name was provided | mcpConnector set but mcpTool empty | Modify Input: set mcpTool; the dataset is already saved. |
DELIVERY_TOOL_UNKNOWN | Log Tool 'x' is not available on this connector | Wrong tool name for that connector | Modify Input: pick a name from the Available tools: list in the same log line. |
DELIVERY_EMPTY | Connector called, body empty | mcpArguments omitted the {message} placeholder | Modify Input: map {message} inside mcpArguments. |
DELIVERY_FLOOD | Up to 100 connector calls per run | deliveryMode defaults to perCompany | Reconfigure: use summary or chunked. |
MCP_PROXY_MISSING | Log APIFY_MCP_PROXY_URL is not set | Running locally instead of on the platform | Reconfigure: apify push and run on the platform. |
CHARGE_LIMIT | Run aborted before size reached | maxTotalChargeUsd spend threshold reached | Prompt User: confirm a higher spend cap. |
⚠️ Verify before publishing: the Apify HTTP status rows (
401,408,429) reflect standard platform behavior. Every Companies-House-side and field-level row is taken from this Actor's source and from real run output. Re-confirm the platform rows if you depend on them for automated retry logic.
🗣️ Natural Language → Actor Mapping
| User says | Intent | Constructed Actor input |
|---|---|---|
| "Who really owns Acme Trading Ltd?" | UBO / KYB | {"company_name_includes":"Acme Trading","company_status":["active"],"size":10} |
| "Is this UK company still active?" | Verification | {"company_name_includes":"<name>","size":10} → read company_status |
| "Run KYC on this list of UK suppliers" | Batch KYB | one run per name on company_name_includes, then read persons_with_significant_control |
| "Find active London software companies started since 2020" | Prospecting | {"company_status":["active"],"nature_of_business":["62012","62020"],"location":"London","incorporated_from":"2020-01-01","size":100} |
| "Newly incorporated fintech companies this year" | Investor research | {"company_status":["active"],"nature_of_business":["64999"],"incorporated_from":"<Jan 1>","size":100} |
| "Which construction firms went under in 2023?" | Insolvency research | {"company_status":["dissolved"],"nature_of_business":["41100"],"dissolved_from":"2023-01-01","dissolved_to":"2023-12-31","size":100} |
| "Any companies in administration near Manchester?" | Distress monitoring | {"company_status":["administration","liquidation"],"location":"Manchester","size":100} |
| "Show me UK charities, not regular companies" | Entity-type filter | {"company_type":["charitable-incorporated-organisation","scottish-charitable-incorporated-organisation"],"size":100} |
| "Which foreign entities own UK property?" | Overseas Entities | {"company_type":["registered-overseas-entity"],"company_status":["active"],"size":100} |
| "Find LLPs in Edinburgh" | Type + location | {"company_type":["llp"],"location":"Edinburgh","size":100} |
| "Companies with 'holdings' in the name but not 'property'" | Name filtering | {"company_name_includes":"holdings","company_name_excludes":"property","size":100} |
| "Give me the next 100 results" | Pagination | repeat the input with start_index advanced by 100 |
| "Push each company into Airtable for compliance review" | CRM delivery | {"mcpConnector":"airtable","deliveryMode":"perCompany","mcpTool":"create_record"} |
| "Alert the risk channel about distressed companies" | Digest delivery | {"mcpConnector":"slack","deliveryMode":"summary","mcpTool":"send_message"} |
| "Who are the directors of this company?" | Officers | ⚠️ Not PSC — use the register's officers endpoint, or LinkedIn Decision Makers |
| "Get me their email and phone number" | Contact data | ➡️ Route to Google Maps Business Leads |
| "Pull their latest accounts" | Filings | ❌ Out of scope — filing-history endpoints |
| "Look up company 12118284" | Single lookup | ⚠️ No company_number input — search by name, or call /company/12118284 directly |
| "Do the same for a German company" | Non-UK | ❌ UK register only |
Should NOT route here: a single company fetched by its company number · directors, officers or secretaries · filing history, accounts, charges or mortgages · emails, phones or websites · shareholder lists and cap tables · non-UK registries · whole-register bulk downloads · more than 100 companies in one run.
🧭 Agent Execution & Routing Logic
[Input User Query]│▼1. Is the subject a UK-registered entity? NO → Abort. UK register only│ YES▼2. What is actually wanted?├── existence / status / age / SIC / registered office → stay here├── beneficial ownership (who OWNS or CONTROLS it) → stay here (PSC)├── directors / officers / the board → Route: CH officers endpoint├── filings / accounts / charges → Route: CH filing-history endpoints└── emails / phones / websites → Route: Google Maps Business Leads▼3. One company, or a filtered list?├── ONE, and you have its number → the register's /company/{number} is the direct route├── ONE, by name → company_name_includes + company_status, size 10, match the number in output└── a LIST → continue▼4. Build the filter set — NEVER run with none:status? type/subtype? SIC (nature_of_business)? location? incorporated_* ? dissolved_* ?(values OR within a field, AND across fields)▼5. Sanity-check for contradictions└── dissolved_from/to with status "active" → returns nothing. Drop one▼6. Set size (≤ 100; free plans get 5). Need more? plan start_index pages: 0, 100, 200 …│ Each page = 1 + size upstream calls against 600 / 5 min / key.│ Large jobs: supply your own api_key, or space the pages out.▼7. Own Companies House key available?├── YES → pass api_key (billed at the cheaper `basic` rate, uses YOUR quota)└── NO → leave blank (built-in keys, `premium` rate, shared quota)▼8. Deliver to a connector? YES → mcpConnector + mcpTool + {message}│ perCompany (≤100 calls) / chunked / summary│ NO → set deliveryMode "none" (it defaults to perCompany)▼[Execute]│├──► SUCCEEDED, items > 0 ──► for each company:│ pscs == [] ? → check the log for "Failed to fetch PSCs" before reporting "no owners"│ need control detail on a PERSON? → natures_of_control is corporate-only; use links.self│ dedupe on company_number; prefix links.company_profile to make it browsable│└──► SUCCEEDED, items == 0 ──► READ THE STATUS MESSAGE AND LOG, they differ:"Please enter a valid API key" → fix or drop api_key"Failed to fetch companies. Status" → bad date format / register error → retry"No companies found matching..." → loosen the filters
💰 Cost Control & Pricing Transparency
Pay-per-event, charged once per company returned. No monthly subscription. There are two rates, and which one applies depends entirely on whether you bring your own Companies House API key:
| Event | Fires when | What it means for you |
|---|---|---|
basic | You supply your own api_key | The cheaper rate. Requests run against your Companies House quota (600 req / 5 min), and your key is validated before the run starts. |
premium | You leave api_key blank | The convenience rate — no registration, no key management. Requests run on the Actor's built-in keys, whose quota is shared across users. |
Exact per-event rates are on the Actor's Pricing tab in the Apify Store. Getting your own key is free at the Companies House developer hub and takes a few minutes — if you plan to run this at volume, it's the cheaper and faster path on both counts.
⚠️ Verify before publishing: this repo contains no
.actor/pay_per_event.json, so thebasicandpremiumrates are configured only on the Store listing. Confirm the live event configuration — and that both event names match the ones the Actor charges — before publishing.
What you are charged for: one event per company pushed to the dataset. A run that returns 40 companies charges 40 events, whichever rate applies. PSC enrichment is included in that — you are not charged separately per beneficial owner.
Free Apify plans are capped at 5 companies per run, so you can validate a filter set for the cost of five events before committing to a full sweep.
Autonomous spend caps: pass maxTotalChargeUsd as a query parameter on the run endpoint for a hard per-execution ceiling.
Cost and quota levers:
- Bring your own key — cheaper rate, dedicated quota, no contention with other users.
- Validate filters at
size: 5first. A filter typo on asize: 100run costs 100 events for data you throw away. - Set
sizeto what you'll actually use. The default is 100, i.e. the maximum. - Remember the 1 + N upstream cost. Every company costs one extra Companies House request for its PSC list. That's what the register's rate limit sees, and it's why back-to-back
size: 100runs hit429. - Cap the spend with
maxTotalChargeUsdon any agent-driven run.
Apify platform usage (compute units, storage) is billed on top at your plan's rates. This Actor is HTTP-only — no browser — so compute is modest; the wall-clock time is dominated by the register's own response times.
🔍 Companion machine-readable files
| File | Purpose |
|---|---|
.actor/actor.json | Identity, version, build tag, and the dataset-schema reference |
.actor/input_schema.json | Authoritative typed input contract — all 14 search fields (incl. the 730-code SIC enum and the 27 company types) plus the 5 delivery fields |
.actor/dataset_schema.json | Console Output tab view — company name, number, status, type, incorporation and dissolution dates, registered office, SIC codes, PSCs |
.actor/output_schema.json | Declares where results are stored |
src/main.py | Input mapping, API key validation and rotation, Advanced Search request, concurrent PSC enrichment, PSC field filtering, charging, free-plan cap |
src/delivery.py | MCP delivery: placeholder flattening, company/PSC block rendering, chunk grouping, per-mode dispatch |
src/connector.py | MCP connector session handling through the Apify MCP Proxy |
sic_list.txt + update_schema.py | Source list and generator for the 730-entry SIC multi-select in the input schema |
Note: this Actor has no pay_per_event.json — the basic and premium rates are configured on the Store listing.
If any table on this page disagrees with the schema files, the schema files win.
🛠️ Troubleshooting
| # | Symptom you see | Most likely cause | Fix |
|---|---|---|---|
| 1 | 100 companies with nothing in common | No filter was set — every field is optional | Pass at least one filter. |
| 2 | SUCCEEDED with 0 items | Could be three different things | Read the status message and log — see the table in Output Contract. |
| 3 | Status message Please enter a valid API key | Companies House rejected your api_key | Fix the key, or clear the field to use the built-in keys. |
| 4 | Log Failed to fetch companies. Status: 400 | Usually a malformed date | Use YYYY-MM-DD exactly. |
| 5 | Exactly 5 companies every run | Free Apify plan cap | Upgrade the plan; the log prints the upgrade banner. |
| 6 | Asked for 500, got 100 | size is hard-capped at 100 | Paginate with start_index in steps of 100. |
| 7 | persons_with_significant_control: [] everywhere | Genuine (exempt / super-secure) or failed PSC calls | Search the log for Failed to fetch PSCs. If present, re-run those company numbers. |
| 8 | Log full of 429 Too Many Requests | 600 req / 5 min / key exhausted — one size:100 run costs 101 | Wait 5 minutes, lower size, or supply your own api_key. |
| 9 | A person's PSC record has no natures_of_control | Individual records don't carry it — only corporate / legal-person ones do | Follow the PSC links.self on the register for a person's control detail. |
| 10 | address.locality is undefined in your code | registered_office_address is a joined string | Parse the string, or use the whole line. |
| 11 | A saved company URL 404s | links.company_profile is a relative path | Prefix https://find-and-update.company-information.service.gov.uk. |
| 12 | sic_codes missing on some records | Not every company has SIC codes on the register | Treat the key as optional. |
| 13 | date_of_cessation missing | Only dissolved companies have one | Expected on active companies. |
| 14 | No emails, phones or websites | The register doesn't publish them | Pair with Google Maps Business Leads. |
| 15 | No directors or officers | PSC is ownership, not management | Use the register's officers endpoint, or LinkedIn Decision Makers. |
| 16 | dissolved_from returned nothing | Combined with company_status: ["active"] | Use a dissolved-type status, or drop the date filter. |
| 17 | location results look wrong | It matches the registered office — often an agent's address | Expected. Registered office ≠ trading address. |
| 18 | Up to 100 connector calls per run | deliveryMode defaults to perCompany | Switch to summary or chunked. |
| 19 | Slack / Notion / Airtable received nothing | Delivery needs both mcpConnector and mcpTool | Set both. The dataset is still written in full. |
| 20 | Connector fired but the message body is empty | mcpArguments did not reference {message} | Map {message} in mcpArguments and populate mcpMessageTemplate. |
| 21 | Notion call timed out on a big result set | One payload with 100 companies is too large | Use deliveryMode: "chunked". |
| 22 | Log APIFY_MCP_PROXY_URL is not set | You ran locally; connectors only resolve on the platform | Deploy with apify push and run on the platform. |
| 23 | HTTP 408 on run-sync-get-dataset-items | The synchronous endpoint has a hard 300-second ceiling | Use async POST /runs → poll → fetch. |
| 24 | HTTP 401 / 403 from Apify | Missing, expired or malformed APIFY_TOKEN | Regenerate in Apify Console → Settings → API & Integrations. |
| 25 | HTTP 429 from Apify | Apify account concurrency / rate limits | Retry with exponential backoff (2s → 4s → 8s). |
Diagnostic checklist before opening an issue
- Baseline run.
{"company_status":["active"],"location":"London","size":5,"deliveryMode":"none"}— a filter set that must return something. - Items returned? If yes, the pipeline is fine and your earlier filter set was too narrow or self-contradictory.
- Still zero? Read the status message, then the log. Those three failure modes (bad key / register error / genuine no-match) look identical from the run status alone.
- PSCs all empty? Search the log for
Failed to fetch PSCs. A clean log means the companies genuinely have none on file. - Seeing
429? Wait five minutes and retry withsize: 10. If that works, you were rate-limited, not broken.
If the issue survives all five steps, open an Issues ticket on the Actor page (or email support) with the run ID and the exact input JSON.
❓ FAQ
Setup & access
Do I need a Companies House API key?
No. The Actor ships with built-in keys and works out of the box at the premium rate. Supplying your own key (free from the developer hub) switches you to the cheaper basic rate and gives you your own rate-limit quota — worth doing for any volume of work.
Is this scraping the Companies House website?
No. It calls the official government API — /advanced-search/companies for the search and /company/{number}/persons-with-significant-control for ownership. The field names and values are the register's own.
Is the data official and up to date?
It is exactly what the register serves at request time. Companies House data depends on companies filing correctly and on time, so it is authoritative about what has been filed, not about what is true — a common gap on PSC declarations in particular.
Can I plug it into Claude, Cursor, or a LangChain agent?
Yes — it is a native MCP tool:
claude mcp add --transport http apify "https://mcp.apify.com?tools=techforce.global/gov-uk-business-scraper"
Search behaviour
Can I look up one company by its company number?
Not directly — there is no company_number input, because this wraps a search endpoint. Filter on company_name_includes and match the number in the output, or call the register's /company/{number} endpoint yourself for a single profile.
How do I get more than 100 companies?
Paginate: keep the filters identical and advance start_index by size each run. There is no total-match count, so page until a run returns fewer items than size.
How do multi-value filters combine?
OR inside a field, AND across fields. company_status: ["liquidation","administration"] + location: "Leeds" means "in either of those states, registered in Leeds".
Does location mean where the business operates?
No — it matches the registered office, which for many small companies is their accountant's or formation agent's address.
Can I find Overseas Entities that own UK property?
Yes: company_type: ["registered-overseas-entity"].
PSC / ownership
What exactly is a PSC?
A Person with Significant Control: someone holding more than 25% of shares or voting rights, the right to appoint or remove a majority of directors, or otherwise exercising significant influence or control. It is an ownership concept — PSCs are often not the directors.
Why is persons_with_significant_control empty?
Either the company genuinely has none on file — some entity types are exempt, and super-secure individuals are withheld — or that company's PSC request failed. The two look identical in the data; the run log distinguishes them.
Why does a person's PSC record have no nature of control?
Individual records keep name, nationality, country_of_residence, date_of_birth, address and links; natures_of_control and notified_on are kept only on corporate and legal-person records. For a person's exact control thresholds, follow their links.self on the register.
Can I trace an ownership chain up to the ultimate owner?
Partly, and only in the UK. A corporate PSC's identification.registration_number is a UK company number when the owner is a UK company — feed it back in as company_name_includes or via the register's /company/{number} endpoint to get its PSCs. Chains that leave the UK stop there.
Do I get shareholders or a cap table?
No. PSC only covers controllers above the statutory thresholds.
Output & scope
Can I get emails, phone numbers or websites?
No — the register doesn't publish them. Pair with Google Maps Business Leads & Sales Intelligence for contact data.
Can I get directors, filings or accounts?
Not from this Actor. PSC ≠ officers, and filing history is a separate set of register endpoints.
Why is the address one long string?
The register splits it into nine sub-fields; the Actor joins them with ", " so it drops straight into a spreadsheet or CRM field. Parse the string if you need the parts back.
Pricing
How is this billed?
Pay-per-event, one event per company returned — at the basic rate when you supply your own Companies House key, or the premium rate when you use the built-in ones. Exact figures are on the Actor's Pricing tab. Apify platform usage is billed separately.
Am I charged extra for PSC data?
No. Ownership enrichment is included in the per-company event, however many PSCs a company has.
How do I guarantee an agent never overspends?
Pass maxTotalChargeUsd as a query parameter on the run endpoint — a hard per-execution ceiling — and validate filters at size: 5 before a full sweep.
🔗 Related Actors
The verification layer of the pipeline
Most lead Actors tell you a business exists and how to reach it. This one tells you whether it is real, how old it is, and who owns it — the step that turns a lead list into something you can act on commercially or defend to a compliance team.
| Actor | Anchored on | Returns | Pair with this Actor to… |
|---|---|---|---|
| This Actor | UK register filters | Company facts + PSC / beneficial ownership | — |
| Google Maps Business Leads & Sales Intelligence | A place + query | Emails, phones, websites, website grade | Add the contact details the register never publishes |
| LinkedIn Decision Makers | One company name | Founders, C-suite, VPs, directors | Put names and faces next to the ownership record (management vs. ownership) |
| LinkedIn Employee Scraper | One company name | Staff, with department and seniority | Gauge real headcount and team shape behind a registered entity |
| Advanced Website Crawling Actor | A domain | Full site content | Check what the company claims about itself against what it has filed |
Vertical UK lead sources worth verifying here
| Actor | Feeds this Actor with |
|---|---|
| Construction Lead Scraper | Contractor and developer names — check status and ownership before subcontracting |
| Finance Lead Scraper | Financial firm names — a natural KYB pairing |
| Healthcare Lead Scraper | Practice and group names — resolve the operating company behind a clinic |
| Hospitality Lead Scraper | Venue and group names — identify the entity behind a trading name |
| DesignRush Agency Scraper · TopDevelopers Scraper | Agency names — confirm a UK agency is a real, active company before signing |
Suggested pipeline patterns
🛡️ KYB / onboarding check
Company name → this Actor (company_status, PSC) → deliveryMode: "perCompany" into Airtable or Notion → a human reviews status, age and beneficial owners before approval.
🎯 Verified UK prospect list
This Actor by SIC + location + incorporated_from → Google Maps Business Leads for contact data → LinkedIn Decision Makers for named buyers. Every lead is a confirmed active company before anyone spends outreach time on it.
📉 Distress / credit monitoring
Schedule daily: company_status: ["liquidation","administration","receivership"] + your target locations → deliveryMode: "summary" into a Slack risk channel.
🧬 Ownership chain walk
Run once → for each corporate PSC, take identification.registration_number → run again on that number → repeat until the chain leaves the UK or terminates in individuals.
💰 Investor sector scan
incorporated_from = start of quarter + sector SIC codes → chunked delivery into Notion → a quarterly view of new UK company formation in your thesis area.
Browse all Actors by Techforce Global at apify.com/techforce.global.
🔐 Compliance & Data Privacy
This Actor reads official UK public registers through the Companies House public API. Company-level data — name, number, status, type, incorporation and dissolution dates, registered office, SIC codes — is public information published by statute, and reusing it is expressly permitted.
PSC data is different: it is personal data about identifiable individuals. For each individual beneficial owner the output can include their name, nationality, country of residence, month and year of birth, and a correspondence address. Four things follow:
- You become a data controller the moment you store it. UK GDPR and (for EU-resident individuals) GDPR apply. Have a lawful basis, record it, set a retention period, and be ready to honour access, objection and erasure requests. Public availability is not a lawful basis on its own.
- Purpose limitation is the real constraint. The PSC register exists for corporate transparency, AML and due diligence. Repurposing beneficial-owner personal data as a marketing list is a different purpose from the one it was published for and is very hard to defend — company-level fields are the right basis for prospecting, not PSC records.
- Treat filed data as filed, not verified. PSC declarations are self-reported and Companies House does not verify most of them. Do not present ownership as established fact in a report that affects someone's access to credit, contracts or services without corroboration, and remember that an absent PSC record is not evidence of absent ownership.
- Protected individuals exist for a reason.
super-secure-person-with-significant-controlrecords are withheld from publication because the person is at risk of violence or intimidation. Do not attempt to identify them from other fields.
Companies House data is published under the Open Government Licence; attribute it accordingly when you republish. You remain responsible for complying with the Companies House API terms of use, your own rate-limit obligations, and all applicable data-protection, AML and marketing law (UK GDPR, GDPR, PECR, CAN-SPAM, CASL) in the jurisdictions you operate in.
This Actor is an independent tool. It is not affiliated with, endorsed by, or sponsored by Companies House, GOV.UK, or the UK government.
🆘 Support & Custom Pipeline Engineering
Need scheduled register monitoring, an ownership-chain walker, bulk KYB across thousands of entities, or a compliance pipeline that writes straight into your case-management system?
- Email: bhavin.shah@techforceglobal.com
- Custom Enterprise Integrations: Book a 15-Minute Technical Consultation
- Maintained by: Techforce Global — Specialists in High-Performance Web Scrapers and Agentic Workflows.
Made with ❤️ by Techforce Global Specialists in High-Performance B2B Contact Data Extraction and AI Automation.
🏷️ Structured data for search & AI discovery
{"@context": "https://schema.org","@type": "SoftwareApplication","name": "UK Companies House Scraper — Advanced Company Search + PSC / Beneficial Ownership Enrichment","applicationCategory": "BusinessApplication","operatingSystem": "Cloud (Apify platform)","description": "Queries the official UK Companies House register through its Advanced Search API — filtering by company name, status, type, subtype, registered office location, incorporation and dissolution date ranges, and 730 selectable SIC codes — and attaches Persons with Significant Control (PSC / beneficial ownership) to every company automatically. No Companies House API key required; bring your own for a cheaper rate. Results are saved to a dataset and can be delivered into Slack, Notion, Airtable, Google Sheets, Jira or any authorized MCP connector.","url": "https://apify.com/techforce.global/gov-uk-business-scraper","offers": {"@type": "Offer","priceCurrency": "USD","description": "Pay-per-event, charged once per company returned: the basic rate when you supply your own Companies House API key, the premium rate when you use the built-in keys. Exact rates are listed on the Actor's Pricing tab."}}