# UK Tenders Scraper: Find a Tender Public Procurement API (`boubap/uk-tenders-scraper`) Actor

Returns UK public tenders from Find a Tender, the official UK procurement service: open calls for tender, contract awards, pipeline notices, CPV codes, deadlines, values and buyers. Filter by keyword, CPV, region, value and date. No API key.

- **URL**: https://apify.com/boubap/uk-tenders-scraper.md
- **Developed by:** [Baptiste Bouton](https://apify.com/boubap) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.63 / 1,000 tender notices

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 Tenders Scraper: Find a Tender Public Procurement API

Returns **UK tenders** and **UK public procurement** notices from **Find a Tender**, the official UK government procurement service, as JSON: calls for tender, contract awards, pipeline notices, buyers, CPV codes, deadlines and estimated values. Filter by keyword, CPV code, UK region, contract value, notice type and date. The data comes from the official Find a Tender OCDS API, not from page scraping. You pay per notice returned. No subscription, no API key.

Since 24 February 2025, every new notice under the Procurement Act 2023 is published on Find a Tender, above and below the thresholds, for England, Wales, Scotland and Northern Ireland. Notices still running under the older regulations (PCR 2015) are included too.

### Daily tender alerts

Schedule the Actor every morning with `publishedWithinDays: 1` and your `cpvCodes`, `regions` or `keywords`. Send the new notices to Slack, email or a CRM with an Apify webhook.

### Use cases

- **Bid monitoring**: every new UK call for tender in your sector, each morning.
- **Sales prospecting**: councils, NHS trusts and departments buying what you sell, with deadline and budget.
- **Pipeline planning**: pipeline and market engagement notices, before the tender opens.
- **Market intelligence**: awarded values by region, sector (CPV) and buyer.
- **AI agents**: live UK procurement data through the Apify MCP server.

### Input

```json
{
  "keywords": "software",
  "cpvCodes": ["72", "48"],
  "regions": ["London", "South East"],
  "noticeTypes": "contract-notices",
  "publishedWithinDays": 7,
  "minValue": 100000,
  "openOnly": true,
  "maxResults": 1000
}
```

| Field | What it does |
|---|---|
| `keywords` | Words to find in the title or description. Notices must contain all the words. |
| `cpvCodes` | CPV codes or prefixes: `72` = IT services, `45` = construction work, `85` = health and social work, `79` = business services. |
| `regions` | Place of performance: `London`, `Scotland`, `Wales`, `North West`, ITL codes such as `UKI`, `UKM`, `UKD3`, or `UK` for the whole country. Notices for the whole UK are always kept. |
| `noticeTypes` | `contract-notices` (calls for tender and their updates), `awards`, `planning` (pipeline and market engagement) or `all`. |
| `publishedWithinDays` | Only notices published in the last N days (1 to 90). |
| `publishedFrom`, `publishedTo` | Exact publication date range (`YYYY-MM-DD`), instead of `publishedWithinDays`. |
| `minValue`, `maxValue` | Estimated value range in GBP, excluding VAT. Notices without a value, or valued in another currency, are dropped when a limit is set. |
| `openOnly` | Calls for tender only: keep notices whose deadline has not passed. |
| `maxResults` | Upper limit of notices returned. |

### Output

```json
{
  "noticeId": "099362-2026",
  "ocid": "ocds-h6vhtk-078c98",
  "url": "https://www.find-tender.service.gov.uk/Notice/099362-2026",
  "title": "Penetration Testing",
  "buyerName": "Senedd Cymru / Welsh Parliament",
  "buyerRegion": "UKL22",
  "buyerCountry": "GBR",
  "publicationDate": "2026-10-21",
  "deadline": "2026-11-24",
  "noticeType": "UK4",
  "stage": "tender",
  "status": "active",
  "procedureType": "Below threshold - open competition",
  "contractNature": ["services"],
  "cpvCodes": ["72000000"],
  "placeOfPerformance": ["UKL"],
  "estimatedValue": 80000,
  "currency": "GBP",
  "aboveThreshold": false,
  "suitableForSme": true,
  "awardedValue": null,
  "awardedCurrency": null,
  "winnerCountries": []
}
```

- `noticeType` is the Procurement Act form when the notice gives it, for example `UK4` tender notice, `UK5` transparency notice, `UK6` contract award notice or `UK7` contract details notice. Other notices show their OCDS stage instead, for example `tender` or `planning`.
- `ocid` links all the notices of one procurement, so you can follow a tender to its award.
- `placeOfPerformance` and `buyerRegion` use ITL (NUTS) codes: `UKI` London, `UKM` Scotland, `UKL` Wales, `UKN` Northern Ireland. `UK` means the whole country.
- For contract awards, `awardedValue` is the total awarded and `winnerCountries` lists the countries where the winners are based. Winner names are not returned.

### Recipes

- **UK government contracts for IT suppliers**: `cpvCodes: ["72", "48"]`, `noticeTypes: "contract-notices"`, `publishedWithinDays: 1`, scheduled daily.
- **Construction tenders in Scotland**: `cpvCodes: ["45"]`, `regions: ["Scotland"]`, `minValue: 250000`.
- **What UK buyers awarded last month**: `noticeTypes: "awards"`, `publishedWithinDays: 30`, read `awardedValue`, `buyerName` and `winnerCountries`. Winner names are not exported.
- **Tenders for small businesses**: run any search and keep the items where `suitableForSme` is true.

### Integrations

- **Make, Zapier and n8n**: use the Apify app or node, run this Actor on a schedule, then send each new notice to Slack, Google Sheets, Airtable or your CRM.
- **Apify API and webhooks**: start a run from your own code and fetch the dataset as JSON, CSV or Excel.
- **Apify MCP server**: let Claude or another AI agent search UK tenders in plain language.

### Pricing

You pay per notice returned, no subscription. A search with no results costs nothing. The current rate per notice is on the Pricing tab.

### Tips

- Schedule a daily run with `publishedWithinDays: 1` to receive only new tenders.
- Combine several CPV prefixes to cover a whole market, for example `["72", "48"]` for IT services and software.
- Sort or filter on `suitableForSme` to find the contracts that buyers flag as suitable for small businesses.
- A run covers at most 90 days of notices. For a longer history, run once per 90-day range with `publishedFrom` and `publishedTo`.
- A wide date range with very narrow filters scans many notices: the run takes longer, but you only pay for the notices returned.

### FAQ

**Do I need a Find a Tender account or API key?** No. The Find a Tender OCDS API is public.

**Can I reuse the data?** Yes. Find a Tender publishes its data under the [Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/). When you republish it, acknowledge the source, for example: "Contains public sector information licensed under the Open Government Licence v3.0."

**Does it cover Contracts Finder?** Not yet. Since February 2025 new notices under the Procurement Act 2023, below threshold included, go to Find a Tender. Contracts Finder now mostly receives notices for procurements started under the older rules.

**Does it collect personal data?** No. The output describes public procurement notices. Contact names, e-mail addresses and phone numbers are never returned, and neither are free-text descriptions, which can contain them. Winner names are deliberately left out too, because many winners are sole traders named after a person. When a title or buyer name contains a person's name after a title such as Dr or Mrs, or a "T/A" trading name, that part is replaced with `[name removed]`.

**How fresh is the data?** Find a Tender publishes new notices every day and the Actor queries it live on each run.

**What are the limits of the API?** The API returns 100 notices per page and rate-limits requests. When it answers 429, the Actor waits and then slows to 12 requests per 2 minutes. A 7-day scan reads about 25 pages and takes 1 to 3 minutes. A 90-day scan with narrow filters reads about 320 pages and can take up to an hour.

### Related Actors

Other Actors from the same account, also pay per result:

- [EU TED Tenders Scraper](https://apify.com/boubap/ted-tenders-scraper): Public tenders from the EU, EEA and partner countries. Same ISO 3-letter country codes, so both datasets merge.
- [Tech Stack Detector](https://apify.com/boubap/tech-stack-detector): Detect the technology stack of a buyer's website.
- [French Company Search](https://apify.com/boubap/france-companies-scraper): Look up French companies (SIREN, SIRET, NAF code, revenue).
- [Google Trends Explore API](https://apify.com/boubap/google-trends-explore): Measure search interest in a market before choosing which CPV codes to monitor.

# Actor input Schema

## `keywords` (type: `string`):

Words to find in the notice title or description. Notices must contain all the words, in any order and any case. Example: cloud migration. Leave empty to filter only by CPV code, region, value or date.

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

Common Procurement Vocabulary codes or prefixes, one per line. Examples: 72 (IT services), 45 (construction work), 85 (health and social work). The form 72000000-5 also works. Several values combine with OR.

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

UK regions where the contract is performed, one per line: names such as London, Scotland, Wales, North West, ITL codes such as UKI, UKM, UKD3, or UK for the whole country. Notices for the whole UK are always kept. Leave empty for all regions.

## `noticeTypes` (type: `string`):

Which kind of notices to return: calls for tender (default), contract awards, pipeline and market engagement notices, or all notice types including cancellations.

## `publishedWithinDays` (type: `integer`):

Only notices published in the last N days. Minimum 1, maximum 90, default 7. Ignored when Published from is set.

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

Optional start date (YYYY-MM-DD). Replaces Published within (days). A run covers at most 90 days.

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

Optional end date (YYYY-MM-DD), included. Leave empty for up to today.

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

Keep notices whose estimated value in GBP is at least this amount, excluding VAT. Notices without a published value, or valued in another currency, are dropped when a value limit is set.

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

Keep notices whose estimated value in GBP is at most this amount, excluding VAT.

## `openOnly` (type: `boolean`):

Calls for tender only: keep notices whose submission deadline is today or later. Default: enabled. Disable it to include notices whose deadline has passed.

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

Upper limit of notices returned. Minimum 1, default 1000. The run stops as soon as it is reached.

## Actor input object example

```json
{
  "cpvCodes": [
    "45"
  ],
  "noticeTypes": "contract-notices",
  "publishedWithinDays": 7,
  "openOnly": true,
  "maxResults": 20
}
```

# Actor output Schema

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

Dataset items of the run: one item per result, with the fields described in the dataset schema.

# 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 = {
    "cpvCodes": [
        "45"
    ],
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("boubap/uk-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 = {
    "cpvCodes": ["45"],
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("boubap/uk-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 '{
  "cpvCodes": [
    "45"
  ],
  "maxResults": 20
}' |
apify call boubap/uk-tenders-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,boubap/uk-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/RVhHQP7waoU2vWJie/builds/A168R1RWdihWbeI39/openapi.json
