UK Contracts Finder Scraper - Tenders & Awards avatar

UK Contracts Finder Scraper - Tenders & Awards

Pricing

from $4.00 / 1,000 contract awards

Go to Apify Store
UK Contracts Finder Scraper - Tenders & Awards

UK Contracts Finder Scraper - Tenders & Awards

Scrape UK public contracts from Contracts Finder, one row per supplier: who won, for how much, from which buyer, the buyer's named contact, and the days until the contract expires, which tells you what goes back to tender soon. Filter by keyword, category, date.

Pricing

from $4.00 / 1,000 contract awards

Rating

0.0

(0)

Developer

Tom Awake

Tom Awake

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

16 hours ago

Last modified

Share

What does UK Contracts Finder Scraper do?

Who won which UK public contract, for how much, from which buyer — and how many days until that contract expires.

Contracts Finder publishes UK public procurement in OCDS format. A notice nests a tender, an array of awards, and a separate parties array where the supplier's address and the buyer's contact live. Nothing is joined, and the supplier's address arrives as a single line-broken blob.

This Actor returns one row per supplier per award, joined, with the things the source leaves implicit.

No API key. No account.


The four things this does that the source does not

1. One row per supplier.

An award can name sixteen suppliers. The source stacks them in an array; we explode them, so every row is one contactable party with its own share of the record. Measured: 319 supplier rows out of 300 awards.

2. The parties join — 100%, no orphans.

awards[].suppliers carries only an id and a name. The address, the company size, and the buyer's named contact all live in a separate parties array. We join them. Measured on 300 recent awards: every supplier resolved, zero orphans.

That join is what produces the buyer contact — name, email and phone on 100% of notices. It is the most valuable field here and it is not in the award object at all.

3. Days until the contract ends.

This is the sales signal: a contract expiring in six months is a procurement about to reopen, and the incumbent is named. The source gives an end date, never a countdown. Measured on recent awards, 73 of 305 contracts expire within 180 days.

4. The supplier's postcode, parsed out of the address blob.

postalCode is populated on 0% of supplier parties. The postcode is nevertheless there, buried in streetAddress between line breaks: "IW HOUSE\n QUARRY ROAD\n CHIPPING SODBURY\n BS37 6JL". We extract it and normalise the whitespace — 88.7% coverage.


Getting past the 300-result ceiling

The API's cursor pagination stops after three pages. It simply stops returning a next link beyond 300 notices — about four days of publications — no matter what you ask for.

This Actor walks backwards through time in date windows, sizing each window to the density it actually finds: narrower where notices are dense, wider where they are sparse. When a window hits the 300 ceiling it resumes from the oldest notice actually returned, rather than stepping over the ones it could not see.

Filters are applied during pagination, not after it. Asking for 300 rows with a selective filter returns 300 rows — an earlier version returned 44, because the loop counted rows before filtering.


Field coverage

Measured on a run of 300 awards with a 180-day expiry filter, and on 305 unfiltered awards.

FieldCoverage
supplierName100%
buyerName, buyerContactEmail, buyerPostcode100%
contractEndDate, daysUntilContractEnd, contractDays100%
cpvCode, cpvDescription100%
awardValue96.7%
supplierPostcode88.7%
supplierScale (large / sme)83.3%
daysToPublication79.0%
buyerContactPhone47.5%
supplierCompanyNumber37.7%

Re-measured 17 September 2026 on a 500-row run: daysUntilContractEnd was present on 500 rows out of 500 and agreed with contractEndDate on all 500 — zero discrepancies. Median 74 days; 289 of the 500 contracts expire within 90 days.

supplierCompanyNumber is the Companies House number, extracted from ids of the form GB-COH-06472932. The other ids (GB-CFS-…) are internal to Contracts Finder and resolve to nothing, so that field is deliberately empty rather than filled with an identifier that looks useful and is not.

There is no supplier city field, on purpose

Contracts Finder never populates locality for suppliers — the field came back empty on 500 rows out of 500, so it was removed rather than shipped as a column of blanks.

Deriving it from the address was tried and measured: 66% of addresses yielded something, but the results included England 39 times, United Kingdom 24 times, counties (Staffordshire, Hampshire) and street names (70 Chancery Lane). A field that is right two thirds of the time is worse than an absent one, because it gets filtered and counted as though it were reliable.

Use supplierPostcode for geography: it is validated against the UK postcode format and present on 86-89% of rows. The buyer side is unaffected — buyerCity comes from a field the source does fill, and is present on 100% of rows.


What it is for

  • Selling to the public sector. Filter endingWithinDays to 180, and each row is a contract about to be re-tendered — with the incumbent, the value, and the buyer's direct email.
  • Competitive intelligence. Every award your competitors have won, by value, buyer and category.
  • Market sizing. 96.7% of awards carry a value. Aggregate by CPV code or by buyer.
  • Supply chain and credit. Suppliers with Companies House numbers can be joined to any UK company dataset.
  • SME policy research. smeSuitable and vcseSuitable are the buyer's own flags; supplierScale is what the supplier actually is. Comparing the two is a question the source cannot answer on its own.

Three dataset views ship with the Actor: Awards, Coming up for renewal, and Suppliers.


Running this as a scheduled watch

Contract award notices appear continuously, and the value of this Actor is time-sensitive: a contract expiring in six months is a procurement about to reopen, and you want to know before your competitor does.

Set publishedWithinDays instead of a fixed date, then schedule the Actor in Apify. The window moves with each run.

{
"stage": "award",
"publishedWithinDays": 7,
"cpvCodes": ["72000000"],
"maxItems": 500
}

Measured 17 September 2026: publishedWithinDays: 7 returned 308 rows published between the 12th and the 16th; 30 returned 500 rows going back to the 4th.

Why not a fixed publishedFrom date? A schedule replays the same input every time. With a fixed date the window never moves, so every run returns the same rows — and charges you for them again. The rolling window is the only setting that makes a weekly watch honest.


Limits

Stated plainly, because they affect what you can conclude.

  • Rate limiting is real. The service returns HTTP 429 under sustained querying. Requests are paced and retried with a long backoff, so large runs take minutes rather than seconds. If a run is throttled part-way through, the rows already collected are returned rather than discarded.
  • Publication dates, not award dates. The date windows filter on when a notice was published. daysToPublication shows the gap: median 14 days, but up to 1,732 observed. A notice published this week can concern an award made years ago.
  • Negative publication delays are dropped. 10 of 300 awards had a publication date earlier than the award date. That has no business meaning, so daysToPublication is left empty rather than negative.
  • Contract end dates are as filed. Some are wrong, some contracts get extended without a new notice, and 12 of 305 had already ended. contractExpired flags those.
  • Values are what the buyer published. Median £63,000, largest £135M observed, and some are £0. Framework call-offs sometimes carry the framework's value rather than the call-off's.
  • sourceUrl is for a browser. The link points at the notice page on Contracts Finder, which rejects automated requests with HTTP 403. It opens normally in a browser; it will not fetch from a script. The ocid field is the canonical OCDS identifier if you need one.
  • UK only, GBP only. Every value observed is in GBP. Scotland, Northern Ireland and Wales also run their own portals; contracts published only there do not appear here.

How much does it cost?

You pay per contract award returned: $0.006 each, that is $6.00 per 1,000. There is no start fee, and subscription plans pay less per contract award.

The example input below asks for up to 500 contract awards, so it costs $3.00 at most.

If a run reaches the spending limit you set, the output stops at that limit and never goes past it. You are never charged for rows that were not delivered.

Use UK Contracts Finder Scraper as an API

Call it from your own code with the Apify client, here in Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("DataIO/uk-public-contract-awards").call(run_input={'stage': 'award', 'endingWithinDays': 180, 'maxItems': 500})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)

It also works from JavaScript, Make, Zapier, n8n, and from AI agents through the Apify MCP server.

Other actors you might like

FAQ

The actor reads public data from its official source, without logging in and without bypassing any access control. What you do with the data, for example contacting people listed in it, is your responsibility under the laws that apply to you, such as GDPR in Europe.

Can I run it on a schedule?

Yes. See Running this as a scheduled watch above: use the rolling-window setting so each run returns only what is new.

Can AI agents use it?

Yes. It is available through the Apify MCP server, and every input field is described in its input schema, so an agent can call it directly.

Source

Contracts Finder, published by the Cabinet Office under the Open Government Licence v3.0, in OCDS 1.1. Public, no authentication. This Actor is not affiliated with the Cabinet Office.