# UK Food Business Leads & Change Monitor (`mutech/new-food-business-leads-uk`) Actor

Monitor UK food-business candidate leads using official FSA data. Track newly observed businesses and possible business changes, with names, addresses, ratings and source links. Built-in sector exclusions and repeat-run monitoring for agencies and suppliers.

- **URL**: https://apify.com/mutech/new-food-business-leads-uk.md
- **Developed by:** [Mu Tech](https://apify.com/mutech) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 results

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 lead monitoring

Find **food-business candidate leads and possible business changes** using official Food Standards Agency (FSA) records. Search records with recent activity dates or monitor later observations and changes. Built for agencies, suppliers and researchers who want structured results with less manual checking.

Enter a town, city, postcode or address. Receive business names, source addresses, food hygiene ratings, observation signals and links to the original FSA records.

**Newly observed does not mean newly opened.** Every result has `openingStatus: "not_verified"`.

### Quick start

1. Enter a location, such as `Glasgow`.
2. Choose **Recent records** for a one-off search, or **Monitor changes** for ongoing tracking. A new input form initially selects Recent records.
3. Run the Actor and open **Candidate leads** and **Run summary** in its output.
4. For ongoing monitoring, use the settings below with a maximum run cost of **$0.25**, save them as an Apify task and schedule repeat runs.

```json
{
  "mode": "monitor",
  "location": "Glasgow",
  "maxResults": 25,
  "recentDays": 90,
  "maxPages": 20
}
```

Use one sequential schedule per location and prevent overlapping runs. Apify provides scheduling, dataset exports and API access.

### One-off recent-record searches

Set `mode` to `recent_records` to search eligible records with FSA rating/inspection dates within `recentDays`. These are **recent activity signals, not verified new openings**. Output uses `signalType: "recent_fsa_record_date"` and `trackingStatus: "recent_record_not_new"`.

This mode does not read, create or update a monitoring baseline or pending queue. `firstSeenAt` and `baselineAt` are null; `lastSeenAt` records the current retrieval time. **Repeated searches can return and charge for the same records again.** Use Monitor changes for ongoing tracking.

For a small one-off search, use:

```json
{
  "mode": "recent_records",
  "location": "Glasgow",
  "maxResults": 5,
  "recentDays": 90,
  "maxPages": 20
}
```

Five delivered records cost **$0.075** including the start fee; a **$0.10** run limit covers this example. A recent-record search may return zero if no eligible records fall within the date window.

### How monitoring works

Select **Monitor changes** (`mode: "monitor"`). Existing tasks and API calls that omit `mode` retain this behaviour. Recent-record searches do not affect a monitoring baseline, including one for the same location.

The **first complete scan establishes a baseline**. It returns a limited preview of eligible records with recent rating or inspection dates. Those dates are activity signals, not opening dates.

Later runs compare the source records with that baseline:

| Signal | Meaning |
| --- | --- |
| `baseline_recent_fsa_record_date` | A recent-record preview from the initial baseline. Its tracking status is `baseline_preview_not_new`. |
| `first_seen_after_baseline` | A record newly observed by this monitor. It could describe a business that already existed. |
| `possible_business_identity_change` | A known FSA identifier appeared with a different normalized business name or address. The business change is unverified. |

Unchanged premises and rating-date updates alone do not generate new leads. Records with old or missing rating dates can appear in later monitoring if they are newly observed.

Runs of this Actor using the same location text within your Apify account share a baseline, including runs from different tasks. Case and extra spaces are ignored. Changing result limits or the preview window does not reset monitoring.

The initial preview selects up to `maxResults` records. Existing records outside that preview do not become new leads on the next run.

### Input settings

| Setting | Default | Purpose |
| --- | --- | --- |
| `mode` | `monitor` when omitted; new input forms prefill `recent_records` | Choose a one-off recent-record search or ongoing change monitoring. |
| `location` | Glasgow | Matches source address text. It does not enforce a strict city or council boundary. |
| `maxResults` | 25 | Maximum records to deliver in this run, from 1 to 500. |
| `recentDays` | 90 | Activity-date window for recent-record searches and the first monitoring preview, from 1 to 365 days. |
| `maxPages` | 20 | Maximum source pages per scan attempt, from 1 to 100. Requests up to 5,000 records per page; the source can return smaller pages. |

A complete, stable scan is required before monitoring state changes. Incomplete scans produce no leads and preserve the previous baseline.

### Output

**Candidate leads** contains the delivered records. **Run summary** explains scan completeness, baseline status, detected changes, delivered counts and queued records.

| Fields | Contents |
| --- | --- |
| `runMode` | `recent_records` or `monitor`. |
| `businessName`, `businessType` | Source business name and category. |
| `address`, `postcode` | Source address information, subject to screening. |
| `ratingValue`, `ratingDate` | Published rating and activity date. Scottish ratings can use text such as “Pass”. |
| `opportunityScore`, `opportunityReason` | Rule-based priority ranking and its reasons. The score is not a probability or confirmed purchasing need. |
| `signalType`, `trackingStatus` | Why this candidate is being delivered. |
| `firstSeenAt`, `lastSeenAt`, `baselineAt` | Monitor observation timestamps. In recent-record searches, first observation and baseline are null. |
| `fhrsId`, `sourceFhrsIds`, `source` | FSA identifiers and original source link. |
| `eventId`, `openingStatus` | Delivery identifier and unverified opening status. |

This shortened example uses placeholders and is **illustrative, not a real business record**:

```json
{
  "businessName": "Illustrative Cafe",
  "businessType": "Restaurant/Cafe/Canteen",
  "signalType": "first_seen_after_baseline",
  "trackingStatus": "first_seen_after_baseline",
  "openingStatus": "not_verified",
  "firstSeenAt": "2026-10-04T08:00:00Z",
  "eventId": "0123456789abcdef0123456789abcdef",
  "source": "https://ratings.food.gov.uk/business/<fhrsId>"
}
```

### Pricing and spending limits

Pricing is **$0.05 per Actor start plus $0.005 per delivered record**, equivalent to **$5 per 1,000 records**. Platform usage during the Actor run is included in this price. Memory is capped at 1 GB.

| Delivered records in one run | Event charges |
| --- | --- |
| 0 | $0.05 |
| 10 | $0.10 |
| 25 | $0.175 |
| 100 | $0.55 |

The start fee applies to runs that start, including those returning zero records. Recent-record searches and baseline previews are billable too. Every delivered record in a repeated recent-record search is charged again, even if its identifier is unchanged. Refer to the Actor’s Pricing tab for current prices.

The Actor respects your run spending limit. For example, a **$0.10** limit permits 10 records after the start fee. In Monitor changes mode, eligible undelivered changes and undelivered records from the selected initial preview remain queued for a later run. Queued candidates are checked again and removed if they are no longer visible or eligible. Recent-record searches do not queue undelivered records; another search starts again from the current eligible records.

A failure after output is written but before monitoring delivery is acknowledged can repeat a record on retry. Use `eventId` to deduplicate combined exports; repeated dataset writes can incur record charges. In recent-record searches, unchanged identity and rating information produce the same `eventId`, but repeated delivery is still billable.

### Business and address screening

Screening is mandatory and uses source names and categories. It excludes alcohol-focused venues and retailers, gambling and adult businesses, tobacco/vape name matches, and selected institutional kitchens. Names matching pork, bacon or ham patterns are also excluded.

Ordinary food-service businesses may remain eligible even if they serve alcohol. The Actor does not inspect menus or certify religious suitability.

Records with missing street addresses or possible flat/apartment addresses are held out of delivery. The Actor does not add personal emails or telephone numbers. These checks can miss unsuitable records or exclude suitable ones; they do not establish that every remaining record is free of personal data or suitable for outreach.

### Troubleshooting and support

**Why did a successful run return zero leads?**\
In Monitor changes mode, the baseline may already exist and no eligible changes were observed. In Recent records mode, no eligible records may fall within the activity-date window. Check `runMode`, `monitoringMode`, `scanComplete`, `returned` and `queuedForLaterRuns` in Run summary.

**Why is my scan incomplete?**\
If the page limit was reached, increase `maxPages` or narrow the location. If source pagination changed during scanning, retry later. The existing baseline is preserved.

**Can I get verified openings, owners, emails or phone numbers?**\
This Actor provides candidate signals from FSA records. It does not verify opening dates or enrich owner/contact details.

**How do I get help?**\
Open an issue on the Actor’s Issues tab with the run ID and input settings.

### Data source and attribution

Source: [Food Standards Agency Food Hygiene Rating Scheme API](https://api.ratings.food.gov.uk/help).

Contains public sector information licensed under the [Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/). Retain source and licence attribution when redistributing the data.

Mu Tech is independent of the FSA. This Actor is not endorsed by the FSA. Ratings can change; check the original source before relying on a rating or publishing it as current. See the [FSA terms for using ratings information](https://ratings.food.gov.uk/terms-and-conditions).

# Actor input Schema

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

Recent records is a one-off search that can return the same records again. Monitor changes establishes a baseline and returns later observations or possible identity changes. Existing tasks/API calls without this field continue monitoring.

## `location` (type: `string`):

Example: Glasgow or G12. Uses address-text matching rather than strict city boundaries. Repeat runs with the same location use the existing monitoring baseline; run them sequentially.

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

Maximum candidate records to deliver after filtering. Later monitoring runs retain undelivered eligible changes for subsequent runs.

## `recentDays` (type: `integer`):

Uses the FSA rating/inspection date in recent-record searches and the first monitoring preview. Later monitoring tracks newly observed records and possible identity changes regardless of rating date. Opening dates remain unverified.

## `maxPages` (type: `integer`):

Requests up to 5,000 records per page; the source may return smaller pages. A complete, stable scan is required. Incomplete scans deliver no records and preserve monitoring state. Increase this limit or narrow the location if it is reached.

## Actor input object example

```json
{
  "mode": "recent_records",
  "location": "Glasgow",
  "maxResults": 25,
  "recentDays": 90,
  "maxPages": 20
}
```

# Actor output Schema

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

Filtered FSA records with observation signals, source links and unverified opening status.

## `summary` (type: `string`):

Scan completeness, baseline status, detected changes and delivery counts. Successful monitoring runs can return zero leads.

# 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 = {
    "mode": "recent_records",
    "location": "Glasgow"
};

// Run the Actor and wait for it to finish
const run = await client.actor("mutech/new-food-business-leads-uk").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 = {
    "mode": "recent_records",
    "location": "Glasgow",
}

# Run the Actor and wait for it to finish
run = client.actor("mutech/new-food-business-leads-uk").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 '{
  "mode": "recent_records",
  "location": "Glasgow"
}' |
apify call mutech/new-food-business-leads-uk --silent --output-dataset

```

## MCP server setup

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

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/dQJIg0GJBa6gfrHXV/builds/CsfyS9VTT2hVGFLQM/openapi.json
