UK Tenders Scraper - Contracts Finder & Find a Tender (OCDS) avatar

UK Tenders Scraper - Contracts Finder & Find a Tender (OCDS)

Pricing

from $7.30 / 1,000 tender returneds

Go to Apify Store
UK Tenders Scraper - Contracts Finder & Find a Tender (OCDS)

UK Tenders Scraper - Contracts Finder & Find a Tender (OCDS)

For bid teams and public-sector sales: UK tenders and contract awards from both official services at once, Contracts Finder and Find a Tender. On 2026-09-09 alone that was 580 notices (136 plus 444). Buyer, CPV, value, deadline, region and winning supplier, duplicates merged. No API key.

Pricing

from $7.30 / 1,000 tender returneds

Rating

0.0

(0)

Developer

NeverEmpty

NeverEmpty

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

For suppliers bidding for public work, bid and framework research, and competitor award tracking: UK public sector tenders and contract awards from both official services in one table — the buyer, CPV codes, value and currency, deadline, delivery region, procedure, status and the winning suppliers, one row per procurement.

A supplier watching one service misses the other. The UK publishes procurement notices on Contracts Finder (lower-value opportunities and awards) and on Find a Tender (the central digital platform under the Procurement Act 2023, including above-threshold notices). This Actor reads the official OCDS APIs of both, compiles every notice about the same procurement into one row, and merges the tenders that appear on both — a merged row lists both OCIDs, both notice links and foundOnBothServices: true, and takes the more advanced state of the two.

Measured on the full set of notices published or updated on 2026-09-09: 136 Contracts Finder releases and 444 Find a Tender releases, read page by page, kept in the repository as a test fixture. On that one day, 8 Contracts Finder procurements and 23 Find a Tender procurements published more than one notice — so a row keeps the value from the tender notice and the supplier from the award notice instead of showing you whichever arrived last. Across a 7-day run (2026-09-05 to 2026-09-11), 14 tenders were merged on an exact match and 19 of the 20 further pairs a reviewer found were caught once the two services' title conventions were normalised — and a pair is merged only when enough matches, because one council published 5 transport-route notices with identical titles and buyer on a single day.

Two of the services' own filters quietly lie, so this Actor does not use them. Contracts Finder silently ignores a keyword parameter — asked for software it returned the same 100 notices in the same order as with no keyword, and only 13 of them mention software. Find a Tender's stages filter returns only part of the stage: 11 of the 95 tender-stage notices of that day, 45 of 283 award-stage, 3 of 55 planning.

It also does not stop at Contracts Finder's first 100 notices. That service sometimes returns exactly 100 notices and no link to the next page even when there are more; this Actor treats a full page with no next link as a cut list, splits the time window in half and reads both halves, until every window returns fewer than 100. And a value of 0 or 1 pound — a placeholder some buyers type (3 notices on 2026-09-09) — is returned as value: null with valuePlaceholder: true, never as a price.

No API key. No proxy. No browser. Data under the Open Government Licence v3.0. Export as JSON, CSV or Excel.

What one row looks like

A real row from 2026-09-09 (Find a Tender, notice 085589-2026):

FieldValue
titleMaritime Domain Analysis and Reporting
buyerNameHome Office
tenderStateopen
value / valueGross / currency100000 / 120000 / GBP
deadline2026-09-22T12:00:00+01:00 (the clock time is kept)
cpvCodes["72316000","35720000"]
procurementMethodDetailsBelow threshold - open competition
services["find-a-tender"]
noticeUrlhttps://www.find-tender.service.gov.uk/Notice/085589-2026

What this Actor gets right (measured on 2026-09-11)

All numbers below come from the full set of notices published or updated on 2026-09-09: 136 Contracts Finder releases and 444 Find a Tender releases, read page by page. That set is included in the repository as test data, and the tests recount it.

1. One tender is one row, even when it was published three times

A procurement produces several notices: the tender, a correction, the award, an update to the award. On 2026-09-09 alone, 8 Contracts Finder procurements and 23 Find a Tender procurements published more than one notice. Award notices on Find a Tender often do not repeat the value or the deadline.

This Actor compiles the notices of one procurement with the OCDS merge rules (later notices win, and awards are matched by id), so a row keeps the value from the tender notice and the supplier from the award notice. 580 notice releases became 540 tenders, with no tender returned or charged twice. A supplier re-published with the same amount under a new award id is counted once in awardedValue.

2. A tender on both services is returned once, and never merged with a different lot

The two services give the same tender different OCIDs (ocds-b5fd17-... on Contracts Finder, ocds-h6vhtk-... on Find a Tender), and neither links to the other: measured over the whole day, 0 shared OCIDs and 0 cross-references. So the same tender can only be matched by title and buyer.

The two services also write the same tender differently. Contracts Finder puts a reference in front of many titles (CA18103 - Adult Skills Fund Course Delivery against Adult Skills Fund Course Delivery) and adds - AWARD to some award titles; buyer names differ in the same way (The Council of the Borough of Kirklees against Kirklees Council, ... LIMITED, DVSA - Driver and Vehicle Standards Agency against Driver & Vehicle Standards Agency). This Actor removes those differences before comparing.

That match is still dangerous: one council publishes several lots with the same title (on 2026-09-09, one council published 5 transport route notices with identical titles and buyer). So a pair is merged only when exactly one tender on each service carries that title and buyer.

Measured on every row of a 7-day run (2026-09-05 to 2026-09-11): 14 tenders were merged by the exact match, and a reviewer found 20 more pairs published on both services. With the differences above removed, 19 of those 20 are now merged and the 14 stay merged. The one left is a Contracts Finder notice whose buyer name was cut short on the notice itself (University Hospitals Sussex NHS Foundati), so it can still appear twice, once per service. Tenders that do not match on title and buyer after this cleaning are not merged, so "one row per tender" holds for matching titles and buyers, not for every possible duplicate.

A merged row lists both OCIDs, both notice links, and foundOnBothServices: true, and takes the more advanced state of the two (a tender still "active" on Contracts Finder but awarded on Find a Tender is returned as awarded). When the two services publish different values, value is the value of the service named in valueSource and the other service's value is kept in valueOnOtherService (measured: Non-Domestic EPCs is 15,000 on Find a Tender and 25,000 on Contracts Finder).

3. Keywords and stages are filtered here, because the services do not filter them honestly

  • Contracts Finder silently ignores a keyword parameter: asked for software, it returned the same 100 notices in the same order as with no keyword, and only 13 of them mention software. Find a Tender rejects it.
  • Find a Tender's stages filter returns only part of the stage: 11 of the 95 tender-stage notices of the day, 45 of 283 award-stage notices, 3 of 55 planning notices.

So this Actor reads every notice of the chosen days and applies keywords (whole words, in title and description), CPV, stage, value, region and buyer itself. The input column of every row says exactly what was searched.

4. Values and deadlines are not invented

  • A value of 0 or 1 pound is a placeholder some buyers type (3 notices on 2026-09-09). It is returned as value: null with valuePlaceholder: true, never as a price.
  • deadline keeps the time of day and deadlineStatus is open, closed or not-published. A tender whose notice still says "active" but whose deadline has passed is tenderState: closed, not open.
  • A notice without a value or deadline returns null, not 0.

5. It does not stop at Contracts Finder's first 100 notices

Contracts Finder sometimes returns exactly 100 notices and no link to the next page, even when there are more. Measured on 2026-09-11: asked for all of 2026-09-10, it returned 100 notices published between 10:07 and 18:31 and no next page; asked for 00:00 to 10:07 of the same day, it returned 8 more. A 7-day request ended the same way, after 100 notices from a single day. A tool that follows the next link reads 100 and stops, without an error.

This Actor treats a full page without a next link as a sign that the list was cut, splits that time window in half and reads both halves again, until every window returns fewer than 100. A notice returned twice by overlapping windows is counted once. For 2026-09-10 that gives 108 notices, the same number as counting the day in four 6-hour windows by hand; for the 7 days to 2026-09-11 it gives 498 Contracts Finder notices instead of 100.

6. It reads both services slowly enough not to be blocked

Both services answer "Rate limit of 12 exceeded. Please retry after 120 seconds" (HTTP 429) when asked too quickly. Measured on 2026-09-11: with 6.5 seconds between requests, every 7-day run was stopped once or twice, the first time 104 to 130 seconds in. This Actor now leaves 10.5 seconds between requests and, if it is still told to wait, waits exactly as long as the service asks.

Measured run times, so you can plan for them:

Days readNotices readRequestsWaits imposed by the servicesRun time
1 (2026-09-09)5807045 seconds
7 (2026-09-04 to 2026-09-10)3,125381533 seconds (about 9 minutes)

A 31-day run reads roughly 150 pages, so expect around half an hour. If a run comes close to its time limit, it stops reading, returns what it has read and adds a row naming the days it did not read.

7. It never returns an empty table without saying why

statusMeaningCharged?
okA tenderYes
no-resultsBoth services answered and nothing matched. The row says how many notices were read and which filters can drop a tenderNo
failedA service could not be read. If the other one could, its tenders are still returned, and the row says so. Only a temporary failure (no answer, a request limit, a server error) is described as likely to work laterNo
incompleteSome pages were read, then a page failed, the page limit was reached, or the run came close to its time limit. What was read is returned, and the row names the periods that were not readNo
bad-inputThe input was rejected before anything was sent (a wrong date, a CPV code that is not 8 digits)No

How complete the columns are

Measured on the 540 tenders of 2026-09-09. The services publish these fields unevenly, and this Actor returns null rather than guessing:

ColumnFilled
title, buyerName, buyerEmail, noticeUrl540 of 540 (100%)
suppliers (winning companies)375 of 540 (69%)
cpvCodes307 of 540 (57%)
deliveryRegions218 of 540 (40%)
value202 of 540 (37%)
deadline202 of 540 (37%)
buyerPhone155 of 540 (29%)

Contracts Finder fills value and deadline far more often than Find a Tender: in notice releases, 81% and 99% on Contracts Finder against 26% and 18% on Find a Tender.

Input

FieldDefaultWhat it does
keywordsnoneWords to find in the title or description, as whole words, ignoring case. A tender matches when it contains any of them
cpvCodesnone8-digit CPV codes. 72000000 matches every code under it, such as 72212000. Main and additional CPV codes are both checked
publishedFrom7 days agoFirst day, YYYY-MM-DD, UK time. Both services select notices by the date they were published or last changed
publishedTotodayLast day, YYYY-MM-DD, UK time. At most 31 days per run
sourcesbothcontracts-finder, find-a-tender, or both
stagesallplanning, tender, award. The stage is the most advanced one reached in the notices read
onlyOpenfalseKeep only tenders open for bids: an active call for tenders (tenderState: open) whose deadline is in the future. Planning notices, awards and cancellations are dropped even when they show a future date, and so are tenders without a published deadline
minValue / maxValuenoneValue range in pounds. Tenders without a value in pounds are dropped when a range is set
regionsnoneWords matched against the delivery region (Find a Tender's NUTS codes such as UKI32 are turned into names such as London). If a tender names no delivery region, the buyer's region is used
buyersnoneWords in the buyer name, such as NHS or Home Office
maxResults200The most tender rows returned, most recently updated first. You are charged per tender row

With no dates given, the last 7 days are read.

Output columns

services, foundOnBothServices, ocid, otherOcids, title, description, buyerName, buyerId, buyerEmail, buyerPhone, buyerRegion, stage, tenderState (planned, open, closed, awarded, cancelled, terminated), tenderStatusRaw, cpvMain, cpvMainDescription, cpvCodes, value, valueGross (including VAT, when published), valueMin (lower end of a range), currency, valuePlaceholder, valueSource (which service the value comes from), valueOnOtherService (the other service's value, on merged rows where both publish one), deadline, deadlineUtc, deadlineStatus, daysUntilDeadline, deliveryRegions, deliveryRegionCodes, procurementMethod, procurementMethodDetails, aboveThreshold, suppliers, supplierIds (Companies House numbers appear as GB-COH-...), awardedValue, awardedCurrency, awardDate, firstNoticeInWindow, lastUpdated, releaseTags, releasesSeen, noticeUrl, noticeUrls, checkedAt, plus status, note and input.

A row reflects the notices published in the chosen days. If a tender was published last month and only its award appeared this week, the row carries what the award notice and any other notice in the window say.

Personal data

The buyer contact returned is the email and telephone that the contracting authority publishes on the official notice. The separate contact-name field the services also publish is not returned. That does not make the rows free of names: the published email is often a named officer's work address (measured on 2,849 rows of a 7-day run: 1,143, or 40%, have the form first.last@...), and title and description are the buyer's own text, returned as published, so they can mention people. Suppliers are returned by company name and registration identifier.

Sources and licence

  • Contracts Finder OCDS search API, contractsfinder.service.gov.uk
  • Find a Tender OCDS release package API, find-tender.service.gov.uk

Both are published by the Cabinet Office under the Open Government Licence v3.0. Contains public sector information licensed under the Open Government Licence v3.0. This Actor is not affiliated with the UK government.

Support

Found a notice that looks wrong, or need another field? Open an issue in the Issues tab.