DEV Community

Hiếu Trần Quang
Hiếu Trần Quang

Posted on

How to get a daily list of new UK companies from Companies House (free API + Python)

About 2,500 companies are incorporated in the UK every day (2,470 on 20 Oct 2026, 2,538 on 21 Oct). For accountants, banks, insurers, agencies and SaaS companies, each one is a business that needs a bank account, bookkeeping, a website and software – and nobody has contacted it yet.

The data is public and free: Companies House exposes every company through a REST API. This post shows how to get "new companies in industry X in town Y" with a few lines of Python, and how to turn it into a daily feed.

1. Get a free API key

Register at the Companies House developer hub, create an application and a REST API key. The key is free; the rate limit is 600 requests per 5 minutes.

Authentication is HTTP Basic: the key is the username, the password is empty.

2. The endpoint you want: advanced search

Most tutorials use /search/companies, which searches by name. For new incorporations you want advanced search, which filters by date, SIC code and location:

curl -s -u "$CH_API_KEY:" \
  "https://api.company-information.service.gov.uk/advanced-search/companies?incorporated_from=2026-10-14&incorporated_to=2026-10-21&sic_codes=62012&location=Leeds&size=100"
Enter fullscreen mode Exit fullscreen mode

That returns new software companies (SIC 62012) registered in Leeds that week, with name, number, type, creation date and registered office address. The hits field tells you the total.

3. In Python

import os
from datetime import date, timedelta

import requests

API = "https://api.company-information.service.gov.uk/advanced-search/companies"
KEY = os.environ["CH_API_KEY"]


def new_companies(since: date, until: date, sic_codes=None, location=None):
    params = {
        "incorporated_from": since.isoformat(),
        "incorporated_to": until.isoformat(),
        "size": 5000,  # max page size
        "start_index": 0,
    }
    if sic_codes:
        params["sic_codes"] = ",".join(sic_codes)
    if location:
        params["location"] = location

    while True:
        r = requests.get(API, params=params, auth=(KEY, ""), timeout=30)
        r.raise_for_status()
        data = r.json()
        items = data.get("items", [])
        yield from items
        params["start_index"] += len(items)
        if not items or params["start_index"] >= data.get("hits", 0):
            break


today = date.today()
for c in new_companies(today - timedelta(days=7), today, sic_codes=["62012"], location="Leeds"):
    addr = c.get("registered_office_address", {})
    print(c["company_number"], c["company_name"], c["date_of_creation"], addr.get("postal_code"))
Enter fullscreen mode Exit fullscreen mode

Things that bite you in practice:

  • SIC codes are codes, not labels. Keep a lookup table (the ONS publishes the SIC 2007 list) so your output says "Business and domestic software development" instead of 62012.
  • Daily feeds need state. If you run this every day with a 7-day window, you will get the same companies again. Store the company numbers you have already processed and skip them.
  • Dissolved within weeks. A noticeable share of new companies never trade. Re-check company_status before you reach out.
  • Personal data. The API also exposes officers and PSCs. For B2B outreach, the company and its registered office are usually enough – and keep PECR/GDPR in mind.

4. Turning it into a daily feed

Run the script on a schedule (cron, GitHub Actions), keep a set of seen company numbers, and push only the new rows to a Google Sheet, Slack channel or CRM. That is the whole pipeline.

No-code alternative

If you would rather not maintain the script, I packaged the same workflow as a hosted tool: Company Registry Search on Apify. You set Registers: United Kingdom, Industry code, Location and Registered since, switch on Only new or changed companies, and add a daily schedule. It adds SIC labels, a simple KYB risk signal, and also covers France (INSEE SIRENE) and the global LEI register in the same format. It's pay-per-result (about $3 per 1,000 companies). Disclosure: I'm the author – the free API above is all you need if you're happy to run your own script.

Code examples for this and related public-data tools (SEC financials, EU/UK tenders, US federal contracts) are in this GitHub repo.


Data: Companies House public data API (Open Government Licence). This article was written with AI assistance and checked against the live API.

Top comments (0)