# UK Public Tenders Tracker - Contracts Finder & Find a Tender (`agentic_solutions/uk-public-tenders-tracker`) Actor

Track UK public sector tenders from the official Contracts Finder and Find a Tender open data. Filter by keyword, CPV, value, region and deadline, with daily new-or-changed alerts. OGL v3 data. Not affiliated with or endorsed by the Cabinet Office.

- **URL**: https://apify.com/agentic_solutions/uk-public-tenders-tracker.md
- **Developed by:** [Agentic Solutions](https://apify.com/agentic_solutions) (community)
- **Categories:** Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.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 Public Tenders Tracker

I built this because UK tenders are split across two government services, and keeping an eye on both by hand is tedious. Since Brexit, UK notices no longer appear on TED, so if you already follow EU tenders you need a separate UK feed.

This actor reads the official open data feeds behind **Contracts Finder** (lower-value contracts in England, plus the wider public sector) and **Find a Tender** (higher-value UK contracts). It returns one clean row per notice, and you can filter them by keyword, CPV code, value, region and deadline.

### What you get

For each tender:

- title, a short summary, and the full description
- buyer name, town, region and postcode (organisation details only, no personal contact names or emails)
- CPV codes, category and procurement method
- estimated value and currency
- submission deadline (for Contracts Finder, checked against each notice, because the bulk feed sometimes shows times a few hours off), contract start and end, and whether it's flagged as suitable for SMEs
- a direct link to the notice on the official site
- `source`, `licence`, `licenceUrl` and `attribution` fields, so every row carries its Open Government Licence credit
- `changeStatus` (`new`, `changed` or `unchanged`) and a `contentHash`

### Daily alerts

Turn on **Only new or changed since last run** and schedule the actor once a day. It remembers what you've already received and only returns notices that are new, or whose deadline, value, status or text has changed. Use a different **State store name** for each alert list you keep.

Pair it with an Apify integration (email, Slack, Google Sheets, Make or Zapier) and you have a free-form tender alert service.

### Input examples

New software and digital tenders from the last week:

```json
{ "keywords": ["software", "digital"], "publishedWithinDays": 7, "onlyNewOrChanged": true }
```

IT services (CPV 72) worth £100k or more on Find a Tender, still open after 1 November:

```json
{ "sources": ["findATender"], "cpvCodes": ["72"], "minValue": 100000, "deadlineFrom": "2026-11-01" }
```

Construction work in London:

```json
{ "cpvCodes": ["45"], "regionContains": ["London"] }
```

### Pricing

Pay per result: **$0.004 per tender** delivered. There's no start fee. Runs stop at **Max tenders**, so you always know the most a run can cost.

### How it treats the source services

- It uses only the published OCDS APIs. No scraping of web pages, and no login.
- It makes about one request per second per service, and identifies itself with a clear User-Agent.
- If Find a Tender answers "too many requests" (HTTP 429), the actor waits as long as the `Retry-After` header asks. If Contracts Finder signals its rate limit (HTTP 403), the actor pauses for five minutes, as its documentation asks. If the limit is still there after that pause, the actor stops using that source for the rest of the run instead of pushing harder.
- Filters on keywords, CPV codes, value, region and deadline are applied after download, because the official APIs only filter by date and stage. For wide date ranges with narrow filters, raise **Max pages per source**.

### Data licence and attribution

Contains public sector information licensed under the [Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/).

- Contracts Finder data: © Crown copyright, from https://www.contractsfinder.service.gov.uk
- Find a Tender data: © Crown copyright, from https://www.find-tender.service.gov.uk

If you republish the data, keep the attribution. Every output row includes it for that reason. Government logos and crests are not covered by the OGL, and this actor doesn't use any. The data is provided as published, so always check the official notice before you bid.

Not affiliated with or endorsed by the Cabinet Office, Contracts Finder, Find a Tender or any UK government body. "Contracts Finder" and "Find a Tender" are used only to describe the data sources.

### Questions or ideas

Open an issue on the actor page. I read them, and I'm happy to add filters that people actually use.

Built by Agentica.

# Actor input Schema

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

Which official feeds to search. Leave both on for full coverage.

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

Match any of these words in the title or description (case-insensitive). Leave empty for all tenders.

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

Full CPV codes (72000000) or prefixes (72). A notice matches if any of its CPV codes starts with one of these.

## `regionContains` (type: `array`):

Text to look for in the buyer's region, town, postcode or delivery locations, e.g. 'London' or 'SN3'.

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

Skip notices with a lower or missing estimated value.

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

Skip notices with a higher or missing estimated value.

## `deadlineFrom` (type: `string`):

Only tenders whose submission deadline is on or after this date (YYYY-MM-DD).

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

Look back this many days. Ignored if 'Published from' is set.

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

Fixed start date (YYYY-MM-DD).

## `stages` (type: `array`):

OCDS stages. 'tender' = open opportunities; 'planning' = early market engagement; 'award' = contract awards.

## `onlyNewOrChanged` (type: `boolean`):

For daily alerts: skip notices you've already received unless they changed (deadline, value, text...).

## `maxItems` (type: `integer`):

Stop after this many tenders (each one is billed).

## `maxPagesPerSource` (type: `integer`):

Each page is up to 100 notices. Raise it for wide date windows with narrow filters.

## `stateStoreName` (type: `string`):

Named key-value store for the new/changed memory. Use different names to keep separate alert lists.

## Actor input object example

```json
{
  "sources": [
    "contractsFinder",
    "findATender"
  ],
  "keywords": [],
  "publishedWithinDays": 3,
  "stages": [
    "tender"
  ],
  "onlyNewOrChanged": false,
  "maxItems": 10,
  "maxPagesPerSource": 20
}
```

# Actor output Schema

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

All output records (default dataset, 'overview' view).

## `runStats` (type: `string`):

RUN_STATS JSON: counts, errors, billing errors.

# 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 = {
    "sources": [
        "contractsFinder",
        "findATender"
    ],
    "keywords": [],
    "publishedWithinDays": 3,
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("agentic_solutions/uk-public-tenders-tracker").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 = {
    "sources": [
        "contractsFinder",
        "findATender",
    ],
    "keywords": [],
    "publishedWithinDays": 3,
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("agentic_solutions/uk-public-tenders-tracker").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 '{
  "sources": [
    "contractsFinder",
    "findATender"
  ],
  "keywords": [],
  "publishedWithinDays": 3,
  "maxItems": 10
}' |
apify call agentic_solutions/uk-public-tenders-tracker --silent --output-dataset

```

## MCP server setup

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

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/MwWtnnZ0lwWF57ENP/builds/gkaDcqq1CzhM4yGsD/openapi.json
