UK Company KYB: Companies House, Officers, PSC & Insolvency
Pricing
from $4.00 / 1,000 company enricheds
UK Company KYB: Companies House, Officers, PSC & Insolvency
UK company data for KYB and KYC. Enrich a company number (CRN) or name from Companies House: status, registered office, SIC, directors, PSC beneficial owners, charges, overdue accounts and insolvency, plus The Gazette.
Pricing
from $4.00 / 1,000 company enricheds
Rating
0.0
(0)
Developer
Yahya Nouali
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Look up a UK company by company number (CRN) or registered name and get a KYB-ready record: status, registered office, SIC codes, directors, persons with significant control (beneficial owners), charges, accounts and confirmation-statement dates, overdue flags, insolvency cases, and — when the register already shows distress — insolvency notices from The Gazette.
Built for onboarding checks, supplier screening, and lead enrichment. Misses are free. A monitor mode stores a baseline and bills only when the register changes.
Why this is enough for a first-line KYB check
Companies House is the UK registrar. The public profile already answers the questions a reviewer asks before opening a filing PDF: is the company active, where is the registered office, what does it do, are accounts overdue, and is there an insolvency flag? Officers and PSCs name the people and entities in control. Charges show outstanding security. The Gazette search adds winding-up and other insolvency notices that cite the company number.
riskFlag is the field to sort on. It is true for dissolution, liquidation, receivership, administration, voluntary arrangement, insolvency proceedings, an insolvency case, overdue accounts, a strike-off proposal, or a matching Gazette insolvency notice.
Input
{"companies": ["00445790", "SC123456", "NORTHWIND TRADING LIMITED"],"mode": "enrich","includeOfficers": true,"includePsc": true,"includeCharges": false,"includeFilings": false,"includeInsolvency": false,"gazetteNotices": "auto","snapshotStoreName": "uk-company-monitor"}
| Field | Default | What it does |
|---|---|---|
companies | required | Company numbers or names. One item each. |
mode | enrich | monitor writes a snapshot and emits only changes. |
includeOfficers | true | Directors, secretaries, LLP members. |
includePsc | true | Beneficial owners (PSC register). |
includeCharges | false | Also fetched when has_charges or links.charges is set. |
includeFilings | false | Latest 25 filing-history items. Due dates already come from the profile. |
includeInsolvency | false | Also fetched when the profile indicates insolvency. |
gazetteNotices | auto | auto, always, or off. |
companiesHouseApiKey | empty | Secret override of COMPANIES_HOUSE_API_KEY. |
snapshotStoreName | uk-company-monitor | Named key-value store used in monitor mode. |
activeOfficersOnly | false | Hides resigned officers in the output list. |
maxCompanies | 1000 | Hard cap 5000. |
Company numbers are normalised to 8 characters. 445790 becomes 00445790. sc 1234 becomes SC001234. Prefixes include SC (Scotland), NI (Northern Ireland), OC (LLP), LP (limited partnership), and the other two-letter series used on the register. Older Northern Ireland numbers such as R123456 are padded to R0123456. A value that is not a number is searched by name. An exact normalised name is EXACT. A weaker hit is returned with matchQuality: "REVIEW" and up to three alternates.
Output
Each dataset item is one JSON object. Scalar fields are listed first so a CSV export stays usable. riskFlag is the first property.
The fragment below is the shape of a row. Names and addresses come from the live register when you run the Actor; this sample is only the field layout.
{"riskFlag": false,"riskLevel": "NONE","riskSummary": "No insolvency, dissolution, or overdue-accounts flag in the data retrieved.","recordType": "company","query": "12345678","matchQuality": "NUMBER","found": true,"companyNumber": "12345678","companyName": "NORTHWIND TRADING LIMITED","companyStatus": "active","registeredOffice": "1 High Street, London, EC1A 1AA","sicCodesFlat": "62012","accountsOverdue": false,"officerNames": "DOE, Jane","pscNames": "HOLDING LTD","charged": true,"billingEvents": ["company-enriched", "officers-psc"],"companiesHouseUrl": "https://find-and-update.company-information.service.gov.uk/company/12345678"}
Nested arrays — officers, personsWithSignificantControl, charges, insolvencyCases, filings, gazetteNotices, changes — are on the same object. sourceLinks points at the Companies House company, officers, PSC, filing history, and charges pages, and at a Gazette notice search for that number.
riskLevel is HIGH when riskFlag is true, REVIEW for a weaker signal (overdue confirmation statement, undeliverable office, office in dispute, outstanding charge, ceased-but-not-dissolved, or an inexact name match), and NONE otherwise.
Monitor rows use recordType: "change" and include changedFields plus changeSummary. Compared fields:
- status and status detail
- name
- registered office
- SIC codes
- officers appointed or resigned
- PSC added, ceased, or with a control change
- new charges
- new insolvency cases
- accounts or confirmation statement becoming overdue, or ceasing to be overdue
- new Gazette notices, when that section was fetched on both runs
- a name query that resolves to a different company number than last time
The first time a section is fetched it is stored and not treated as a change. A later run diffs it. Turning officers on after a profile-only baseline does not bill every current director as a new appointment.
Invalid numbers and failed requests are dataset rows (invalid, invalid_identifier, error) and are not charged. A value that looks like a broken company number, such as ZZ!!12 or a digit-heavy string that is not a CRN, is invalid_identifier and is not sent to the name search. Ordinary names, including names with an ampersand or a single digit such as 3M, are still searched. In monitor mode, a company that is simply unchanged, or not found on the first run, is counted in the RUN_SUMMARY key-value record and is not written to the dataset.
Pricing
Pay per event. There is no start fee and no per-row dataset fee.
| Event | Price | When |
|---|---|---|
company-enriched | $0.004 | Enrich mode, and the profile was found. Primary event. |
officers-psc | $0.002 | Enrich mode, officers and/or PSCs were requested, and the register answered (including an empty list). |
change-detected | $0.015 | Monitor mode, and this company differs from the saved snapshot. |
| — | $0 | Not found, invalid input, first monitor baseline, unchanged company. |
1,000 enriched companies with directors and PSCs cost $6. A later monitor pass that finds 8 changes costs $0.12. See PUBLISHING.md for the console pricing JSON.
API key
The Actor reads COMPANIES_HOUSE_API_KEY from the environment. On Apify, set that variable as a secret. You can also pass companiesHouseApiKey on the input; that value wins for the run and is marked secret in the input schema.
Companies House uses HTTP Basic authentication with the key as the username and an empty password. The key is not written to the dataset or the log.
Create a key in the Companies House developer hub. The published limit is 600 requests per 5 minutes per key. This Actor shares one token bucket across the run, retries HTTP 429 with Retry-After or exponential backoff, and stops the run if the limit still persists. It does not call officers, PSCs, charges, insolvency, or filing history unless you asked or the profile says that resource exists (has_charges, has_insolvency_history, has_been_liquidated, links.charges, links.insolvency, or an insolvency status). Those boolean flags are deprecated by Companies House in favour of the links; both are honoured.
The Gazette lookup does not use a key.
Monitor mode
- Run with
"mode": "monitor". - The Actor writes one snapshot per found company into the named key-value store (
snapshotStoreName, defaultuk-company-monitor) on the Apify account that runs it. - That first run emits no company rows and charges nothing.
- The next run diffs the live register against the snapshot. Only changed companies are pushed, at $0.015 each.
- Deleting the store, or changing its name, starts a new free baseline.
Prefer company numbers for monitoring. A name is resolved again on every run. If the best match changes, the row is a resolved-company change so a KYB list does not silently follow a different entity.
Run locally
npm installnpm testnpm run build
Live check, one profile request, skipped when the key is absent:
$COMPANIES_HOUSE_API_KEY=your_key npm run smoke
Full local run (Apify stores results under storage/):
mkdir -p storage/key_value_stores/defaultcp examples/input.enrich.json storage/key_value_stores/default/INPUT.jsonCOMPANIES_HOUSE_API_KEY=your_key npm start
Package a source archive without node_modules:
$npm run package:actor
Use cases
- KYB / KYC onboarding. Confirm the CRN, legal name, status, registered office, SIC, directors, and PSCs before opening an account or paying a supplier.
- Lead enrichment. Turn a list of names or numbers into a spreadsheet with status, address, and active officer names. Rows marked
REVIEWneed a human to confirm the name match. - Portfolio monitoring. Re-run the same CRN list weekly. Pay only when status, address, control, charges, or overdue filings change.
- Insolvency screening.
riskFlagcollects dissolution, insolvency status, overdue accounts, strike-off proposals, and Gazette notices in one column.
Integrations: Make, Zapier, n8n
You can call this Actor from no-code tools through Apify's official integrations. Use its Actor ID tM7A2MKgSLKfMx0ro, and connect each tool with OAuth or your Apify API token. Never put the token in the Actor input.
- Make: in the Apify app, add Run an Actor and set Run synchronously to Yes. Then add Get Dataset Items with the run's default dataset ID, and map the rows to Google Sheets, a CRM or Slack. For long runs, use the Watch Actor Runs trigger instead.
- Zapier: the Apify app has the Run Actor action. A synchronous run has a 30-second hard timeout, so for larger lists start the run and use the Finished Actor Run trigger with Fetch Dataset Items.
- n8n: install the official node
@apify/n8n-nodes-apify. It is a verified community node on n8n Cloud; on self-hosted n8n, add it under Settings > Community Nodes. Use Run an Actor and Get Dataset, or the Apify trigger for finished runs.
Example input:
{"mode": "enrich", "companies": ["00445790"], "includeOfficers": true, "includePsc": true}
Scheduled monitor to Slack or Sheets
- Save a monitor input as an Actor task and keep the same store name on every run:
{"mode": "monitor","companies": ["00445790"],"snapshotStoreName": "uk-company-monitor"}
- In Apify Console > Schedules, run the task on a cron such as
0 7 * * 1(every Monday at 07:00), with your timezone selected. - On the task's Integrations tab, add Slack or an HTTP webhook on Run succeeded. You can also use Make Watch Actor Runs, Zapier Finished Actor Run or the n8n Apify trigger.
- Fetch the dataset items and keep only the change rows:
recordTypeis"change". The first run only stores the baseline and is free.
HTTP API
This call runs the Actor and returns the dataset rows in one request. Synchronous runs time out after 300 seconds, so use /runs for big lists.
curl -X POST "https://api.apify.com/v2/acts/tM7A2MKgSLKfMx0ro/run-sync-get-dataset-items" \-H "Authorization: Bearer <YOUR_APIFY_TOKEN>" \-H "Content-Type: application/json" \-d '{"mode": "enrich", "companies": ["00445790"], "includeOfficers": true, "includePsc": true}'
FAQ
Which sources does this use?
- Companies House Public Data API at
api.company-information.service.gov.uk: company profile (including registered office, SIC, status, accounts, and confirmation statement), officers, persons with significant control, filing history, charges, and insolvency. - The Gazette notice feed at
/insolvency/notice/data.json, which is limited to corporate and personal insolvency notices. No key.
Document images are not downloaded. Accounts figures and VAT numbers are not part of the public profile API, so they are not in the output.
What licence applies?
Companies House. The Public Data API is free and requires a key. Companies House states that it places no restriction on how public register information is used once it has been obtained, apart from three points: customers must take their own advice on third-party copyright in filed documents, the Crown insignia must not be reproduced, and Companies House must be credited when its guidance, website text, or statistics are reused. The Open Government Licence v3.0 applies to Companies House publications where that licence is stated. It is not a blanket licence over every scanned filing. This Actor returns structured register fields only.
The rate limit and the instruction not to embed API keys in source are in the Companies House developer guidelines. Reuse of register information is described in Companies House: public task, copyright and Crown copyright.
The Gazette. Notice content other than personal data is Crown copyright and may be reused under the Open Government Licence v3.0. The Gazette says the same in Re-using our data and in its developer documentation. The OGL does not cover personal data. The paid Gazette Electronic Information Service is a separate subscription and is not called here.
The Gazette fair-use policy for automated tools asks for an identifiable User-Agent, at most 5 requests every 10 seconds, respect for robots.txt and Retry-After, and — for unattended crawlers — operation between 21:00 and 07:00 UK time. This Actor does one targeted lookup per company when Gazette search is on, and it rate-limits those calls to 5 per 10 seconds. It is not a crawl of the site. Keep large batches inside that policy, and contact The Gazette before a high-volume unattended job. gazetteNotices: "auto" (the default) only searches when Companies House already shows insolvency, liquidation, or a proposal to strike the company off.
What about GDPR and dates of birth?
Officer names, roles, service addresses, nationality, occupation, country of residence, and month and year of birth are published on the public register under the Companies Act. PSC details are public in the same way, except where Companies House has protected a person. Protected PSCs are returned as protected: true with no name and no birth month.
The public API provides month and year only. This Actor never outputs a full date of birth. If a payload ever contained a day, that day is discarded and is not written to the dataset.
If you store these rows, or join them to other personal data, you need your own UK GDPR lawful basis. KYB and AML checks are often done as legitimate interests, which still need an assessment. Gazette notice text can name individuals. The Open Government Licence does not authorise reuse of that personal data; handle notice excerpts accordingly.
Why was I not charged?
The row was invalid, the company was not found, the monitor run was the first baseline, or nothing had changed since the snapshot. charged is false and billingEvents is empty on those rows. A failed request (recordType: "error") is also free.
Why is the name match marked REVIEW?
The search endpoint returned companies, but none had the same name once punctuation and a trailing “Limited” / “Ltd” / “PLC” were ignored. The best hit is still returned, with alternates, so you can pick the right CRN. An exact match is not marked REVIEW. Prefer passing the company number when you have it.
Limitations
- One Companies House key allows 600 requests in each 5-minute window. This Actor cannot raise that quota. A company with profile, officers, and PSCs costs three requests; charges, insolvency, filings, and a name search add more, and only when needed.
- Officers, PSCs, and charges are capped at the first 100 items. Filings are capped at 25.
warningssays when the list was truncated. - Gazette search is one page of 10 notices for the company number, then filtered to notices that mention that number or the registered name. It will miss a notice that cites neither.
- No accounts figures, no VAT number, no document PDFs, no shareholder register beyond what the PSC record contains.
- Monitor snapshots live in the caller’s named key-value store. Another Apify user has a separate store. Reset the baseline by deleting the store.
- A restarted run uses delivery markers to avoid a second charge for the same company in the same run id. A crash in the moment after a push and before that marker can duplicate a row; it should not duplicate the charge.
Development
Node.js 20 or newer. Tests use mocked HTTP and fixtures shaped like the published Companies House and Gazette JSON. They do not call the live APIs.
npm testnpm run typecheck
CI runs both on Node 20.