Around 13k companies get incorporated in the UK every week. I wanted that list for a few sectors, every Monday, in a spreadsheet, without the ones I'd already seen. Turned out to be more annoying than expected, so here's what I ended up with.
The free way
Companies House has an advanced search where you can filter on incorporation date, SIC code and location, and download the results as CSV. For a one-off list that's honestly all you need.
Stuff I ran into doing it every week though:
- A download is capped at 5,000 rows. A full week is way more, so you end up doing one day at a time.
- The CSV isn't quoted. Addresses and SIC lists have commas in them, so a normal CSV parser shifts columns. I had to parse it with an anchored regex per line.
- A big chunk of new companies are dormant (SIC 99999). You probably want to drop those.
- Next week you get an overlapping list and have to figure out which ones are actually new.
Automating it
I ended up wrapping all of that in an Apify Actor (yes, I made it, it's paid). It does the daily downloads and parsing, filters on SIC code, keyword or postcode, and keeps a memory of what it already returned, so a weekly run with a slightly longer window only gives you companies you haven't had yet.
New restaurants and takeaways in the UK, for example:
{ "countries": ["GB"], "daysBack": 10, "activityCodes": ["5610"], "onlyNewSinceLastRun": true, "stateKey": "uk-new-restaurants" } That's about 800 companies a week. You get name, number, legal form, date, SIC codes with descriptions, address and the Companies House link. It's $3 per 1,000 rows, so roughly $2.40 a week for this one. The free Apify plan works for trying it, but caps a run at 100 rows.
It also does France (BODACC), Norway (Brønnøysund) and Finland (PRH). Small gotcha if you mix countries: Norway and Finland switched to NACE Rev 2.1 in 2025, so restaurants are 5611x there and 5610x in the UK. Using just 56 works for all of them.
Into Google Sheets with n8n
My setup in n8n:
- Schedule Trigger, Mondays 07:00.
- Apify node, "Run actor and get dataset", actor
polderdata~new-company-registrations-scraper, the JSON above as input. - Edit Fields node to turn the arrays into strings (
$json.activityCodes.join(', ')). - Google Sheets, append row. Set Mapping Column Mode to "Map Automatically", because it silently resets to manual when you pick a sheet and then complains that there are no values to send.
If a week has nothing new the run just stops after the Apify step.
One thing that bit me while testing: the "already seen" memory is updated as soon as the Apify step finishes. So when the Sheets step failed, the next run came back empty because those companies were already marked as delivered. Use a new stateKey for every test run.
What's not in there
No directors, emails or phone numbers. The register doesn't have contact details anyway, and I left out anything that's a person's name, sole traders included. If you need contacts you'll have to run the company name and address through some enrichment tool.
Curious what other people use these lists for.
