# UK Food Business Leads: FSA Hygiene Ratings + Companies House (`ukdatakit/uk-food-business-leads`) Actor

Restaurants, cafés, takeaways, pubs and food shops in any UK council or postcode district, from official FSA food hygiene data, matched to Companies House. Find new openings, low ratings and limited companies. Monitor mode. OGL, no scraping.

- **URL**: https://apify.com/ukdatakit/uk-food-business-leads.md
- **Developed by:** [Christopher Brown](https://apify.com/ukdatakit) (community)
- **Categories:** Lead generation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 food business leads

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## UK Food Business Leads: FSA Hygiene Ratings + Companies House

Find restaurants, cafés, takeaways, pubs, hotels and food shops in any UK council or postcode district, straight from the **Food Standards Agency (FSA) food hygiene rating data**, and see which **limited company** is behind each one from **Companies House**.

Use it to:

- **Spot new openings.** Businesses "awaiting inspection" have registered with the council but not yet had their first hygiene visit – usually a new opening or a new owner. The monitor mode gives you fresh ones every week.
- **Find businesses that need help.** Filter for ratings 0–2 if you sell food safety training, cleaning, pest control or consultancy.
- **Build a compliant B2B list.** Each row says whether the business is confidently matched to an active limited company, plc or LLP (`pecrCorporateSubscriber`), so you can keep sole traders out of email campaigns.

Official open data only. No Google Maps, no scraping, no personal contact details.

### What you get (one row per food business)

| Field | Example |
|---|---|
| businessName, businessType | Horus Charcoal Grill, Restaurant/Cafe/Canteen |
| address, postcode, localAuthority | 9-11 Cannon Street, Bedminster, Bristol, BS3 1BH, Bristol |
| rating, ratingDate | AwaitingInspection (no date yet), or 0–5 with the inspection date |
| awaitingFirstInspection | true = registered but not yet inspected |
| hygieneScore, structuralScore, managementScore | FSA inspection scores (lower is better) |
| latitude, longitude | where published |
| companyName, companyNumber, companyType, incorporatedOn | HORUS CHARCOAL GRILL LTD, 17458729, ltd, 2026-09-14 |
| companyMatch | `high` (same name, same postcode), `medium` (same name, same area), `possible`, `none` |
| possibleCompanyName / Number | same name elsewhere in the UK – a hint only, never counted as the match |
| pecrCorporateSubscriber | true only for a high/medium match to an active limited company, plc or LLP |
| fsaUrl, companiesHouseUrl | links to the official pages |

Results come newest registrations first (by FSA ID).

### How to use it

**Quick search:** enter a council (e.g. `Leeds`, `Westminster`, `Glasgow City`) or postcode districts (`BS1`, `M4`), pick business types and press Start. The default (Bristol restaurants and takeaways, 50 rows) finishes in about 30 seconds.

**New openings monitor:** set Mode to *New openings monitor* and schedule it weekly.

- First run: saves a snapshot and returns everything awaiting its first inspection.
- Later runs: only `new-listing`, `rating-changed` (with `previousRating`) and `removed` rows.
- Changing your filters starts a new snapshot.

**Only limited companies:** switch this on to return only businesses confidently matched to an active company. The actor keeps looking up businesses until it has your Max results (up to 15 lookups per wanted row, so very narrow searches may return fewer).

### Pricing

**$0.003 per food business returned** (pay per event), including the Companies House lookup. 1,000 leads cost $3. You can cap spending in the run options. A monitor run with no changes costs nothing.

### How the company match works

The FSA lists trading names; Companies House lists registered names. We search Companies House for each business name and only accept an **active** company whose name is identical once "Ltd", "Limited", punctuation and "&/and" are normalised:

- **high** – the registered office has the same postcode as the premises;
- **medium** – same postcode district or area;
- **possible** – one company with that name, registered somewhere else (often a chain head office or an unrelated firm). Shown separately for you to check.

Many small food businesses trade under a different name from their company, or are sole traders, so in our tests 15–40% of rows matched. We would rather leave a field empty than guess.

### Using the data lawfully (UK GDPR and PECR)

- **Email marketing:** under PECR you may send B2B marketing emails to *corporate subscribers* (limited companies, plcs, LLPs) at their business addresses, with a clear opt-out in every message. Sole traders and ordinary partnerships count as individuals and need prior consent. Use `pecrCorporateSubscriber = true` as your starting filter, and still check each company yourself.
- **Personal data:** this actor returns no names of people, phone numbers or personal emails. Businesses run from a private home (address withheld by the FSA) are skipped by default.
- You are the controller of any list you build. Have a legitimate interest assessment, tell people where you got their details, honour objections, and screen against the TPS/CTPS before calling.
- **Showing ratings publicly:** showing a rating does not imply FSA endorsement, and ratings change. Check the live FSA page before you publish a rating, and do not use FSA rating images except under the FSA Brand Standard.

This is general information, not legal advice.

### Data sources and licence

- Food hygiene ratings: Food Standards Agency, Food Hygiene Rating Scheme API (England, Wales, Northern Ireland) and Food Hygiene Information Scheme (Scotland). Open Government Licence v3.0. Updated daily by local authorities.
- Company data: Companies House Public Data API. Contains public sector information licensed under the Open Government Licence v3.0.

Every row carries an `attribution` field. Keep it when you share the data.

### FAQ

**Is "awaiting inspection" always a new business?** Usually it is a newly registered business or a change of owner. Some have been waiting for a while, as councils have inspection backlogs.

**Why no phone numbers or websites?** The FSA does not publish them, and we don't scrape Google or websites. Use the company number to find more on Companies House.

**Does it cover Scotland?** Yes. Scottish councils use Pass / Improvement Required instead of 0–5.

**Can I use my own Companies House key?** Yes, add it in the input (stored as a secret). Otherwise the built-in key is used.

### Changelog

See [CHANGELOG.md](CHANGELOG.md).

# Changelog

This Actor's version history is a separate document: https://apify.com/ukdatakit/uk-food-business-leads/changelog.md

# Actor input Schema

## `mode` (type: `string`):

Search returns every matching food business, newest registrations first. New openings monitor saves a snapshot and, on later runs, returns only new listings, rating changes and removals. The first monitor run returns businesses awaiting their first inspection (usually new openings or new owners). Schedule it weekly.

## `localAuthorities` (type: `array`):

Council names as used by the FSA, e.g. Bristol, Leeds, Westminster, Glasgow City. Partial names match every council containing the text. Ignored if you enter postcode districts.

## `postcodeDistricts` (type: `array`):

Optional. Postcode districts such as BS1, M4 or EH1. If you fill this in, it replaces the council list, so you can target a few districts precisely.

## `businessTypes` (type: `array`):

Leave empty for all types. Default: restaurants/cafés and takeaways.

## `ratings` (type: `array`):

Leave empty for all. AwaitingInspection = registered but not yet inspected (often a new opening). 0–2 = improvement needed. Pass / Improvement Required are Scottish (FHIS) results.

## `nameContains` (type: `array`):

Optional. Keep only businesses whose name contains any of these words, e.g. pizza, coffee, bakery.

## `matchCompaniesHouse` (type: `boolean`):

Look up each business on Companies House to find the limited company behind it (company number, type, incorporation date). Adds about half a second per business.

## `onlyLimitedCompanies` (type: `boolean`):

Keep only businesses confidently matched to an active limited company, plc or LLP. Use this if you plan to email them: under PECR you can send B2B marketing to corporate subscribers with an opt-out, but sole traders and partnerships count as individuals.

## `excludeWithheldAddresses` (type: `boolean`):

Businesses run from a private home have their street address withheld by the FSA (only a partial postcode is shown). Skipping them keeps personal data out of your list.

## `maxResults` (type: `integer`):

Maximum rows to return (0 = no limit). Each row is one charged event.

## `watchlistName` (type: `string`):

Optional label for the monitor snapshot. The snapshot is also keyed by your filters, so changing filters starts a new baseline.

## `companiesHouseApiKey` (type: `string`):

Optional. A built-in key is used if empty. Get a free key at developer.company-information.service.gov.uk.

## Actor input object example

```json
{
  "mode": "search",
  "localAuthorities": [
    "Bristol"
  ],
  "businessTypes": [
    "Restaurant/Cafe/Canteen",
    "Takeaway/sandwich shop"
  ],
  "matchCompaniesHouse": true,
  "onlyLimitedCompanies": false,
  "excludeWithheldAddresses": true,
  "maxResults": 50
}
```

# Actor output Schema

## `results` (type: `string`):

One row per food business with its FSA hygiene rating and any matched Companies House company.

## `changes` (type: `string`):

New listings, rating changes and removals since the last monitor run.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "localAuthorities": [
        "Bristol"
    ],
    "businessTypes": [
        "Restaurant/Cafe/Canteen",
        "Takeaway/sandwich shop"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ukdatakit/uk-food-business-leads").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "localAuthorities": ["Bristol"],
    "businessTypes": [
        "Restaurant/Cafe/Canteen",
        "Takeaway/sandwich shop",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("ukdatakit/uk-food-business-leads").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "localAuthorities": [
    "Bristol"
  ],
  "businessTypes": [
    "Restaurant/Cafe/Canteen",
    "Takeaway/sandwich shop"
  ]
}' |
apify call ukdatakit/uk-food-business-leads --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ukdatakit/uk-food-business-leads"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/gapShnpyZqa0LAOzj/builds/1DfNCeXbEdIFzUbdg/openapi.json
