Tutorial · United Kingdom
Companies House API in Python
The UK register has a free, genuinely good REST API. Here is how to use it from Python — and an honest account of the point where it stops being enough.
Authentication
Companies House uses HTTP Basic auth with your API key as the username and an empty password. That trips people up, because most APIs use a bearer token. Register a free application on the Companies House developer hub to get a key.
import os, requests
CH = 'https://api.company-information.service.gov.uk'
AUTH = (os.environ['CH_API_KEY'], '') # key as username, password EMPTY
r = requests.get(f'{CH}/company/00445790', auth=AUTH, timeout=20)
r.raise_for_status()
print(r.json()['company_name']) # TESCO PLCSearch, then fetch
Search returns candidates; the profile endpoint returns the record. Always confirm on company_number rather than name — UK names are not unique and change often.
def search(q, limit=5):
r = requests.get(f'{CH}/search/companies',
params={'q': q, 'items_per_page': limit},
auth=AUTH, timeout=20)
r.raise_for_status()
return [{'number': i['company_number'],
'title': i['title'],
'status': i.get('company_status')} for i in r.json().get('items', [])]
def profile(number):
r = requests.get(f'{CH}/company/{number}', auth=AUTH, timeout=20)
r.raise_for_status()
return r.json()
for c in search('tesco'):
print(c['number'], c['status'], c['title'])Officers and PSC
Two separate endpoints, both paginated. PSC — Persons with Significant Control — is the UK beneficial-ownership register, and it is unusually open: most EU equivalents closed to the public after the 2022 CJEU ruling, so this is real ownership data you can actually read.
def paged(path, per_page=50):
"""Companies House paginates with start_index; it does not return a next link."""
start, out = 0, []
while True:
r = requests.get(f'{CH}{path}',
params={'items_per_page': per_page, 'start_index': start},
auth=AUTH, timeout=20)
if r.status_code == 404: # some companies have no PSC resource at all
return out
r.raise_for_status()
items = r.json().get('items', [])
out += items
start += per_page
if len(items) < per_page:
return out
officers = paged('/company/00445790/officers')
psc = paged('/company/00445790/persons-with-significant-control')
print(len(officers), 'officers,', len(psc), 'PSC records')Three things that will bite you
- Company numbers are strings, not integers.
00445790is Tesco;445790is a 404. Zero-pad to 8 characters, and never store them as an int. - There is no check digit. Unlike a Spanish NIF or a Norwegian organisasjonsnummer, a UK company number cannot be validated offline — you can only check the shape, then look it up.
- Rate limiting is 600 requests per five minutes, and it returns 429 with a
Retry-After. Honour it; hammering through it gets keys suspended.
Shape-checking before you spend a call is worth doing — the identifier validator does it in the browser for UK numbers and for the European identifiers that do carry a checksum.
When the free API is enough — and when it isn't
Being straight about this: if you only need the UK, the Companies House API is free, well documented and complete. Use it. There is no honest argument for paying for a wrapper around a free government API.
Where it runs out is at the edges of its scope:
| Need | Companies House |
|---|---|
| UK company, officers, PSC | Yes — free and authoritative |
| Any non-UK country | No — a separate integration per country |
| Sanctions or export-control screening | No |
| Insolvency outside the UK | No |
| One schema across countries | No — each registry has its own shape |
The same lookup through Prometiam, with more countries behind the same call and the same response shape:
r = requests.get('https://api.prometiam.com/functions/v1/risk-api/companies/search',
params={'name': 'tesco', 'country': 'GB'},
headers={'Authorization': f'Bearer {os.environ["PROMETIAM_API_KEY"]}'},
timeout=20)
# same call shape for every other country the API covers — one schema, one keyFree trial is 500 credits over 14 days with a card required and nothing charged for 14 days. If the UK is all you need, stay on Companies House — that is the right call and we would rather say so.
FAQ
Is the Companies House API free?
Yes, with a free API key. It is one of the better open government APIs in Europe.
Why does my auth fail?
Almost always because the key is being sent as a bearer token. It is HTTP Basic, key as username, password empty.
Can I validate a UK company number offline?
Only its shape — 8 digits, or two letters and six digits. There is no check digit, so existence requires a lookup.
What is the rate limit?
600 requests per five minutes, returning 429 with Retry-After.
Does Companies House cover other countries?
No, UK only. Each other registry is a separate integration with its own shape — which is the problem a multi-country API exists to solve.