# UK Public Tenders Scraper (Find a Tender) (`pohjastudio/uk-public-tenders-find-a-tender-scraper`) Actor

Scrape UK public procurement notices from Find a Tender: buyers, CPV codes, deadlines, contract values, regions and contract winners.

- **URL**: https://apify.com/pohjastudio/uk-public-tenders-find-a-tender-scraper.md
- **Developed by:** [Pohja Studio](https://apify.com/pohjastudio) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## UK Public Tenders Scraper (Find a Tender)

Scrape UK public procurement notices from **Find a Tender**, the UK government's official notice service. Every contract above threshold from central government, councils, the NHS, universities, police and housing associations is published here, in the open OCDS standard.

No API key, no account. Open Government Licence data.

### What you get

| Field | Description |
|---|---|
| `title`, `description` | What is being bought |
| `buyerName`, `buyerRegion`, `buyerLocality`, `buyerPostcode` | The contracting authority |
| `contactEmail`, `contactUrl` | The procurement contact published for bidders |
| `cpvCode`, `cpvDescription`, `allCpvCodes` | CPV classification, including codes on lots and items |
| `category` | Works, services or goods |
| `valueGbp`, `currency` | Contract value where the buyer publishes it |
| `deadline`, `awardPeriodEnd` | Submission deadline and award window |
| `status`, `stages`, `procurementMethod` | Whether it is open, and how it is being run |
| `deliveryRegions`, `lotCount` | Where the work happens, how many lots |
| `awards` | On award notices: winning supplier, award value, gross value |
| `ocid`, `noticeId`, `url`, `publishedAt` | Identifiers and a direct link to the notice |

### Use cases

- **Contractors and suppliers** — find open opportunities in your CPV codes and region before the deadline, instead of reading every notice.
- **Competitive intelligence** — award notices name the winner and the value, so you can see who takes what, at what price, and how often.
- **Bid teams and tender consultancies** — a filtered feed to route to the right bid manager.
- **Market research** — public spend by category, buyer and region over time.
- **CRM enrichment** — buyers with region, postcode and procurement contact.

### Input

| Option | Description |
|---|---|
| `stages` | `tender` for open opportunities, `award` for who won, `planning` for early pipeline. Empty means all. |
| `updatedFrom` / `updatedTo` | Update window. The feed is ordered by update time, so this is the fastest way to narrow a run. |
| `cpvPrefix` | Match any CPV on the notice, its lots or items, e.g. `45` for construction. |
| `keywords` | Keep notices whose title or description contains any of these. |
| `mainCategory` | Works, services or goods. |
| `regionPrefix` | e.g. `UKI` for London, `UKM` for Scotland. |
| `minValueGbp` / `maxValueGbp` | Contract value window. |
| `buyerNameContains` | Filter to one buyer or a group of them. |
| `deadlineAfter`, `onlyOpenForBids` | Keep only what you can still bid on. |
| `maxItems`, `maxPages`, `includeRawFields` | Run size, paging depth, raw OCDS payload. |

#### Example: open construction tenders in London

```json
{
  "stages": ["tender"],
  "cpvPrefix": "45",
  "regionPrefix": "UKI",
  "onlyOpenForBids": true,
  "maxItems": 200
}
```

#### Example: who won IT contracts over £1M this year

```json
{
  "stages": ["award"],
  "cpvPrefix": "72",
  "minValueGbp": 1000000,
  "updatedFrom": "2026-01-01T00:00:00"
}
```

### How filtering works

Find a Tender filters by **stage** and **update window** on its side; everything else — CPV, value, region, keywords, deadline, buyer — is applied by this Actor over the pages it reads, 100 notices per page.

That matters for narrow searches: if you ask for one CPV code in one region, the Actor may need to read several pages before it fills your `maxItems`. Setting `updatedFrom` keeps those runs short.

Value filters are strict: a notice that publishes no contract value does not pass a `minValueGbp` filter rather than slipping through. Many UK notices genuinely omit the value, so expect nulls in that column.

### Data source and licence

Data comes from the Find a Tender OCDS API, published by the Cabinet Office under the [Open Government Licence v3.0](http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/). Contact details in the output are the organisational procurement contacts that buyers publish so that suppliers can respond to the notice.

### Pricing

Billed per notice delivered. Notices that are read but filtered out, and duplicates, are not charged.

# Actor input Schema

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

Which notice types to fetch. Leave empty for all. 'tender' = open opportunities, 'award' = who won and for how much, 'planning' = early pipeline.

## `updatedFrom` (type: `string`):

Only notices updated on or after this date. The feed is ordered by update time, so this is the fastest way to narrow a run.

## `updatedTo` (type: `string`):

Only notices updated before this date.

## `cpvPrefix` (type: `string`):

Keep only notices with a matching CPV code anywhere on the notice, its items or its lots. Examples: 45 = construction, 71 = engineering, 72 = IT services, 79 = business services.

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

Keep notices whose title or description contains at least one of these (case-insensitive).

## `mainCategory` (type: `string`):

Works, services or goods.

## `regionPrefix` (type: `string`):

Keep only notices delivered in, or published by a buyer in, this region. Examples: UKI = London, UKM = Scotland, UKH = East of England.

## `minValueGbp` (type: `integer`):

Drop notices below this contract value. Notices that publish no value at all are also dropped.

## `maxValueGbp` (type: `integer`):

Drop notices above this contract value.

## `buyerNameContains` (type: `string`):

Keep only notices from buyers whose name contains this text.

## `deadlineAfter` (type: `string`):

Only notices whose submission deadline falls on or after this date.

## `onlyOpenForBids` (type: `boolean`):

Keep only active notices whose deadline has not passed.

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

Stop after this many notices. You are charged per notice delivered.

## `maxPages` (type: `integer`):

Safety limit on how deep to page through the feed (100 notices per page) when filters are narrow.

## `includeRawFields` (type: `boolean`):

Attach the untouched OCDS release under `raw`.

## Actor input object example

```json
{
  "stages": [
    "tender"
  ],
  "cpvPrefix": "45",
  "keywords": [
    "roofing",
    "asbestos"
  ],
  "mainCategory": "any",
  "regionPrefix": "UKI",
  "onlyOpenForBids": false,
  "maxItems": 1000,
  "maxPages": 200,
  "includeRawFields": false
}
```

# Actor output Schema

## `notices` (type: `string`):

Tender notices with buyer, CPV codes, deadline, contract value, region and — on award notices — the winning supplier.

## `noticesInConsole` (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 = {
    "stages": [
        "tender"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("pohjastudio/uk-public-tenders-find-a-tender-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 = { "stages": ["tender"] }

# Run the Actor and wait for it to finish
run = client.actor("pohjastudio/uk-public-tenders-find-a-tender-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 '{
  "stages": [
    "tender"
  ]
}' |
apify call pohjastudio/uk-public-tenders-find-a-tender-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,pohjastudio/uk-public-tenders-find-a-tender-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/Y7fsd7L24S3QAr1nj/builds/LeWcVgEih9hOij5Be/openapi.json
