UK Public Tenders Scraper - FTS + Contracts Finder avatar

UK Public Tenders Scraper - FTS + Contracts Finder

Pricing

$3.00 / 1,000 notice returneds

Go to Apify Store
UK Public Tenders Scraper - FTS + Contracts Finder

UK Public Tenders Scraper - FTS + Contracts Finder

UK tenders, contract awards and pipeline notices from the official Find a Tender and Contracts Finder OCDS APIs: buyer contacts, CPV, value, deadline.

Pricing

$3.00 / 1,000 notice returneds

Rating

0.0

(0)

Developer

Jason

Jason

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

Pulls UK public procurement notices from the two official government services, Find a Tender (above-threshold and Procurement Act 2023 notices for the whole UK) and Contracts Finder (below-threshold and legacy notices, mainly England), through their public OCDS APIs. No API key, no browser automation, no login. You get one flat JSON record per notice release with the buyer and its contact email, CPV codes, estimated value, submission deadline, award suppliers and value, and a link to the notice page, filtered by date window, stage (tender, award, planning), keyword, CPV prefix, region and minimum value. Both feeds are read newest-first and merged into one de-duplicated stream of new UK tenders, awards and pipeline notices. The two services together publish roughly 500 to 620 releases per weekday, so set maxItems to match the window you ask for - see Limits and freshness.

What you get

Every record contains:

  • id - <source>:<ocid>:<release id>, source (find-a-tender or contracts-finder), url - the public notice page, ocid, releaseId (Find a Tender notice number such as 084162-2026, or the Contracts Finder notice GUID plus sequence)
  • stage - the OCDS release tag, stageGroup (tender, award, planning, or other for the rare implementation release), tags (the raw array). Tags seen across 1,695 consecutive releases (2-4 September 2026): award 1,108, tender 261, planning 130, awardUpdate 69, tenderUpdate 62, planningUpdate 32, tenderCancellation 17, contractAmendment 6, contractTermination 5, tenderAmendment 4, implementation 1
  • title, description (first 5,000 characters), status (active, complete, planning, cancelled, ...), language
  • buyerName, buyerId (Companies House, charity or PPON identifier when published), buyerRegion (NUTS/ITL code such as UKG33, Find a Tender only), buyerRegionName (West Midlands, Scotland, ...), buyerLocality, buyerPostcode, buyerCountry, buyerEmail, buyerPhone, buyerContactName, buyerWebsite
  • deliveryRegions - where the contract is performed (NUTS codes on Find a Tender, region names on Contracts Finder)
  • publishedDate - release date, ISO 8601 with UK offset; deadline - tender submission deadline (tenderPeriod.endDate), or the expression-of-interest / early-engagement due date for planning notices
  • valueAmount, valueCurrency - the buyer's estimated value (net amount when both net and gross are published, else gross; sum of lot values when no total is given; the award total when no estimate exists)
  • cpvCodes (array, de-duplicated across lots and awards), cpvLabels (matching descriptions), mainCategory (goods, services, works)
  • procurementMethod (open, selective, limited, direct), procurementMethodDetails (Open procedure, Call-off from a framework agreement, ...), aboveThreshold, suitableForSme, suitableForVcse, lotCount
  • awardSuppliers (array of supplier names), awardValue, awardCurrency, awardDate, contractStartDate, contractEndDate
  • fetchedAt - ISO timestamp of the run

The dataset has two views: Overview (title, buyer, region, CPV, deadline, value, suppliers, link) and Buyer contacts (contact name, email, phone, town, postcode, website).

Input

FieldTypeDefaultDescription
sourcesstring[]bothfind-a-tender, contracts-finder, or both.
daysBackinteger3Look-back window in days ending now. Find a Tender is filtered on the notice's last update time, Contracts Finder on its publication time. Ignored when dateFrom/dateTo are set.
dateFromstring-Start of the window, YYYY-MM-DD (00:00 UTC).
dateTostringnowEnd of the window, YYYY-MM-DD (23:59:59 UTC).
keywordsstring[]noneCase-insensitive terms matched against title, description and buyer name; any match keeps the record.
stagesstring[]alltender (opportunities, including updates and cancellations), award (awards and contract changes), planning (pipeline and early engagement). A raw OCDS tag such as tenderUpdate is also accepted.
cpvPrefixesstring[]allCPV codes or prefixes, 2 to 8 digits. 72 = IT services, 45 = construction, 33 = medical, 48 = software, 79 = business services, 85 = health and social care.
regionsstring[]allCase-insensitive substrings matched against the buyer's region code and name, town, postcode, country and the contract's delivery regions, plus the UK nation implied by any NUTS code: "West Midlands", "London", "Scotland", "England", "Manchester", "UKG". This is a coverage filter, not a buyer-address filter - see the note below the table.
minValueinteger0Keep only notices whose estimated value (or award value when no estimate exists) is at least this amount, in the notice currency (GBP). Notices with no value are dropped when set.
maxItemsinteger500Stop after this many kept notices, newest first across both sources. Anything smaller than the window's volume drops the oldest notices in that window - size it to the window (see Limits and freshness).

Example - IT and software tenders from the last week, England only, worth at least GBP 100,000:

{
"daysBack": 7,
"stages": ["tender"],
"cpvPrefixes": ["72", "48"],
"regions": ["England"],
"minValue": 100000,
"maxItems": 1000
}

Example - the complete unfiltered feed, scheduled daily (the overlapping window absorbs publication lag, and 2,000 comfortably covers the roughly 1,000-1,250 releases two weekdays produce):

{ "daysBack": 2, "maxItems": 2000 }

Bad CPV codes, unknown sources or stages, negative values and malformed dates fail fast: the run stops with the validation message as its status before any request is made.

How regions matches. A notice is kept when the term appears anywhere in the buyer's own address or in the contract's delivery area. That is deliberate - most users want "work I could bid for in Scotland", and a Coventry buyer running a UK-wide framework is genuinely relevant to a London supplier - but it means regions: ["London"] also returns buyers based elsewhere whose contract is delivered UK-wide. If you want the buyer's own location only, leave regions empty and filter the output on buyerRegionName, buyerLocality or buyerPostcode (Find a Tender publishes a NUTS code for every buyer; Contracts Finder publishes the town and postcode).

Output example

A real Find a Tender record from a live run (2026-09-07), description shortened:

{
"id": "find-a-tender:ocds-h6vhtk-06bd70:084162-2026",
"source": "find-a-tender",
"url": "https://www.find-tender.service.gov.uk/Notice/084162-2026",
"ocid": "ocds-h6vhtk-06bd70",
"releaseId": "084162-2026",
"stage": "tender",
"stageGroup": "tender",
"tags": ["tender"],
"title": "Private Medical Insurance",
"description": "Orbit is seeking a suitable supplier to provide Private Medical Insurance (PMI) as part of Orbit's employee benefits package to its employees. The awarded supplier will be expected to deliver a high-quality, cost-effective and accessible scheme for eligible employees ...",
"buyerName": "ORBIT GROUP LIMITED",
"buyerId": "GB-COH-IP28503R",
"buyerRegion": "UKG33",
"buyerRegionName": "West Midlands",
"buyerLocality": "Coventry",
"buyerPostcode": "CV3 2SU",
"buyerCountry": "United Kingdom",
"buyerEmail": "group.tenders@orbit.org.uk",
"buyerPhone": null,
"buyerContactName": null,
"buyerWebsite": "https://www.orbit.org.uk",
"deliveryRegions": ["UKC", "UKD", "UKE", "UKF", "UKG", "UKH", "UKI", "UKJ", "UKK"],
"publishedDate": "2026-09-05T06:25:48+01:00",
"deadline": "2026-09-22T10:00:00+01:00",
"valueAmount": 2172000,
"valueCurrency": "GBP",
"cpvCodes": ["66512200"],
"cpvLabels": ["Health insurance services"],
"mainCategory": "services",
"procurementMethod": "open",
"procurementMethodDetails": "Open procedure",
"aboveThreshold": true,
"suitableForSme": true,
"suitableForVcse": null,
"status": "active",
"lotCount": 1,
"awardSuppliers": [],
"awardValue": null,
"awardCurrency": null,
"awardDate": null,
"contractStartDate": null,
"contractEndDate": null,
"language": "en",
"fetchedAt": "2026-09-07T06:19:46.085Z"
}

A Contracts Finder award from the same run looks like this (fields common to both sources omitted):

{
"id": "contracts-finder:ocds-b5fd17-4a336c05-e4fd-4530-86b6-b037c17f1acd:883ce98b-3552-4303-bd02-5a00c8d66519-913088",
"source": "contracts-finder",
"url": "https://www.contractsfinder.service.gov.uk/Notice/883ce98b-3552-4303-bd02-5a00c8d66519",
"stage": "award",
"title": "National Roads Telecommunications Service 3 (NRTS3) Independent Assurance Review",
"buyerName": "National Highways Limited",
"buyerLocality": "Birmingham",
"buyerPostcode": "B4 6GA",
"buyerEmail": "James.mayer@nationalhighways.co.uk",
"deliveryRegions": ["North East", "North West", "Yorkshire and the Humber", "East Midlands", "West Midlands", "East of England", "London", "South East", "South West"],
"publishedDate": "2026-09-05T22:20:36+01:00",
"valueAmount": 65000,
"cpvCodes": ["79411000"],
"procurementMethodDetails": "Call-off from a framework agreement",
"suitableForSme": false,
"awardSuppliers": ["Turner & Townsend Infrastructure Limited"],
"awardValue": 65000,
"awardCurrency": "GBP",
"awardDate": "2026-08-07T00:00:00+01:00",
"contractStartDate": "2026-08-10T00:00:00+01:00",
"contractEndDate": "2026-09-18T23:59:59+01:00"
}

valueAmount and awardValue are null when the buyer published no figure. The run also writes a SUMMARY record to the key-value store with the number of releases scanned and kept per source, how many were dropped by each filter, and the resolved date window.

Pricing

Pay per result: US$0.003 per notice delivered (US$3 per 1,000 notices). You are charged only for records pushed to the dataset; empty runs cost nothing. Runs on the Apify free plan are limited by the platform's free-tier usage allowance.

Data source and licence

Limits and freshness

  • Volumes. Measured on 1-4 September 2026 by exhausting each 24-hour window: Find a Tender published 457, 371, 436 and 471 releases on those four weekdays (about 370 to 470 per weekday), Contracts Finder 107, 129, 138 and 148 (about 105 to 150) - together roughly 500 to 620 releases per weekday. Weekends are far quieter. Find a Tender's mix is about two thirds awards (58-68% across those days), a quarter tender notices (21-27%) and a tenth planning notices (10-15%); on Contracts Finder more than 9 in 10 releases are awards.
  • Size maxItems to the window - the defaults are a sample, not a complete archive. maxItems counts records kept after filtering, so a keyword, CPV, region or value filter normally keeps a run well under the default 500. An unfiltered run is different: three working days hold about 1,700 releases (2-4 September 2026 returned exactly 1,695), so the default maxItems: 500 returns the newest 500 and stops, logging limitReached: true (also recorded in the SUMMARY key-value record). Because the merged stream is newest-first, that truncation drops the oldest notices in the window. For a gap-free unfiltered feed, schedule {"daysBack": 2, "maxItems": 2000} daily.
  • Notices appear in the APIs shortly after publication and both services publish seven days a week (weekends are quiet). The Find a Tender window is on update time, so amended notices come round again as tenderUpdate / awardUpdate releases with a new releaseId; a daily run with daysBack: 2 overlaps enough to absorb any publication lag.
  • Stage filtering is done locally on the OCDS tag. The APIs' own stages parameter is deliberately not used: in testing it dropped every Procurement Act 2023 (UK4) tender notice on Find a Tender (for 2026-09-03 it returned 3 releases where tag-based filtering finds about 100).
  • Rate limit and run time. Pages are 100 releases (the APIs' maximum) and the Actor follows links.next until the window is exhausted or maxItems is reached. Find a Tender enforces an undocumented allowance of about 12 requests per client that refills only a couple of requests a minute; beyond it the API answers 429 Too Many Requests with the body "Rate limit of 12 exceeded" and Retry-After: 120 (measured 7 September 2026). The Actor spaces Find a Tender pages 5 seconds apart, so a default run (about 6 pages, 500 notices, roughly 35 seconds) never touches the limit; a run of several thousand notices will hit it once or twice and waits out the two-minute Retry-After automatically instead of failing. Both services also get retries with exponential back-off on 429 and 5xx.
  • Window edges. Both services read the offset-less timestamps their docs specify as UK local time, and Find a Tender ignores an explicit Z or +01:00 offset, so the Actor sends the London clock reading of the instant you asked for. daysBack therefore really does end at the moment the run starts (no missing final hour during British Summer Time), and dateFrom/dateTo are exact UTC midnights.
  • Each OCDS release is one record. The same procurement (ocid) can appear several times over its life (planning, tender, update, award); use ocid to group them.
  • Dates are returned as the source publishes them (ISO 8601 with the UK offset). Values are not converted between currencies; virtually all are GBP.
  • Contracts Finder buyer addresses carry no region code, so buyerRegion / buyerRegionName are null there; the regions filter still works through the buyer's town and the delivery regions.

Use cases

  • Daily lead feed of new UK tenders in your CPV codes and regions, with the buyer's procurement email for bid/no-bid outreach.
  • Competitor and incumbent tracking: award notices show which suppliers win what, at what value, and when the contract ends (contractEndDate) so you can prepare for the re-tender.
  • Market research and compliance: archive every notice for a sector or buyer, or rebuild a history with dateFrom/dateTo.

Support

Open an issue on the Actor's Issues tab on Apify Store. Replies within 14 days.