UK Food Business First-Seen Leads avatar

UK Food Business First-Seen Leads

Pricing

$2.50 / 1,000 first observed food businesses

Go to Apify Store
UK Food Business First-Seen Leads

UK Food Business First-Seen Leads

Track FHRS food businesses first observed after your prior complete scan. Filter by council, region, business type and rating. No opening-date claims or private contacts.

Pricing

$2.50 / 1,000 first observed food businesses

Rating

0.0

(0)

Developer

AFK Digital

AFK Digital

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

10 days ago

Last modified

Share

API24 — UK Food Business First-Seen Leads

Source: Netcup adf-netcup-01, /opt/APIFY/API24. Apify Actor: afkdigital/uk-food-business-first-seen-leads. Full cloud validation and pricing are described below.

An independent Apify Actor that monitors the Food Standards Agency Food Hygiene Rating Scheme (FHRS) public register. Designed for food suppliers, POS providers, packaging distributors, and commercial-kitchen service firms looking for businesses first observed in their own monitoring scope.

Accuracy notice: An FHRS entry first seen by this Actor is not proof of a newly opened, newly incorporated, or newly registered business. The FSA Search API does not expose a dependable per-establishment registration/publishing timestamp. RatingDate is the hygiene inspection/rating date; collection meta.extractDate is an API data extraction time, not a business publication date.

Public source, licence, and access

FSA currently permits anonymous read access; there are no credentials to request or protected endpoints to bypass. FHRS is public-sector information under OGL v3; attribution is displayed on every result and in the run summary. Commercial use of the public data is allowed subject to licence conditions; that does not authorize using or exposing personal contact details, making unsupported opening-date claims, or ignoring relevant marketing/privacy law.

FSA throttles requests but publishes no fixed request-per-second rate. This Actor uses sequential calls, a default 1,250 ms minimum gap, and short bounded retries on HTTP 403/429/5xx. Exhaustion fails safely rather than circumventing restrictions. The Actor does not scrape web pages, rotate proxies, or call unofficial endpoints.

What counts as a lead?

  1. First full scan: Enumerate every page of every selected local authority and apply all filters. The result is a free, portable baseline. There are no paid leads on this run.
  2. Subsequent full scans: Compare FHRS IDs against the baseline and all previously accepted observations; produce only qualifying unseen IDs. Compare a conservative hashed business-name/address fingerprint to suppress likely FHRSID reassignments.
  3. An observation is recorded and eligible for the custom charge only once successfully emitted. Excess candidates beyond resultLimit are retained as pending observations (with their original firstObservedAt timestamps).
  4. Repeated existing FHRS IDs, filtered-out businesses, suspected ID reassignments, baseline records, API errors, and incomplete scans are never charged as new leads.
  5. Source collection inconsistencies, mismatched page totals, repeated IDs across pages, safety-ceiling overruns, and source failures stop the scan before any new leads are emitted.

Scope safety: A new monitor must have localAuthorityId, exact localAuthority name, or exact FSA region. For existing snapshots, filters must be identical; changing a filter requires a fresh baseline. Excessively large scans fail rather than making a claim based on partial results.

Inputs

FieldFunction
localAuthorityId / localAuthority / regionAt least one required; names match the FSA authority catalogue case-insensitively
businessTypeIdOptional exact FSA business type ID, sent to FSA
businessTypeOptional substring of official FSA business type
keywordOptional substring of official business name, not emails/phones
dateFrom, dateToOptional inclusive inspection date (RatingDate) range
ratingMin, ratingMaxNumeric FHRS rating 0–5, inclusive; pending/non-numeric FHIS results excluded when bounded
resultLimitMax new billable results per run (default 100)
monitorIdStable unique logical monitor ID; enables persistence across separate Apify runs
previousSnapshotOptional exported SNAPSHOT JSON to resume without a persistent monitor; takes precedence
pageSizeRequested FSA page size; actual maximum is server-capped
maxPages / maxAuthoritiesFail-safe completion ceilings (defaults 150 and 40)
requestDelayMsSequential FSA pacing, minimum 1,000 ms

For a repeatable, automatic monitor use the same monitorId on later runs or a stable Apify Task (the task ID is used if no explicit monitorId is provided). A named KV store is created under a one-way hash of that ID combined with Apify's initiating APIFY_USER_ID when available, to avoid cross-user state collisions. Filters are additionally keyed with a SHA-256 scope hash.

When neither monitorId nor an Apify Task ID is present, use the prior run's SNAPSHOT value as previousSnapshot on the next run. Without a previous snapshot, the next run intentionally becomes a new baseline.

Concurrency and anti-repeat safety: A persistent per-user/per-monitor/per-scope Apify Request Queue provides an atomic unique-key claim for each new FHRSID, before the custom paid dataset event. If concurrent runs detect the same new FHRSID, only the first claimant attempts to deliver and charge it; subsequent attempts are suppressed, including attempts with stale snapshots. For best delivery reliability schedule non-overlapping tasks. A hard process crash after a successful claim but before delivery can cause an unbilled skipped observation: the safety model deliberately prefers not charging twice over claiming guaranteed delivery. Refer to RUN-SUMMARY claim fields and the release report.

Output fields

The default Dataset contains two explicitly typed records: recordType: "first-seen-business" for a qualifying paid lead, or a free recordType: "monitor-status" receipt when a successful complete scan finds no billable new business. The latter carries monitorId, status, checkedAt, authoritiesChecked, establishmentsScanned, filterMatches, and resultsEmitted: 0 and does not claim a business opened or was newly registered. Integrations that expect leads only should filter recordType == "first-seen-business". Paid lead records contain these public/derived fields:

fhrsId, businessName, addressLine1–addressLine4, postCode, localAuthority, region, businessType, businessTypeId, ratingValue, ratingNumeric, inspectionDate, sourceExtractAt, firstObservedAt, observationStatus, sourceUrl, matchReason, dataAttribution.

The source URL points directly to the documented official API detail resource: https://api.ratings.food.gov.uk/Establishments/{FHRSID}. No inferred company registration date or publication/update date is fabricated. Phone numbers, personal email addresses, contact details, and local-authority emails are explicitly excluded from the output and snapshot.

Default KV records:

  • RUN-SUMMARY: status, complete scan metrics, counts of newly observed/migrated/pending rows, charging and source information, or safe failure reason.
  • SNAPSHOT: portable state (format, scopeHash, seenIds, hashed name/address identities, pending timestamps, coverage counts).

Local installation, testing and repeat runs

Requires Node.js 22+.

cd /opt/APIFY/API24
npm ci --no-audit --no-fund
npm test
npm run smoke
mkdir -p storage/key_value_stores/default
cp examples/baseline.json storage/key_value_stores/default/INPUT.json
API24_DISABLE_CHARGING=1 npm start
API24_DISABLE_CHARGING=1 npm start
cat storage/key_value_stores/default/RUN-SUMMARY.json

The example monitors FSA local authority 321 (Isles of Scilly), filtering business type Restaurant. First run: baseline-created, one free monitor-status record and zero chargeable leads. Second unchanged run: completed, one free monitor-status record and zero chargeable leads. The test command npm run smoke uses genuine FHRS records and a controlled omitted-record baseline to demonstrate a genuine-ID first-seen diff without claiming the establishment really just opened.

For an Apify task, paste e.g.:

{
"localAuthorityId": 321,
"monitorId": "my-scilly-food-leads",
"businessType": "Restaurant",
"resultLimit": 50,
"maxPages": 10
}

For a different region, see examples/region.json. Exact region names are returned by the FSA Authorities endpoint; scanning too many pages/authorities will fail with a clear message and no partial billable results.

Monetisation and release gating

Price: $0.0025 USD per qualifying first-seen FHRS record ($2.50 per 1,000). The Actor uses exactly one Apify pay-per-event event, first-seen-business, for a qualifying new observation delivered to the Dataset. The free first-run baseline, unchanged repeats, filtered results and source failures are not charged. Spend caps are checked before claiming a record. The run summary counts only the configured custom event using the ChargingManager, excluding any synthetic free dataset event.

Verified Apify monetization: The Actor has a PAY_PER_EVENT pricing configuration with only first-seen-business as the configured paid event at $0.0025. The private cloud baseline and identical-repeat runs each charged zero events; a controlled omission test based on a genuine published FHRS ID charged one event, and replaying the old snapshot charged zero. This is not proof that the test business recently opened. Consult the API24 release report for the latest build and concurrency checks. Avoid simultaneous scheduling for the same monitor to reduce missing-delivery risk following abrupt process interruptions.

Local tests disable monetisation with API24_DISABLE_CHARGING=1. This environment variable is not for a monetized production Actor run.

Limitations and integrity

  • FSA data may be delayed or corrected. Missing records may be withdrawn or moved, not necessarily closed. Newly observed records may be old businesses absent from an earlier extract.
  • A change of FSA FHRSID can reflect a council system migration; the fingerprint check reduces, but cannot eliminate, reassignment false positives.
  • Scotland FHIS ratings are not generally numeric 0–5; choose an unbounded numeric rating filter to include those categories.
  • A bad/old snapshot, altered scope, partial pages, HTTP 403/429 or source schema drift causes a safe failure. No scraping or rate-limit evasions are used.
  • No automated collection of personal emails or phone numbers. Users must comply with UK GDPR and electronic-marketing rules when contacting businesses via independently obtained, lawful channels.
  • This is a read-only public registry monitor, not a company formation, restaurant permit, new-opening or commercial-contacts database.

Files

src/fhrs.js — official v2 HTTP API, pagination, pacing, error handling

src/monitor.js — input validation, scope, FHRS matching, portable snapshots and lead selection

src/main.js — Apify lifecycle, named snapshot state, output and custom PPE charging

.actor/ — Apify Actor definition, input/dataset/output schema

test/ — mocked boundary/error tests and live FSA test script

reports/ — local evidence; deliberately omitted from Docker/Actor uploads

Store QA repair (2026-10-15)

A small official localAuthorityId: 321 scope and stable demo monitorId are prefilled in the input form. Valid first scans and unchanged repeat scans return a free status receipt, allowing Apify automated QA to verify a non-empty dataset without pretending a lead exists or charging for one. The API still requires an explicit authority/region if called without the UI prefill.