UK Public Tenders — Find a Tender + Contracts Finder
Pricing
from $2.10 / 1,000 results
UK Public Tenders — Find a Tender + Contracts Finder
One reliable feed of UK public procurement notices. Merges Find a Tender and Contracts Finder (the Procurement Act 2023 split) into a single schema, with CPV, value, region and keyword filters and a new-notices-only mode.
Pricing
from $2.10 / 1,000 results
Rating
0.0
(0)
Developer
Fatih İlhan
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 hours ago
Last modified
Categories
Share
One feed for UK public procurement notices. Since the Procurement Act 2023 came into force (24 February 2025), UK tenders are split across two government systems: Find a Tender (the above-threshold service, now with the new Act's notice types) and Contracts Finder (below-threshold and many central-government notices). This Actor reads both official OCDS APIs and returns them in a single, identical schema: planning/pipeline notices, tenders, awards and contracts, with buyer, value, CPV codes, region, deadline and supplier. No API key, no scraping, no HTML parsing.
Filter by keyword, CPV code, value, region and notice type, or turn on only-new mode and put it on an Apify schedule to get a daily feed of fresh notices.
Why it is built the way it is
- Both sources, one schema. The same 24 fields for every notice, whichever service it came from. Missing data is
null, never guessed. - If one source is down, you still get the other. A failing source is retried with exponential backoff and
Retry-Afterhandling; if it still fails, the other source's notices are returned, the run does not fail, and the failure is written toRUN_SUMMARY. - Complete, not "first page". Every page is read until the feed is exhausted. A run that stops early says so in
RUN_SUMMARY(andonlyNewwill not skip what was not read). - Server-side filters that lose notices are not used. Both APIs have a
stagesfilter that silently drops notices (checked against the live feeds), so all filtering is done after fetching. - One record per call, even across the two services. The same tender is often published on both with different ids and slightly different titles; those are detected (buyer + title + deadline) and returned once, listing both sources.
- Pay only for results. No placeholder rows, no error rows. Errors live in
RUN_SUMMARY, not in your dataset.
Example inputs
IT and software opportunities from the last 24 hours (the default window; by default you get tender and planning notices)
{"cpvCodes": ["72"]}
Who won? Awarded contracts are opt-in: add award (and contract for contract details) to noticeTypes
{"cpvCodes": ["72"],"noticeTypes": ["award", "contract"],"publishedFrom": "2026-10-01"}
To get open tenders, pipeline and awards together, list every type: "noticeTypes": ["planning", "tender", "award", "contract", "implementation"]. In the Console, pick them in the "Notice types" box.
Everything from specific buyers (case-insensitive, partial match on the buyer name)
{"buyers": ["Ministry of Defence", "Transport for London"],"publishedFrom": "2026-09-01"}
Contracts worth £100k or more
{"minValue": 100000,"noticeTypes": ["tender", "award"]}
Daily new IT tenders (schedule this Actor to run every morning)
{"cpvCodes": ["72"],"onlyNew": true}
Create an Apify Schedule (for example cron 0 7 * * *) for this input. The first run returns the last 24 hours (or whatever publishedFrom you set); every later run returns only what was published since. State is stored in the named key-value store uk-public-tenders-state under your account.
Input
All fields are optional.
| Field | Type | Meaning |
|---|---|---|
keywords | string list | Title or description contains any of these (case-insensitive, from the start of a word: cyber matches cybersecurity). |
cpvCodes | string list | CPV prefix match, e.g. 72 = IT services, 72212 = application software, 45 = construction. Checks the notice's main and additional CPV codes. |
publishedFrom / publishedTo | string | YYYY-MM-DD or ISO-8601 datetime (UTC if no zone). A bare publishedTo date includes the whole day. Default: the last 24 hours. |
minValue / maxValue | integer (GBP) | Keep notices whose value range overlaps this range. Notices that state no value are excluded when a value filter is set. |
noticeTypes | list | planning, tender, award, contract, implementation. Default: tender + planning; awards and contracts are opt-in (see the example above). |
buyers | string list | Buyer (contracting authority) name contains any of these texts: case-insensitive, partial match (nhs, transport for london, council). Notices with no buyer name never match. |
regions | string list | UK region names or NUTS codes (London, Scotland, UKI, UKD7). Names and codes match each other (against both region_code and region_name); England covers all nine English regions. |
onlyNew | boolean | Only notices not returned by an earlier run with the same filters (new notices and new versions of known notices). |
sources | list | fts, contracts_finder. Default: both. |
To cap the number of results (and your spend), use the Apify "Maximum charged results" run option. The Actor returns at most that many notices, newest first, and reports in RUN_SUMMARY.truncation that it truncated and how many matches were left out.
Output
One dataset item per procurement (ocid). If the same procurement appears several times in the window (tender, then award, then amendments), the latest matching version is returned.
| Field | Description |
|---|---|
notice_id | Notice identifier (097437-2026 on Find a Tender, a UUID on Contracts Finder). |
related_notice_ids | Notice ids of same-source copies folded into this record (see "Known limitations"). Empty list when there are none. |
source | List: ["fts"], ["contracts_finder"], or both when the same ocid is in both services. |
ocid | Open Contracting process id; stable across the notices of one procurement. |
title | Title exactly as published. |
title_clean | The title without leading reference prefixes such as CA18567 - , RFQ 2026/43 - , GB-Glasgow: or UK4 Tender Notice: (the original is in title). |
description | Notice text. On Contracts Finder, an appended "Additional information:" section is dropped when it only repeats the main description, and kept when it adds something. |
buyer_name, buyer_id | Contracting authority and its identifier. |
notice_type | planning, tender, award, contract or implementation. |
status | Procurement status as published (active, complete, planned, ...). |
published_date | UTC ISO-8601 publication time of the notice version. |
deadline_date | Tender submission deadline (UTC ISO-8601). null on award notices: a closed deadline is not an action date for an award. |
tender_deadline_date | The published submission deadline, kept on every notice type, including awards. |
value_min, value_max, currency | Value as published (see "Known limitations"). |
cpv_codes | All CPV codes on the notice, main code first. |
region_code | List of NUTS codes, e.g. ["UKK14"]. Contracts Finder region names are mapped to their NUTS1 code (Scotland -> UKM); non-UK codes such as CY are left as published. Empty list if unknown. |
region_name | List of region names (NUTS1), e.g. ["South West"]; United Kingdom for a nationwide UK; England appears here only (it has no NUTS1 code). Empty list if unknown. |
procedure_type | For example "Open procedure", "Call-off from a framework agreement". |
award_supplier | Awarded supplier name(s), if any (several are separated by ; ). |
url | The notice page on Find a Tender / Contracts Finder, never an attachment/download link. On Find a Tender it is built from the notice id; on Contracts Finder it comes from the notice's own page link, so it is null in the rare case none is published. |
source_url | The API record the data was read from. |
fetched_at | When the Actor fetched it (UTC). |
Example record (real, from a live run)
{"notice_id": "cab39ee0-c192-4fb2-9253-472214e58ca7","related_notice_ids": [],"source": ["fts","contracts_finder"],"ocid": "ocds-b5fd17-4321ebe7-2ddb-47fa-81f9-fa095553b41b","title": "CA18567 - RFQ 2026/43 - Development of a Dublin Belfast Economic Corridor Investment Land Guide","title_clean": "Development of a Dublin Belfast Economic Corridor Investment Land Guide","description": "The DBEC Partnership wishes to appoint a suitably qualified and experienced consultant to produce an Investment Land Guide that will strengthen the Dublin Belfast Economic Corridor's investment proposition.\n\nTo access this competition: \n\nRegistered:\nLogin to https://suppliers.multiquote.com and v...","buyer_name": "Newry, Mourne and Down District Council (NMD)","buyer_id": "GB-CFS-333373","notice_type": "tender","status": "active","published_date": "2026-10-14T13:42:19Z","deadline_date": "2026-10-30T12:00:00Z","tender_deadline_date": "2026-10-30T12:00:00Z","value_min": null,"value_max": 25000,"currency": "GBP","cpv_codes": ["79411100","72221000","73210000"],"region_code": ["UK"],"region_name": ["United Kingdom"],"procedure_type": "Open procedure","award_supplier": null,"url": "https://www.contractsfinder.service.gov.uk/Notice/cab39ee0-c192-4fb2-9253-472214e58ca7","source_url": "https://www.contractsfinder.service.gov.uk/Published/Notices/OCDS/Search?publishedFrom=2026-10-12T12:00:00Z&publishedTo=2026-10-15T14:06:46Z&limit=100&cursor=cHVibGlzaGVkRnJvbT0yMDI2LTEwLTEyVDEyOjAwOjAwWnxwdWJsaXNoZWRUbz0yMDI2LTEwLTE1VDE0OjA2OjQ2WnxsaW1pdD0xMDB8bmV4dEN1cnNvcj03ODY3OTg=","fetched_at": "2026-10-15T14:06:49Z"}
RUN_SUMMARY
Every run writes a RUN_SUMMARY record to the key-value store, including runs that return nothing or in which a source failed. For each source it reports pages and requests, releases fetched, how many were filtered out and why, how many were de-duplicated, retries and rate-limit responses, errors and duration; plus whether the run was truncated by the item limit, and the onlyNew state. A zero-result run can therefore always be told apart from "a source was down".
Known limitations
- Long date ranges run slowly. The government APIs rate-limit clients: in testing, a burst of about 20 requests, then roughly 5 pages (up to 500 notices) a minute, and a 120-second pause each time the limit is hit. About 700 notices a day are published across both services, so one day takes seconds, a 3-day pull of everything took under a minute in testing, and a week or more can take several minutes or longer. Recommended use: a daily Apify schedule with
onlyNew: true(see the example above). Each run then reads only what is new and finishes quickly. Use wide date ranges only for one-off backfills and narrow them with filters where you can. - Contracts Finder often has no region. Roughly half of its notices give only a postcode or country, so
region_code/region_nameare empty and they can never match aregionsfilter. - Some Find a Tender records have no CPV code. They cannot match a
cpvCodesfilter, so they will not appear in CPV-filtered results even if they concern that sector. (In testing about 3% of Find a Tender records had none, after reading CPV from lots, items and awards; Contracts Finder records always had one.) - Contracts Finder award values are tender values. For an award notice,
value_min/value_maxare the notice's tender-level figures (typically the estimated or framework value), not necessarily the amount finally awarded. Find a Tender award notices without a tender value fall back to the award or contract value, as a range, never summed. - Notices with no value never pass a value filter (
minValue/maxValue); a non-GBP value does not either. - Notices re-published under a new id are folded into the newest one. Buyers sometimes publish the same notice twice within minutes (new notice id, new
ocid, identical text). Within one service, notices with the same buyer id, title, description and type that were published within 48 hours of the newest one are returned as a single record; the older notice ids are listed inrelated_notice_ids. Deadlines and values are not compared, so two genuinely separate calls that reuse one text within 48 hours (for example lots published as separate notices) are also folded: checkrelated_notice_idsif that matters to you. - Cross-source de-duplication is a match, not an id lookup. The two systems never share process ids, so a call published on both is recognised by the same buyer, the same title once reference prefixes are removed, the same tender-deadline day and the same notice type. This is deliberately strict: it applies to tender and planning notices only (awards repeat too often to be matched safely), and a copy whose title was reworded, or that has no deadline (most planning notices), is not matched and appears twice. A merged record keeps the later copy's fields and fills its gaps from the other.
- Personal data is not output. Procurement officers' contact names and e-mails in the source data are deliberately left out.
Data source and licence
Data comes from the official OCDS APIs of:
- Find a Tender Service (Cabinet Office)
- Contracts Finder (Crown Commercial Service / Cabinet Office)
Contains public sector information licensed under the Open Government Licence v3.0. This Actor is not affiliated with or endorsed by the UK Government. Notice content remains the responsibility of the publishing authority; check the notice itself before bidding.