# UK Government Tenders - Find a Tender & Contracts Finder (`scoutdesk/uk-public-tenders-scraper`) Actor

Get UK government tenders, contract opportunities, pipeline notices and contract awards from the official Find a Tender and Contracts Finder APIs. Filter by keyword, CPV code, region, value, buyer and deadline. Monitor mode returns only new notices. No API key, no proxies.

- **URL**: https://apify.com/scoutdesk/uk-public-tenders-scraper.md
- **Developed by:** [Scout Desk](https://apify.com/scoutdesk) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 notices

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## UK Government Tenders Scraper: Find a Tender & Contracts Finder API

Get **UK government tenders, contract opportunities, pipeline notices and contract awards** from both official UK procurement portals, **Find a Tender (FTS)** and **Contracts Finder**, in one clean, deduplicated dataset. Filter by **keyword, CPV code, region, contract value, buyer, deadline and SME suitability**, then schedule it as a **daily new-tender alert feed**. No API key, no proxies, no browser. You pay only for the notices you keep.

### What does UK Government Tenders Scraper do?

UK public bodies (central government, councils, NHS trusts, universities, housing associations, police, and devolved governments in Scotland, Wales and Northern Ireland) must publish their procurement notices on the government's official portals. This Actor reads them directly from the **official OCDS (Open Contracting Data Standard) APIs** published by the UK Cabinet Office:

- **Find a Tender** carries above-threshold notices and, since the Procurement Act 2023 took effect in February 2025, most new UK notices (UK1–UK17 notice types).
- **Contracts Finder** carries many lower-value (below-threshold) opportunities and awards in England.

It turns the deeply nested OCDS JSON into **one flat row per notice**, with the fields bid teams actually need: title, buyer, value, deadline, CPV codes, regions, SME flag, the official notice link and the e-tendering portal link to submit your bid.

### Why use it?

- 🎯 **Find opportunities before competitors.** Run it every morning with your keywords and CPV codes, and get only the *new* notices since yesterday.
- 🏛️ **Two portals, one feed.** No more checking Find a Tender and Contracts Finder separately.
- 🧹 **Analysis-ready data.** Values, deadlines, CPV codes and regions are normalised. You get the latest version of each notice, not five revisions of it.
- 🏆 **Win/loss intelligence.** Switch to *contract awards* to see who won what, for how much, and from which buyer.
- 🛡️ **Built to keep running.** It respects both portals' rate limits automatically, including Contracts Finder's silent throttling that makes other tools return empty results.
- ⚖️ **Legally clean.** The source is official government open data under the [Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/), which permits commercial reuse.

**Who uses it:** bid writers and bid consultancies, SME suppliers to the public sector, sales and business development teams selling to councils and the NHS, market researchers, journalists, and procurement analysts.

### What data can you extract?

| Field | Example |
|---|---|
| Title / description | "Asset Tracking System" |
| Buyer, buyer ID, town, postcode | NHS Borders, GB-PPON-…, Melrose |
| Stage / notice type | `tender` / `UK4` |
| Estimated value (net and gross) and currency | 116000, 139200, GBP |
| Submission deadline / clarification deadline | 2026-11-16T12:00:00Z |
| Contract start, end and duration | 2027-02-01 → 2030-01-31, 1095 days |
| CPV codes and descriptions | 48422000 "Software package suite" |
| Region codes and names | UKM91 / Scotland |
| SME / VCSE suitable | true |
| Procedure | Open procedure |
| Lots | count and titles |
| Awarded suppliers, award value, award date | for award notices |
| Official notice URL | https://www.find-tender.service.gov.uk/Notice/… |
| Submission portal URL | the buyer's e-tendering portal link |
| OCID / release ID | stable IDs for joining and deduplication |
| Optional | buyer contact point, full raw OCDS release |

### How to use it

1. Click **Try for free**.
2. Enter **keywords** (e.g. `software`, `cleaning`, `cyber security`) and/or **CPV code prefixes** (e.g. `72` for IT services, `45` for construction).
3. Choose the **stage**: open tenders (default), planning/pipeline notices, or contract awards.
4. Optionally narrow by **region** (e.g. `London`, `Scotland`, `UKD`), **value range**, **buyer name** (e.g. `NHS`, `Council`) or **SME-suitable only**.
5. Click **Start**, then download the results as **JSON, CSV, Excel or HTML**, or pull them through the API.

#### Daily alert feed (monitor mode)

Turn on **Monitor mode: only new notices** and give your saved search a **Monitor key** (e.g. `london-it`). Then create an Apify **Schedule** (e.g. every weekday at 07:00). Each run returns only notices you haven't seen before, which you can push to email, Slack, Google Sheets, HubSpot or Zapier/Make with Apify integrations.

### Input example

```json
{
  "keywords": ["software", "cloud", "digital", "IT support", "website"],
  "keywordScope": "titleOnly",
  "noticeStages": ["tender"],
  "sources": ["find-a-tender", "contracts-finder"],
  "daysBack": 7,
  "onlyOpen": true,
  "maxResults": 25
}
```

More examples:

```json
{ "noticeStages": ["award"], "sources": ["find-a-tender"], "buyerNameContains": ["NHS"], "daysBack": 3, "maxResults": 100 }
```

```json
{ "noticeStages": ["tender"], "cpvCodes": ["72000000", "48"], "regions": ["London"], "daysBack": 3,
  "onlyNewSinceLastRun": true, "monitorKey": "london-it" }
```

### Output example

One item from a real run on 8 Oct 2026 (description shortened):

```json
{
  "source": "Find a Tender",
  "stage": "tender",
  "noticeType": "UK4",
  "title": "NS&I Digital Market Intelligence Support service",
  "description": "A digital and fintech insight agency is required to help NS&I monitor the external competitor landscape…",
  "status": "active",
  "buyerName": "NS&I",
  "buyerId": "GB-PPON-PJNT-9481-WXVY",
  "buyerLocality": "London",
  "buyerPostcode": "SE1 9HA",
  "mainCategory": "services",
  "procurementMethod": "Open procedure",
  "cpvCodes": ["79310000"],
  "cpvDescriptions": ["Market research services"],
  "buyerRegionCode": "UKI44",
  "regionCodes": ["UKI44"],
  "regionNames": ["London"],
  "valueAmount": 125000,
  "valueAmountGross": 150000,
  "valueCurrency": "GBP",
  "publishedDate": "2026-10-07T16:37:10+01:00",
  "tenderDeadline": "2026-11-02T12:00:00Z",
  "enquiryDeadline": "2026-10-22T11:00:00Z",
  "contractStart": "2026-12-08T00:00:00Z",
  "contractEnd": "2027-12-07T23:59:59Z",
  "contractDurationDays": 364,
  "lotsCount": 1,
  "suitableForSme": true,
  "aboveThreshold": true,
  "noticeUrl": "https://www.find-tender.service.gov.uk/Notice/094926-2026",
  "submissionUrl": "https://app.panacea-software.com/nsandi/eRFX-Suppliers/OpenReq.aspx?requirementId=86e03043-…",
  "ocid": "ocds-h6vhtk-078325",
  "releaseId": "094926-2026",
  "scrapedAt": "2026-10-08T09:52:44+00:00"
}
```

Other row types: **award** rows add `awardedSuppliers`, `awardValue` and `awardDate`; **planning** rows usually have a value but no deadline yet.

### How much does it cost to scrape UK tenders?

This Actor uses **pay-per-result** pricing: you pay a small fixed price for each notice saved to your dataset, and **notices filtered out by your criteria are free**. A typical daily monitor for one sector returns 5–50 new notices, so it costs cents per day. There is no separate charge for compute: you pay per notice saved (plus Apify's tiny standard per-run start fee, if shown on the pricing tab). You can cap spending per run with Apify's *maximum cost per run* setting, and the Actor stops cleanly at your limit.

### Tips

- **CPV codes are hierarchical.** `72` matches every IT service code; `72267` matches software maintenance and its children. Full 8-digit codes like `80000000` are handled correctly (education, not "everything starting with 8").
- **Use "Title only"** keyword search for precise results; "Title + description" is broader.
- **Region filter:** use ITL/NUTS codes (`UKI`, `UKM`, `UKL22`) or ITL1 names (`London`, `Scotland`, `Wales`, `North West`). By default it matches the **delivery location**, which includes nationwide notices that list your region. Set *Region applies to* = **Buyer location only** to get only buyers based in that region. Notices without region data are excluded when you filter by region.
- **Run time:** both portals list notices newest first, so the Actor stops as soon as it has your *Max results* newest matching notices. A default run (open tenders, 50 results) usually finishes in under 30 seconds. Narrow filters over a long window (e.g. one region and CPV code over 14 days) have to scan every notice in the window: about 1–3 minutes for 3 days, 3–5 minutes for 7 days and 8–10 minutes for 14 days, because the Actor deliberately stays under the portals' shared rate limit (about 10 requests a minute).
- **Scheduled monitors:** set *Days back* to 2–3 for a daily schedule. Each run scans the whole window, so a short, overlapping window is faster, and monitor mode still never returns the same notice twice.
- **Long windows** (e.g. 90 days) take longer because both portals rate-limit requests; the Actor throttles itself automatically.
- **Statuses:** with *Only open tenders* on, notices past their deadline or cancelled are dropped.

### FAQ

**Is scraping UK tender data legal?**
This Actor doesn't scrape web pages. It reads the official, documented, key-free OCDS APIs published by the UK Cabinet Office. The data is licensed under the **Open Government Licence v3.0**, which allows copying, publishing and commercial use with attribution ("Contains public sector information licensed under the Open Government Licence v3.0"). Notices can name buyer officers, so **buyer contact points are off by default**. If you turn them on, you are responsible for using that personal data in line with UK GDPR (e.g. only for responding to the procurement).

**How fresh is the data?**
It's live. Each run queries the portals' APIs directly, and new notices typically appear within minutes of publication.

**Does it cover Scotland, Wales and Northern Ireland?**
Yes, for notices published to Find a Tender (Public Contracts Scotland, Sell2Wales and eTendersNI above-threshold notices flow there). Sub-threshold notices that appear only on the devolved portals are not included yet.

**Why do some notices have no value or deadline?**
Buyers don't always publish them (e.g. pipeline and planning notices). The fields are `null` rather than guessed.

**Can I get the full original data?**
Yes. Turn on *Include raw OCDS release*.

**What happens if one of the portals is down?**
The Actor retries with back-off. If Contracts Finder or Find a Tender is still unavailable after a few minutes, the run carries on with the other portal, says so in the run's status message, and lists the problem under `sourceErrors` in the `RUN_SUMMARY` record. In monitor mode, notices you missed are picked up on the next run, as long as *Days back* covers the gap.

**Does it cover EU tenders?**
No. Since Brexit, UK notices are published on Find a Tender and Contracts Finder, not on the EU's TED. For tenders and contract awards from the 27 EU member states, the EEA and Switzerland, use our companion Actor, [EU Tenders Scraper (TED)](https://apify.com/scoutdesk/eu-ted-tenders-scraper). It has the same flat output, monitor mode and pay-per-result pricing.

**Something's broken or you need a field?**
Open an issue on the Actor's **Issues** tab. We monitor runs daily and aim to fix portal changes within 48 hours.

### Other public procurement data

This Actor is part of a public-tenders family:

- 🇬🇧 **UK Government Tenders Scraper** (this Actor): Find a Tender and Contracts Finder.
- 🇪🇺 **[EU Tenders Scraper (TED)](https://apify.com/scoutdesk/eu-ted-tenders-scraper)**: EU, EEA and Swiss public tenders, awards and planning notices from Tenders Electronic Daily, with EUR value conversion.

***

*Contains public sector information licensed under the Open Government Licence v3.0. This Actor is not affiliated with the Cabinet Office, Crown Commercial Service or GOV.UK.*

# Actor input Schema

## `keywords` (type: `array`):

Only return notices whose title, description or lot titles contain these words or phrases (case-insensitive, matched at word start). Leave empty for all notices.

## `keywordMatch` (type: `string`):

Match ANY keyword (broad) or ALL keywords (narrow).

## `keywordScope` (type: `string`):

Search keywords in the title and lot titles only (precise) or also in the full description (broad).

## `excludeKeywords` (type: `array`):

Drop notices that contain any of these words or phrases.

## `noticeStages` (type: `array`):

Which procurement stages to return: open opportunities (tender), pipeline / pre-market engagement (planning), or contract awards (award).

## `sources` (type: `array`):

Official UK procurement portals to read. Find a Tender carries most notices since the Procurement Act 2023 took effect (Feb 2025); Contracts Finder still carries many lower-value and legacy notices.

## `daysBack` (type: `integer`):

How many days of notices to scan, counting back from now. Ignored when 'Published from' is set.

## `publishedFrom` (type: `string`):

Optional start date (YYYY-MM-DD). Overrides 'Days back'.

## `publishedTo` (type: `string`):

Optional end date (YYYY-MM-DD). Defaults to now.

## `cpvCodes` (type: `array`):

Filter by Common Procurement Vocabulary codes. Prefixes work: '72' = IT services, '48' = software packages, '45' = construction, '79' = business services, '85' = health & social work.

## `regions` (type: `array`):

Filter by ITL/NUTS region code prefix or ITL1 region name, e.g. UKI or London, UKM or Scotland, UKL or Wales, UKN or Northern Ireland, UKJ or South East. Notices without region data are excluded when this filter is set.

## `regionMatch` (type: `string`):

Match the region filter against where the contract is delivered (default; includes nationwide notices that list your region) or only against the buyer's own location (Find a Tender notices only).

## `buyerNameContains` (type: `array`):

Only notices from buyers whose name contains one of these strings, e.g. 'NHS', 'Council', 'Ministry of Defence'.

## `minValue` (type: `integer`):

Only notices with an estimated value at or above this amount (net of VAT where published, otherwise gross). Notices without a value are excluded when set.

## `maxValue` (type: `integer`):

Only notices with an estimated value at or below this amount. Notices without a value are excluded when set.

## `onlyOpen` (type: `boolean`):

For the tender stage, drop notices whose submission deadline has passed or that were cancelled.

## `smeSuitableOnly` (type: `boolean`):

Only notices the buyer marked as suitable for small and medium-sized enterprises.

## `maxResults` (type: `integer`):

Maximum number of notices to save (newest first). You are charged per saved notice. The run stops scanning as soon as it has this many of the newest matching notices, so smaller values also finish faster.

## `onlyNewSinceLastRun` (type: `boolean`):

Remember notices returned in previous runs (per 'Monitor key') and return only ones you have not seen. Schedule the Actor daily for a new-tender alert feed.

## `monitorKey` (type: `string`):

Name for the monitor's memory. Use a different key for each saved search you schedule.

## `includeBuyerContacts` (type: `boolean`):

Add the contact point published on the notice (may include a named officer's work email/phone). Off by default; if you enable it you are responsible for handling that data lawfully (UK GDPR).

## `includeRawOcds` (type: `boolean`):

Attach the full original OCDS release JSON to each row (larger output).

## Actor input object example

```json
{
  "keywords": [
    "software",
    "cloud",
    "digital",
    "IT support",
    "website"
  ],
  "keywordMatch": "any",
  "keywordScope": "titleAndDescription",
  "excludeKeywords": [],
  "noticeStages": [
    "tender"
  ],
  "sources": [
    "find-a-tender",
    "contracts-finder"
  ],
  "daysBack": 1,
  "cpvCodes": [],
  "regions": [],
  "regionMatch": "delivery",
  "buyerNameContains": [],
  "onlyOpen": true,
  "smeSuitableOnly": false,
  "maxResults": 50,
  "onlyNewSinceLastRun": false,
  "monitorKey": "default",
  "includeBuyerContacts": false,
  "includeRawOcds": false
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keywords": [
        "software",
        "cloud",
        "digital",
        "IT support",
        "website"
    ],
    "daysBack": 1,
    "maxResults": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("scoutdesk/uk-public-tenders-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "keywords": [
        "software",
        "cloud",
        "digital",
        "IT support",
        "website",
    ],
    "daysBack": 1,
    "maxResults": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("scoutdesk/uk-public-tenders-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "keywords": [
    "software",
    "cloud",
    "digital",
    "IT support",
    "website"
  ],
  "daysBack": 1,
  "maxResults": 50
}' |
apify call scoutdesk/uk-public-tenders-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scoutdesk/uk-public-tenders-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/lGft0dG9qcSQv5pL5/builds/7P6lWEaAWk1EJ8oMf/openapi.json
