UK Public Tenders Scraper — Contracts Finder + Find a Tender avatar

UK Public Tenders Scraper — Contracts Finder + Find a Tender

Pricing

Pay per usage

Go to Apify Store
UK Public Tenders Scraper — Contracts Finder + Find a Tender

UK Public Tenders Scraper — Contracts Finder + Find a Tender

Get UK government tenders, contract opportunities and awards from the official Contracts Finder and Find a Tender (FTS) OCDS APIs. Filter by keyword, CPV code, region, value, deadline and SME suitability. No login, no API key, Open Government Licence data.

Pricing

Pay per usage

Rating

0.0

(0)

Developer

timeless_enigma

timeless_enigma

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

2 days ago

Last modified

Categories

Features

Limited permissions

Share

Get UK government tenders, contract opportunities and contract awards from the two official UK portals in one run:

  • Contracts Finder: mostly lower-value contracts in England, plus SME-suitability flags.
  • Find a Tender (FTS): UK-wide, higher-value contracts.

You get clean JSON, CSV or Excel. Filter by keyword, CPV code, region, contract value, deadline and SME suitability. Use it to find bids to chase, monitor buyers, or see who won which contract for how much.

✅ Official Cabinet Office OCDS APIs · ✅ No login, no API key, no browser · ✅ Open Government Licence v3.0 data · ✅ Buyer contact-person blocks dropped, emails and phone numbers in text redacted (see Personal data)

What you can do with it

  • Bid pipeline: pull every open tender in your sector (e.g. CPV 72 IT services) with deadlines and values, every morning.
  • Win/loss intelligence: run with stage = award to see awarded suppliers and award values.
  • Market research: count tenders by buyer, region or category over a date range (see Realistic date ranges).
  • Feed an AI agent or CRM: stable, flat field names; schedule it, and use webhooks or integrations to push results to Sheets, Slack, etc.

Input

FieldTypeDefaultNotes
sourcesarraybothcontractsFinder, findATender
stagestringtendertender (open opportunities: tender, tenderUpdate, tenderAmendment; cancellations excluded), award (winners: award*/contract*), planning (pipeline), all (everything, incl. cancellations)
includeCancellationsbooleanfalseWhen false (default), any procedure (OCID) that has a tenderCancellation release is dropped entirely, including its older tender notices, so a cancelled tender never appears as open. When true, cancellations and their earlier notices are returned (Find a Tender: 37 cancellation releases in the week of Oct 28–Nov 4, 2026)
daysBackinteger7Used when publishedFrom is empty: whole UTC days back from publishedTo (0 = current UTC day only)
publishedFrom / publishedToYYYY-MM-DDdaysBack ago / todayContracts Finder filters by publish date; Find a Tender by last-updated date
keywordsarray–Keep a notice if its title or description contains any of these (case-insensitive)
excludeKeywordsarray–Drop matches
cpvPrefixesarray–e.g. 72 IT, 45 construction, 85 health, 79 business services
regionsarray–Substring match on region names (London) or ITL/NUTS codes (UKI, UKM)
minValue / maxValueinteger (GBP)–Notices without a value are dropped when these are set
onlyOpenbooleanfalseOnly notices with a submission deadline still in the future
smeSuitableOnlybooleanfalseOnly notices the buyer marked SME-suitable
dedupeByOcidbooleantrueOne row per procurement (newest notice). Off = every amendment gets its own row
includeDescriptionbooleantrueTurn off for smaller rows
crossSourceDedupebooleantrueDrop a notice already returned by the source listed first in sources (same normalized title + buyer)
maxResultsinteger200Total saved (charged) rows across sources, split fairly (see below)
maxPagesPerSourceinteger200Safety cap, 100 raw releases per page; FTS ≈ 30 pages/week

Example:

{
"sources": ["contractsFinder", "findATender"],
"stage": "tender",
"publishedFrom": "2026-10-28",
"publishedTo": "2026-11-04",
"keywords": ["software", "digital", "cyber", "data"],
"onlyOpen": true,
"maxResults": 50
}

Output example (one row; real data from Contracts Finder, Nov 4, 2026)

{
"source": "Contracts Finder",
"noticeId": "698da360-f303-47eb-8f37-6e8223279525-920602",
"ocid": "ocds-b5fd17-7b593149-b063-487f-ac29-45cdba120930",
"stage": "award",
"status": "complete",
"title": "2026-087 AI Technical Sandbox",
"buyerName": "Ofgem",
"buyerLocality": "London",
"publishedDate": "2026-11-04T17:45:14Z",
"valueAmount": 450000,
"valueCurrency": "GBP",
"cpvCode": "72421000",
"cpvDescription": "Internet or intranet client application development services",
"category": "services",
"procurementMethod": "open",
"suitableForSme": true,
"contractStart": "2026-10-19T00:00:00+01:00",
"contractEnd": "2028-12-31T23:59:59Z",
"awardedSuppliers": ["SoftCat PLC"],
"awardValue": 450000,
"noticeUrl": "https://www.contractsfinder.service.gov.uk/Notice/698da360-f303-47eb-8f37-6e8223279525",
"license": "Open Government Licence v3.0"
}

Every row also has buyerId, buyerPostcode, regions, lastUpdated, deadline, additionalCpvCodes, procurementMethodDetails, suitableForVcse, lotCount and (optionally) description. A RUN_SUMMARY record in the key-value store shows per-source counts, skipped duplicates and why the run stopped.

How results are counted and ordered

  1. Each source is fetched without a server-side stage filter, and the stage filter is applied here on each release's OCDS tag: tender = tender / tenderUpdate / tenderAmendment (plus tenderCancellation only with includeCancellations: true or stage: all); award = award* / contract*; planning = planning*. Both portals' own stages parameters silently drop notices. Find a Tender's drops Procurement Act 2023 notices (48 of 606 tender-stage releases returned in one week). Contracts Finder's drops planning notices whose status is "planning" (15 of 18). Unless cancellations are included, every release of a procedure (OCID) that has a tenderCancellation release is dropped, whichever order the releases arrive in (week of Oct 28–Nov 4: 36 cancelled procedures on Find a Tender, none on Contracts Finder).
  2. Your filters (keywords, CPV, region, value, open, SME) run next.
  3. Dedupe: within a source, only the newest matching notice per procurement (OCID) is kept (dedupeByOcid: true). With dedupeByOcid: false, every amendment/update is its own row. Across sources (crossSourceDedupe), a row is dropped only if an earlier source in sources already returned the same normalized title + buyer name. Rows from the same source are never compared with each other. OCIDs differ between the two portals, so title + buyer is the only shared key. In the week of Oct 28–Nov 4, 2026 it matched exactly one procurement (Derby City Council, ENQ1406). It will miss a notice whose title was edited on one portal.
  4. Fair split: maxResults is shared. Each source gets an equal share (e.g. 100 → 50 + 50), and any share one source can't fill goes to the other (e.g. 97 + 3). Rows are saved interleaved (CF, FTS, CF, FTS, …), so a spending limit cuts both sources evenly.

Realistic date ranges

All dates are UTC calendar days: publishedFrom starts at 00:00:00Z and publishedTo ends at 23:59:59Z. daysBack counts whole UTC days back from publishedTo (default: today in UTC). daysBack: 0 = only the current UTC day so far, which can be empty early in the UK morning or, from the US, late in the evening. daysBack: 1 = yesterday + today.

Measured for Oct 28 – Nov 4, 2026 (one week, page size 100; both sources are fetched unfiltered):

SourceRaw releases / weekAPI pages / weektender (excl. cancellations)awardplanning
Find a Tender2,87629567 (+39 with cancellations)1,952314
Contracts Finder83894877218
  • Up to ~5 weeks of both sources fit in the default maxPagesPerSource: 200 (FTS is about 30 pages a week). For a quarter, set about 400. A full year of FTS (about 1,500 pages) is more than the 1,000-page maximum, so split it into quarterly runs.
  • Run time: unthrottled, a 1-week run of both sources takes about 26–35 s (Polter's QA and my runs, Nov 4, 2026). The slow runs (~150 s or more) are caused by Find a Tender HTTP 429 rate limiting with Retry-After: 120, not by paging.
  • 429 / 5xx handling: every request is retried up to 7 times (8 attempts). A server Retry-After (seconds or HTTP date) is honoured up to 5 minutes. Without one, the Actor backs off exponentially (4 s, 8 s, 16 s … capped at 120 s, +0–20% jitter). Pages are spaced by requestDelayMs (500 ms). Counts of 429s and total wait time are in RUN_SUMMARY.perSource.<source>.http429 / retryWaitMs. Expect more 429s on shared cloud IPs. If a source still fails after all retries, the other source's rows are still saved and the error is listed in RUN_SUMMARY.
  • If a page cap is hit, RUN_SUMMARY.perSource.<source>.hitPageCap = true and the log warns that results may be incomplete.
  • Daily schedules: use daysBack: 1 and dedupe downstream. Because days are UTC, daysBack: 0 can miss notices published late in the UTC day, or return nothing when run early in the UTC morning. daysBack: 1 (yesterday + today) covers that gap but overlaps the previous run, so the same notice can come back (and be charged) twice. Dedupe on noticeId (or ocid + lastUpdated) in your sheet/DB.

Pricing (pay per event)

EventPrice
Actor start$0.005 per run
Tender notice saved (after your filters)$0.004 per notice (= $4 per 1,000)

You pay only for rows that match your filters. Raw notices that are filtered out are free. Each notice is charged just before it is saved. If you set a maximum total charge, the Actor stops cleanly at the limit and never saves an unpaid row. If the limit can't even cover the start event, it exits without fetching. Example: a daily run returning 40 notices costs $0.165.

Personal data (UK GDPR)

This Actor drops the OCDS contactPoint blocks (named buyer officials, their emails and phones) and replaces email addresses and UK phone numbers found in free text with [email redacted] / [phone redacted]. It does not remove names inside free text. Notice titles and descriptions can still mention individuals (e.g. "representations to the Corporate Director …"), and awardedSuppliers can contain the names of sole traders or partnerships, because that is how the government publishes them. If you store or reuse this output, you are the controller and are responsible for having a lawful basis under UK GDPR / the Data Protection Act 2018 (e.g. legitimate interests for B2B tender research) and for honouring data-subject rights. Don't use it for direct marketing to individuals without checking PECR.

Limits and notes

  • Data is only as complete as the portals. Some notices have no value, region or deadline. Award notices may carry an old tender deadline.
  • Find a Tender filters by last-updated date, so an older notice amended in your window will appear.
  • Phone redaction targets UK formats (+44… or 0 followed by a non-zero digit, 10–11 digits). It skips times, ISO dates and notice reference numbers such as 068147-2026. Non-UK phone formats in free text are not redacted.
  • Placeholder or pointer text in the supplier-name field is removed from awardedSuppliers. Examples: "Please refer to …", "See Contracts Finder Notice for full supplier list", "This contract was awarded to 34 suppliers", "Full list of successful suppliers is available on Contracts Finder", "Refer to CAN …", "Multiple Suppliers", "Various", "Not Applicable", "N/A", "TBC", "Withheld Section94 Supplier". In the Oct 28–Nov 4 feeds this removed 17 of 3,333 unique supplier strings. For multi-supplier frameworks, awardedSuppliers can therefore be empty; check noticeUrl.
  • Max 366 days per run; maxPagesPerSource default 200, max 1,000 (100 raw releases per page). See Realistic date ranges.
  • Dedupe relies on the APIs listing newest releases first (observed, not documented).
  • If a run is aborted, rows already collected are charged and saved (fair split, interleaved) before the Actor exits, and RUN_SUMMARY.stoppedBecause says so. Rows from pages not yet fetched are lost.
  • Not affiliated with the UK Government. Contains public sector information licensed under the Open Government Licence v3.0.

FAQ

Do I need an API key or account on the UK portals? No. Scotland / Wales / NI portals? Notices above the thresholds appear on Find a Tender. Portal-only notices from Public Contracts Scotland, Sell2Wales and eTendersNI are not included yet. Can I get a daily alert? Yes. Schedule the Actor daily with publishedFrom/publishedTo empty and daysBack: 1, then connect an integration (email, Slack, Sheets). Consecutive runs overlap by one day on purpose (so nothing is missed), so dedupe on noticeId downstream.