# UK Tenders – Find a Tender & Contracts Finder Scraper (`madeform/uk-tenders`) Actor

Scrape new UK public procurement tenders from Find a Tender and Contracts Finder in one run. Filter by keyword, CPV code, region, value or SME suitability. Get buyer, value, deadline, CPV labels and notice links as JSON, CSV or Excel. De-duplicated, only-new mode for alerts. $3 per 1,000 tenders.

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

## Pricing

$3.00 / 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.

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 – Find a Tender and Contracts Finder scraper for UK public procurement

**UK Tenders** collects **UK public sector tenders** from both official government services in one run: **Find a Tender** (FTS, all above-threshold and Procurement Act 2023 notices for England, Scotland, Wales and Northern Ireland) and **Contracts Finder** (CF, lower-value opportunities in England). It reads their official OCDS APIs and turns every notice into one clean row: buyer, **CPV codes with labels**, category, region, **estimated value in GBP**, **submission deadline with days left**, SME suitability, the e-tendering portal link and a link to the original notice. The same notice on both services is returned once. It is made for bid teams, suppliers and analysts who want a daily or weekly list of new UK tenders, filtered by keyword, CPV code, region, value or contract type. With **Only new tenders** switched on, scheduled runs return only what you have not received before. The easiest way to try it: open the Actor and click **Start**. The default input fetches UK tenders from both services published in the last 7 days (max 100), and **users on Apify's free plan get up to 50 tenders per run**.

**Why bid teams use it**

- **Find a Tender and Contracts Finder in one feed**, de-duplicated. No account, no API key and no proxies needed.
- **Ready to act on**: CPV labels, days left to the deadline, value excluding and including VAT, SME/VCSE flags, delivery region and the portal where you register or submit.
- **Procurement Act 2023 ready**: new-regime notices (UK4 tender notices and others) are included next to notices under the old regulations, with the legal framework on every row.
- **Daily tender alerts without duplicates**: with `onlyNew`, each tender is returned and billed once per filter.
- **Simple pricing**: $3.00 per 1,000 tenders, no start fee, and nothing to pay when a run finds no tenders.
- **Minimised personal data**: contact names, e-mail addresses, phone numbers and addresses are left out or removed before the data reaches you.

Need EU tenders as well? [TED Europe Tenders](https://apify.com/madeform/ted-europe-tenders) covers all 30 EU/EEA countries with the same kind of rows. The UK left TED at the end of 2020, so UK tenders are only in this Actor.

### Use cases

- **Bid discovery**: every morning, get new UK tenders in your CPV codes, regions and value range, with deadlines and portal links.
- **B2G sales leads**: see which councils, NHS trusts, universities and central government bodies are buying what, and at what value.
- **SME and VCSE opportunities**: keep only contracts that buyers have marked suitable for small businesses or social enterprises.
- **Tender alerts in Slack, e-mail or Teams**: combine a daily schedule with Make, Zapier or n8n.
- **Market analysis**: compare tender volumes by region, CPV sector, category, procedure or legal framework over time.
- **AI agents and LLM pipelines**: let an assistant find, filter and summarise relevant UK tenders (see "Use it with AI agents" below).

### Example: IT tenders in London and the South East in Google Sheets every morning

An IT services company wants every new public IT contract in London and the South East worth at least £100,000. They set `cpvCodes` to `["72000000", "48000000"]` (IT services and software), `regions` to `["london", "southEast"]`, `minValue` to `100000` and switch on `onlyNew`. The Actor runs on a daily schedule and is connected to Google Sheets. Each morning the sheet gets new rows only, with the buyer, title, value, days left until the deadline and the link to the buyer's e-tendering portal. Tenders that were already delivered yesterday are not returned and not billed again.

### How to use UK Tenders

1. Open the Actor in Apify Console. Keep both **sources** selected, or choose only Find a Tender or only Contracts Finder.
2. Pick the **publication period** (last day, 7 days, 30 days or custom dates).
3. Optional: add **keywords**, **CPV codes**, **regions**, a **value range**, a **contract type**, **above/below threshold** or **SME suitable only**.
4. For scheduled runs, switch on **Only new tenders since the last run**.
5. Set `maxResults` and click **Start**. Open the **Output** tab to view the tenders as a table, or download them as JSON, CSV or Excel.

### Input

| Field | Description |
|---|---|
| `sources` | `FTS` (Find a Tender) and/or `CF` (Contracts Finder). Default: both. |
| `datePreset` | `last1d`, `last7d` (default), `last30d` or `custom`. |
| `publishedFrom`, `publishedTo` | Custom publication dates, `YYYY-MM-DD`. At most one year per run. |
| `keywords` | Comma-separated words or phrases; a tender matches if its title, description, lot titles or buyer name contains any of them. |
| `excludeKeywords` | Comma-separated words or phrases that skip a tender. |
| `cpvCodes` | 8-digit CPV codes, matched by hierarchy prefix (`45000000` matches all of `45…`). |
| `categories` | `works`, `goods`, `services`. |
| `regions` | `england`, `london`, `southEast`, `southWest`, `eastOfEngland`, `eastMidlands`, `westMidlands`, `northWest`, `northEast`, `yorkshire`, `scotland`, `wales`, `northernIreland`. Matches the delivery region, or the buyer's region when no delivery region is given. |
| `minValue`, `maxValue` | Estimated value excluding VAT, in GBP. Tenders without a value are skipped when a value filter is set. |
| `threshold` | `all` (default), `above` or `below` the procurement thresholds. |
| `smeSuitableOnly` | Only notices marked suitable for SMEs. |
| `noticeTypes` | `tender` (default), `tenderUpdate` (changes to earlier tenders) and/or `planning` (pipeline and preliminary market engagement). Award and contract notices are never returned. |
| `onlyOpen` | Skip tenders whose submission deadline has passed. |
| `onlyNew` | Return only tenders not delivered in an earlier run with the same filters. |
| `maxResults` | 1–10,000, default 100. Free plan: at most 50 per run. |

#### Input example

```json
{
  "sources": ["FTS", "CF"],
  "datePreset": "last7d",
  "cpvCodes": ["72000000"],
  "regions": ["london", "southEast"],
  "minValue": 100000,
  "onlyOpen": true,
  "maxResults": 100
}
```

IT tenders worth at least £100,000 in London and the South East, from both services, published in the last 7 days and still open. An empty input `{}` gives all new tender notices from both services for the last 7 days.

### What you get

One row per notice, with these fields:

- **Identity**: `noticeId`, `ocid`, `source` (`FTS`/`CF`), `sourceName`, `noticeType`, `legalFramework`, `publishedDate`, `publishedAt`, `noticeUrl`.
- **What**: `title`, `description` (max 500 characters), `category`, `procedure`, `cpvMain`, `cpvMainDescription`, `cpvCodes`, `cpvDescriptions`, `lotCount`, `lotTitles`.
- **Who and where**: `buyerName`, `buyerTown`, `buyerRegion`, `buyerCountry`, `deliveryRegionCodes`, `deliveryRegions`.
- **Money and dates**: `valueAmount` (excl. VAT), `valueAmountGross` (incl. VAT, FTS), `minValue` (CF ranges), `valueCurrency`, `aboveThreshold`, `tenderDeadline`, `enquiryDeadline`, `daysUntilDeadline`, `contractStart`, `contractEnd`, `durationDays`.
- **Suitability and links**: `smeSuitable`, `vcseSuitable`, `submissionUrl` (the e-tendering portal, when given as a link), `alsoPublishedOn`, `alsoPublishedUrls`.
- **Licence**: `attribution`, `license`, `licenseUrl`, `retrievedAt` on every row.

### Example output

These rows come from a real run with the default input (both services, tender notices, last 7 days) on 29 October 2026 (run `GdgniRDtSHIE3FV8x`, build 0.0.5, 50 rows on the free plan: 46 from Find a Tender and 4 from Contracts Finder). The table shows the most important columns of three of them; values are unchanged.

| source | noticeId | buyerName | title | cpvMainDescription | valueAmount | tenderDeadline | smeSuitable |
|---|---|---|---|---|---|---|---|
| FTS | 102639-2026 | Milton Keynes City Council | Electrical Servicing and Maintenance to Milton Keynes City Council | Electrical installation work | 445000 | 2026-12-04T12:00:00+00:00 | null |
| CF | 1a3ab83a-b601-48e0-b584-55054606f5df | London Borough of Sutton | Prepaid Card Service Adult & Childrens Social Care | Financial and insurance services | 140000 | 2026-10-29T23:59:00Z | true |
| FTS | 102921-2026 | East of England Ambulance Service NHS Trust | EEAST - 26-T20 - Neurodiversity Awareness Training | Education and training services | 1000000 | 2026-11-23T12:00:00Z | true |

A whole row as JSON (same run, unchanged). `daysUntilDeadline` is counted when the row is fetched.

```json
{
  "noticeId": "102639-2026",
  "ocid": "ocds-h6vhtk-07938c",
  "source": "FTS",
  "sourceName": "Find a Tender",
  "noticeType": "tender",
  "legalFramework": "Procurement Act 2023",
  "publishedDate": "2026-10-29",
  "publishedAt": "2026-10-29T13:39:06Z",
  "title": "Electrical Servicing and Maintenance to Milton Keynes City Council",
  "description": "Milton Keynes City Council are currently out to tender for the provision of Electrical Servicing and Maintenance. Suppliers that would like to take part in this tender process are invited to \"Express Interest\" upon which they will be given access to the full tender documentation through this E Tendering system https://in-tendhost.co.uk/milton-keynes/ Suppliers will be notified by email and the tender documents can be accessed from the \"My Tenders\" area of this website be electing the \"view deta…",
  "buyerName": "Milton Keynes City Council",
  "buyerTown": "Milton Keynes",
  "buyerRegion": "South East",
  "buyerCountry": "United Kingdom",
  "category": "services",
  "procedure": "Open procedure",
  "cpvMain": "45310000",
  "cpvMainDescription": "Electrical installation work",
  "cpvCodes": [
    "45310000",
    "50532000",
    "50710000",
    "50711000"
  ],
  "cpvDescriptions": [
    "Electrical installation work",
    "Repair and maintenance services of electrical machinery, apparatus and associated equipment",
    "Repair and maintenance services of electrical and mechanical building installations",
    "Repair and maintenance services of electrical building installations"
  ],
  "valueAmount": 445000,
  "valueAmountGross": 534000,
  "minValue": null,
  "valueCurrency": "GBP",
  "aboveThreshold": true,
  "tenderDeadline": "2026-12-04T12:00:00+00:00",
  "enquiryDeadline": "2026-11-20T23:59:00+00:00",
  "daysUntilDeadline": 35,
  "contractStart": "2027-07-01T00:00:00+01:00",
  "contractEnd": "2030-06-30T23:59:59+01:00",
  "durationDays": null,
  "lotCount": 1,
  "lotTitles": [],
  "deliveryRegionCodes": [
    "UKJ"
  ],
  "deliveryRegions": [
    "South East"
  ],
  "smeSuitable": null,
  "vcseSuitable": null,
  "submissionUrl": "https://in-tendhost.co.uk/milton-keynes/",
  "noticeUrl": "https://www.find-tender.service.gov.uk/Notice/102639-2026",
  "alsoPublishedOn": [],
  "alsoPublishedUrls": [],
  "attribution": "Contains public sector information licensed under the Open Government Licence v3.0. Data modified: contact details removed, text shortened. Not endorsed by the UK Government. Source: Find a Tender (https://www.find-tender.service.gov.uk), retrieved 2026-10-29.",
  "license": "Open Government Licence v3.0",
  "licenseUrl": "https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/",
  "retrievedAt": "2026-10-29T20:05:15.131Z"
}
```

### Limits and errors

- **Rows per run:** `maxResults` 1–10,000 (default 100). On Apify's free plan a run stops at 50 tenders and says so in the status message.
- **Period:** presets `last1d`, `last7d` and `last30d`, or a custom range of at most one year. Each publication day is fetched separately from each service.
- **Speed:** the Actor follows the services' fair-use rules: at most one Find a Tender request every 6 seconds and about one Contracts Finder request per second, with no proxies or IP rotation. A 7-day run over both services usually takes about a minute; large ranges take longer.
- **Timeouts and retries:** every request has a 90-second timeout. Rate limiting (HTTP 429) and server errors (5xx) are retried up to 4 times, waiting the full `Retry-After` when the service sends one, otherwise 2, 4, 8 and 16 seconds. Network errors and timeouts are retried the same way. If Find a Tender asks for a wait longer than 15 minutes, or Contracts Finder still refuses (HTTP 403) after a 5-minute pause, that service counts as failed (see below).
- **When one service fails:** with both services selected, an error from one of them (after the retries, or at once for errors such as HTTP 400) skips that service; the run continues with the other one and the final status message says which service could not be reached, so you know notices are missing. With one service selected, the run fails with that message. Messages show only the status code, never the response body, and rows saved before an error stay in the dataset.
- **Invalid input:** the run stops at once with a message that names the field and shows a valid value, for example `Invalid region "Kent". Use one of: england, london, …`.
- **No results:** the run ends as succeeded with the message `No tenders found.` and tips on how to widen the search. With `onlyNew`, it says that nothing new has been published since the last run.

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

The Actor uses pay per event pricing: **$3.00 per 1,000 tender notices** ($0.003 per saved row), with no start fee and no charge for runs that find nothing. One tender row saved equals one billed event.

| Typical setup | Tenders saved | Cost |
|---|---|---|
| One test run with the default input | up to 100 | up to $0.30 |
| Daily `onlyNew` alert for all new UK tenders, both services (560 tender notices in the 9 days 20–28 Oct 2026: 496 on Find a Tender, 64 on Contracts Finder) | about 1,900 a month | about $5.70 a month |
| Daily alert for one sector or region | typically 50–300 a month | $0.15–$0.90 a month |
| One-off export of 10,000 tenders | 10,000 | $30.00 |

The figures are examples. You pay only for the tenders that are actually saved, and you can cap the cost of any run with **Maximum cost per run** in the run options.

**Free plan:** users on Apify's free plan get at most **50 tenders per run**. For plans and platform credits, see [Apify pricing](https://apify.com/pricing).

**Run time:** the Actor reads the official APIs politely and never uses proxies: at most one request every 6 seconds to Find a Tender and about one per second to Contracts Finder. A run over the last few days takes 1–2 minutes; a 30-day run over both services can take 10–20 minutes. If a service answers with a rate limit, the Actor waits as long as the service asks (Retry-After). Contracts Finder can ask clients to pause for 5 minutes when it is busy; the Actor then waits as the service requires.

### Schedule it and connect it

- **Schedule:** run the Actor every day or week with [Apify schedules](https://docs.apify.com/platform/schedules). For a daily list, combine the schedule with `onlyNew`.
- **API:** start runs and read the dataset through the Apify API.
- **Integrations:** send new rows to other tools through [Apify integrations](https://docs.apify.com/platform/integrations), for example [Make](https://docs.apify.com/platform/integrations/make), [Zapier](https://docs.apify.com/platform/integrations/zapier), [n8n](https://docs.apify.com/platform/integrations/n8n) or [Slack](https://docs.apify.com/platform/integrations/slack).
- **Google Sheets:** use the Actor [Google Sheets Import & Export](https://apify.com/lukaskrivka/google-sheets) to write the dataset to a spreadsheet.
- **Export:** download the dataset as JSON, CSV or Excel.

### Use it from your code: cURL, Python and JavaScript

You can start UK Tenders and read the results through the [Apify API](https://docs.apify.com/api/v2). Get your API token in Apify Console under [Settings → API & Integrations](https://console.apify.com/settings/integrations) and set it as the environment variable `APIFY_TOKEN`.

**cURL**: start a run, wait for it and get the rows in one request.

```bash
curl -X POST "https://api.apify.com/v2/acts/madeform~uk-tenders/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"cpvCodes":["72000000"],"datePreset":"last7d","maxResults":50}'
```

**Python** (`pip install apify-client`):

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("madeform/uk-tenders").call(run_input={
    "regions": ["scotland"],
    "categories": ["works"],
    "datePreset": "last30d",
    "maxResults": 50,
})
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item["noticeId"], item["buyerName"], item["tenderDeadline"])
```

With apify-client 1.x or 2.x, `call()` returns a dict: use `run["defaultDatasetId"]` instead of `run.default_dataset_id`.

**JavaScript / TypeScript** (`npm install apify-client`):

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('madeform/uk-tenders').call({
    keywords: 'cyber security, penetration testing',
    datePreset: 'last30d',
    maxResults: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const item of items) console.log(item.noticeId, item.buyerName, item.tenderDeadline);
```

### Use it with AI agents (MCP)

UK Tenders also works as a tool for AI assistants and agents through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp). Add this server URL to Claude, Cursor, VS Code or any other MCP client, and sign in with your Apify account when asked:

```text
https://mcp.apify.com?tools=madeform/uk-tenders
```

Then ask in plain language, for example: *"Find open UK construction tenders in Wales and the South West worth at least £500,000 published in the last 7 days, sorted by deadline, with buyer, value and portal link."* The agent fills in the input, runs the Actor and reads the rows. Agent runs are billed exactly like normal runs, one event per saved row.

### FAQ

#### Is it legal to use this data?

Find a Tender and Contracts Finder publish their notices under the [Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/), which allows commercial reuse with attribution. The OGL does not cover personal data, and the Actor modifies the data (see "Data source and licence" below). You are responsible for how you use the output.

#### Which tenders are covered?

Find a Tender: notices for all UK nations, including those first published on Public Contracts Scotland and Sell2Wales, under the Procurement Act 2023 and the older regulations. Contracts Finder: opportunities published there, mostly lower-value contracts in England. By default only tender notices (new opportunities) are returned; `noticeTypes` adds tender updates and planning/market engagement notices. Award and contract notices, winners and suppliers are not collected.

#### How up to date is the data?

Every run fetches the notices live from the two official APIs. The Actor keeps no archive of its own. Each row has a `retrievedAt` timestamp.

#### How are duplicates handled?

Within a publication day, the same procurement (`ocid`) is returned once (newest release), and a notice that appears on both services with the same title and buyer is returned once from Find a Tender, with the Contracts Finder link in `alsoPublishedUrls`.

#### How does "only new" work?

With `onlyNew` the Actor remembers how far the last run got, per filter combination, and returns only tenders published after that point. It stores the last publication date and the notice ids handled on that date, nothing else, in a key-value store named `uk-tenders-state` in your own Apify account. If a run stops early (`maxResults`, the free plan limit or your maximum charge), the next run continues where it ended. To start over, delete the key `state-…` in that store.

#### Why are some fields `null`?

The Actor shows only what the notice states. Many notices have no value, some have no deadline, and not every notice gives a delivery region or a portal link.

#### What do I get on the free plan?

Up to 50 tenders per run.

#### Can I see who won a tender?

No. The Actor returns tender and planning notices only, not award notices or suppliers.

#### How is this different from searching on Find a Tender or Contracts Finder?

The websites are made for reading notices one at a time, on two separate services. This Actor combines both, turns them into uniform rows, removes duplicates, remembers what you have already received and sends the result to a spreadsheet, your CRM, an API client or an AI agent on a schedule.

### Minimised personal data

The Actor is built to keep personal data to a minimum:

- It reads only a fixed whitelist of planning and tender fields. Contact points (names, e-mail addresses, phone and fax numbers), street addresses and postcodes, all parties other than the buyer, award and contract data, suppliers and attached documents are never stored or output. Raw notices are never saved.
- Free text (title, description, lot titles, buyer name) is scrubbed of e-mail addresses (including forms such as `name(at)example.gov.uk`), UK and international phone numbers and National Insurance numbers. Names after words such as "contact", "contact officer", "FAO", "Attn", "Dear" or "enquiries to", and names with a title (Mr, Mrs, Ms, Dr), are removed. Removed parts are replaced by `[removed]`. Organisation names are kept.
- Links that contain an e-mail address are dropped.
- The only state kept between runs (`onlyNew`) is a date and notice ids.

Notices may still contain personal data (for example names in free text). You are the controller for your use of the output. Check your lawful basis (typically legitimate interests), your transparency duties under UK GDPR/GDPR Article 14 (information to be provided where personal data have not been obtained from the data subject) and your retention period. Do not use the data for direct marketing to individuals.

Data storage: Apify stores run data in the USA (AWS us-east-1) under Apify's [Data Processing Addendum](https://docs.apify.com/legal/data-processing-addendum) with Standard Contractual Clauses and the UK Addendum; see Apify's [shared responsibility model](https://docs.apify.com/security/shared-responsibility). If you need to keep the data in the UK or EU, export it and delete the dataset after the run.

### Data source and licence

Contains public sector information licensed under the [Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/). Source: [Find a Tender](https://www.find-tender.service.gov.uk) and [Contracts Finder](https://www.contractsfinder.service.gov.uk), Cabinet Office / Crown Commercial Service. Retrieved via the OCDS APIs on the date given in each row's `retrievedAt` field. Every row carries the attribution in its `attribution`, `license` and `licenseUrl` fields.

**The data is modified.** Contact details are left out or replaced by `[removed]`, descriptions are shortened to 500 characters, fields are reformatted (dates, values, regions), and duplicates across the two services are merged. The original notice is the one at `noticeUrl`.

This Actor is an independent tool. It is not affiliated with or endorsed by the UK Government, the Cabinet Office or Crown Commercial Service.

### More from Madeform

- [TED Europe Tenders](https://apify.com/madeform/ted-europe-tenders) – tenders from all 30 EU/EEA countries from TED, $3.00 per 1,000 tenders.
- [TED Nordic Tenders](https://apify.com/madeform/ted-nordic-tenders) – tenders from Sweden, Norway, Denmark, Finland and Iceland, $3.00 per 1,000 tenders.
- [Trafikverket Disruptions](https://apify.com/madeform/trafikverket-disruptions) – Swedish road incidents, roadworks, rail disruptions and train delays, $1.00 per 1,000 rows.

# Actor input Schema

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

Find a Tender (FTS) carries above-threshold and Procurement Act 2023 notices for the whole UK, including notices from Public Contracts Scotland and Sell2Wales. Contracts Finder (CF) carries lower-value English opportunities. Leave both selected to get both; the same notice on both services is returned once.

## `datePreset` (type: `string`):

Which publication dates to include. 'Last day' means yesterday and today. Choose 'Custom dates' to use the two date fields below. With 'Only new tenders' switched on, this period is used for the first run only; later runs continue after the last tender delivered.

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

Used with 'Custom dates' (or whenever filled in, it overrides the period). First publication date to include, format YYYY-MM-DD, for example 2026-10-01. At most one year per run.

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

Last publication date to include, format YYYY-MM-DD. Leave empty for today.

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

Optional. One or more words or phrases separated by commas, for example: cyber security, penetration testing. A tender matches when its title, description, lot titles or buyer name contains any of them (case-insensitive, matching the start of words, so 'school' also finds 'schools').

## `excludeKeywords` (type: `string`):

Optional. Comma-separated words or phrases. Tenders containing any of them are skipped, for example: framework, dynamic purchasing system.

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

Optional. 8-digit CPV codes (the classification of what is procured), for example 45000000 for construction work or 72000000 for IT services. Matching is by prefix of the code hierarchy: 45000000 matches all codes starting with 45, 45210000 matches 4521…. A tender matches when its main or any additional CPV code matches.

## `categories` (type: `array`):

Optional. Only tenders whose main category is one of these. Leave empty for all.

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

Optional. UK regions (ITL 1) where the contract is delivered. When a notice gives no delivery region, the buyer's region is used. Notices that only say 'United Kingdom' are not matched by a region filter.

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

Optional. Only tenders with an estimated value (excluding VAT) of at least this amount. Tenders without a stated value are skipped when a value filter is set.

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

Optional. Only tenders with an estimated value (excluding VAT) of at most this amount.

## `threshold` (type: `string`):

Optional. 'Above threshold' keeps notices above the UK procurement thresholds, 'Below threshold' keeps lower-value notices. Notices that do not say are skipped by both options.

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

Keep only notices where the buyer marked the contract (or a lot) as suitable for small and medium-sized enterprises.

## `noticeTypes` (type: `array`):

Which notices to return. 'Tender' is a new opportunity (tender notice / contract notice). 'Tender update' is a change to an earlier tender (for example a new deadline). 'Planning' covers pipeline, planned procurement and preliminary market engagement notices. Award and contract notices are never returned.

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

Skip tenders whose submission deadline has already passed. Tenders without a stated deadline are kept.

## `onlyNew` (type: `boolean`):

Return only tenders you have not received in an earlier run with the same filters. Use it for scheduled runs so you never pay for the same tender twice. The Actor remembers only the last publication date and the notice ids of that date, in a key-value store named 'uk-tenders-state' in your account.

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

Maximum number of tenders to save (1–10,000). Each saved tender is one billed event. Users on Apify's free plan get at most 50 per run.

## Actor input object example

```json
{
  "sources": [
    "FTS",
    "CF"
  ],
  "datePreset": "last7d",
  "keywords": "software, cloud",
  "cpvCodes": [
    "72000000",
    "48000000"
  ],
  "threshold": "all",
  "smeSuitableOnly": false,
  "noticeTypes": [
    "tender"
  ],
  "onlyOpen": false,
  "onlyNew": false,
  "maxResults": 100
}
```

# Actor output Schema

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

UK tender notices from Find a Tender and Contracts Finder, one row per notice, in the run's default dataset.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("madeform/uk-tenders").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("madeform/uk-tenders").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 '{}' |
apify call madeform/uk-tenders --silent --output-dataset

```

## MCP server setup

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

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/5dyyTmtqAanjmE6yU/builds/cmZnO5k66MeeFHyd6/openapi.json
