How to Get UK Companies House Data as JSON (Without Maintaining a Scraper)
If you are building KYB checks, lead lists or compliance monitoring for UK companies, you need the
official register fields: status, type, SIC codes, incorporation date, accounts-overdue flag and
registered office address. Companies House publishes exactly that as JSON — but wiring up the official
API yourself still means a key, pagination, retries and a rate limit you must not trip.
Here is how to get the data in two ways, with a real sample of the output.
The official API, in a nutshell
- Base URL:
https://api.company-information.service.gov.uk/ - Free API key: https://developer.company-information.service.gov.uk/
- Rate limits: one request per 550 ms and 600 requests per 5 minutes per key; 429 responses carry a
Retry-Afterheader worth honouring. - Scope: company-level fields only. The officer and PSC endpoints return personal data — if you do not have a lawful basis for personal data, do not call them (GDPR). The examples below never do.
Option A — call the official API directly
curl -sS -u "$CH_API_KEY:" \ "https://api.company-information.service.gov.uk/company/00063903" | jq . That works fine for one company. The moment you search the register by name, you are maintaining
pagination, backoff and schema handling for every field you store.
Option B — run a ready-made Actor
steadfetch/companies-house-monitor wraps that API on the Apify platform: it handles pagination,
the 550 ms / 600-per-5-min rate limits, retries and an output schema check on every run. You need no
Companies House key of your own (an optional apiKey input lets you use your own if you want an
isolated rate-limit budget).
Input — one company, or a register search:
{ "mode": "company", "companyNumber": "00063903", "maxResults": 10 } { "mode": "search", "query": "tesla", "maxResults": 100, "since": "2025-01-01" } Run it with one API call:
curl -sS -X POST \ "https://api.apify.com/v2/acts/steadfetch~companies-house-monitor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \ -H "Content-Type: application/json" \ -d '{"mode":"company","companyNumber":"00063903","maxResults":10}' Real output sample (a genuine register record, as published in the Actor's docs):
{ "url": "https://find-and-update.company-information.service.gov.uk/company/08209948", "title": "! LTD", "scrapedAt": "2026-10-19T23:45:44.207Z", "company_number": "08209948", "company_name": "! LTD", "company_status": "active", "company_type": "ltd", "sic_codes": ["99999"], "incorporated_on": "2012-09-11", "accounts_overdue": false, "address": { "address_line_1": "9 PRINCES SQUARE", "locality": "HARROGATE", "postal_code": "HG1 1ND", "country": "England" } } One dataset item per company, validated against the published dataset schema on every run — if a field
type changes upstream, the run fails loudly instead of writing bad rows (strictSchema defaults to
true).
JavaScript and Python
Node.js, with apify-client:
import { ApifyClient } from 'apify-client'; const client = new ApifyClient({ token: process.env.APIFY_TOKEN }); const { defaultDatasetId } = await client.actor('steadfetch/companies-house-monitor').call({ mode: 'search', query: 'tesla', since: '2025-01-01', }); const { items } = await client.dataset(defaultDatasetId).listItems(); console.log(JSON.stringify(items, null, 2)); Python, with apify-client:
import json, os from apify_client import ApifyClient client = ApifyClient(os.environ["APIFY_TOKEN"]) run = client.actor("steadfetch/companies-house-monitor").call(run_input={ "mode": "search", "query": "tesla", "since": "2025-01-01", }) items = client.dataset(run["defaultDatasetId"]).list_items().items print(json.dumps(items, indent=2)) Runnable versions of all three (curl, Node, Python) plus the sample output live in
steadfetch/examples/companies-house-monitor.
What it costs
Pay-per-result pricing on Apify: 2.50 USD per 1,000 valid results (0.0025 USD per company) plus a
0.00005 USD run-start fee. Failed requests, retries and empty searches are not charged per result, and
no proxy is billed — Companies House answers with structured JSON, so no browser is involved.
Fields you get
| Field | Meaning |
|---|---|
company_number / company_name / company_status | Register identity and state |
company_type, sic_codes | Legal form and activity classification |
incorporated_on, accounts_overdue | Age and filing health signals |
address | Registered office (business address, not personal) |
url, scrapedAt | Source link and extraction timestamp, on every record |
No officers, no PSCs, no personal data — by design.
Getting started
Open the Actor page in the Apify Store, run it
from the console or with the API snippets above, and pull the dataset into whatever you already use.
Steadfetch builds public-data Actors that don't break: schema-validated output, official sources only.
More at apify.com/steadfetch.
