# UK & EU Government Tenders Scraper: TED, Find a Tender, Canada (`locaihost/gov-tenders`) Actor

Public procurement tenders & contract awards from UK Find a Tender, UK Contracts Finder, EU TED and CanadaBuys in one normalised schema. Keyword, CPV, country & value filters; returns only new notices on scheduled runs. Official open-data APIs, no personal data.

- **URL**: https://apify.com/locaihost/gov-tenders.md
- **Developed by:** [locaihost data](https://apify.com/locaihost) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.65 / 1,000 tender results

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 & EU Government Tenders Scraper: TED, Find a Tender, Canada

Get **public procurement opportunities and contract awards** from four official government sources in **one clean, consistent format**, and on scheduled runs **only the notices you haven't seen yet**.

![Five real open tenders from UK Find a Tender in this Actor's output: title, buyer, CPV category, closing date and value](https://locaihost.org/img/readme/gov-tenders.png)

| Source | Coverage | Notices |
|---|---|---|
| 🇬🇧 **UK Find a Tender** | Higher-value UK public contracts | Open tenders, awards, planned |
| 🇬🇧 **UK Contracts Finder** | Lower-value UK contracts (councils, NHS, universities…) | Open tenders, awards |
| 🇪🇺 **EU TED** (Tenders Electronic Daily) | All 27 EU countries + EEA (~4,000 notices/day) | Open tenders, awards, prior information |
| 🇨🇦 **CanadaBuys** | Government of Canada | Open tenders |

### Who is it for?

- **Suppliers & bid teams.** A daily list of new tenders in your sector, delivered to Slack, email, a Google Sheet or your CRM, without checking four portals.
- **Bid-intelligence & sales tools.** A normalised multi-country feed to power alerts, dashboards or AI agents.
- **Market & competitor research.** Who is winning which public contracts, from which agencies, for how much.

### Why this one

- **One schema for every country.** Title, buyer agency, status, dates, value, currency, CPV/UNSPSC category, winning supplier, link.
- **New-only mode** (on by default). Each saved task remembers what it already returned, so a daily schedule gives you just the fresh notices, and you **only pay for new results**.
- **Filters that matter:** keywords, CPV/UNSPSC code prefixes, buyer country, minimum value, notice type.
- **Official open-data APIs only.** No scraping of web pages, no proxies, no CAPTCHAs, so runs are fast (about 1–2 minutes) and reliable.
- **Organisations, not people.** Buyers and suppliers are organisations. Email addresses and phone numbers in notice text are replaced with `[email removed]` / `[phone removed]`. Descriptions are the buyer's own text, so a contact officer's name can still appear in them; see the FAQ.

### How to use

1. Click **Try for free** and pick your filters, e.g. keywords `software, cloud` and countries `GB, IE`.
2. Run it once to see the results.
3. **Save it as a task** and add a **daily schedule**. With *Only new since last run* on, each run returns just the new notices.
4. Connect an integration (Slack, email, Google Sheets, Zapier, Make, webhooks) to get them where you work.

#### Example input

```json
{
  "keywords": ["software", "cloud", "cyber"],
  "cpvCodes": ["72", "48"],
  "statuses": ["open"],
  "countries": ["GB", "IE"],
  "daysBack": 3,
  "onlyNew": true
}
```

`72` and `48` are CPV prefixes for IT services and software. Other common prefixes: `45` construction, `79` business services, `85` health and social, `90` environmental services, `34` transport equipment.

#### Example output

```json
{
  "source": "uk-contracts-finder",
  "country": "GB",
  "referenceNo": "a9d5130f-67de-4c46-a791-7193d11b6d24-917151",
  "title": "RHUL-27041 Gartner Research Services",
  "description": "Awarded to Gartner UK Limited for Cloud Research Gartner for IT Leadership Team",
  "agency": "Royal Holloway and Bedford New College",
  "category": "CPV 48000000 Software package and information systems",
  "status": "awarded",
  "publishedAt": "2026-10-08",
  "closingAt": "2026-08-11",
  "awardedAt": "2026-08-11",
  "value": 72300,
  "currency": "GBP",
  "supplier": "Gartner UK Limited",
  "url": "https://www.contractsfinder.service.gov.uk/Notice/a9d5130f-67de-4c46-a791-7193d11b6d24",
  "licence": "Contains public sector information licensed under the Open Government Licence v3.0 (UK Cabinet Office).",
  "scrapedAt": "2026-10-10T06:42:16.567Z"
}
```

| Field | Meaning |
|---|---|
| `title` / `description` | Plain text: HTML entities (`&rsquo;`, `&amp;`) decoded and tags (`<br/>`) removed. TED titles come without the "Ireland – Construction work – " prefix TED adds; that CPV label is in `category` instead |
| `country` | Buyer country as ISO 3166-1 alpha-2 (`IE`, `PK`), also for TED, which publishes 3-letter codes |
| `status` | `open` (you can still bid), `awarded`, `planned` (prior information notice), `closed`, `cancelled` |
| `closingAt` | Bid deadline (open tenders) |
| `value` / `currency` | Estimated value for open tenders; awarded amount for awards, where the buyer published one. Placeholder amounts of 0 or 1 (common on UK portals) come back as `null` |
| `supplier` | Winning companies (awards only), `;`-separated |
| `licence` | The publisher's licence and attribution text. Keep it with the data if you republish it |

### Pricing

**Pay per result.** You pay for each tender returned. Fetching, filtering and empty re-runs are free (apart from Apify's $0.00005 run-start fee).

| Apify plan | Price per 1,000 tenders |
|---|---|
| Free and Starter | **$3.00** |
| Scale | $2.25 |
| Business and above | $1.65 |

**Worked example.** A saved task with *Only new* on, scheduled daily, that finds 50 new matching tenders a day costs 50 × $0.003 = **$0.15 a day**, about $4.50 a month on Starter. A first run with `daysBack: 30` across all four sources can return a few thousand notices, so set `maxResults` if you want a hard ceiling.

**Free Apify plan:** each run returns up to **100 tenders**. Any paid Apify plan removes the cap. You can also set a maximum charge per run in the Apify run options.

### Use with AI agents (MCP)

This Actor is a ready-made tool for Claude, Cursor, VS Code and other MCP clients through the [Apify MCP server](https://mcp.apify.com). Agents find it by searching for "UK tenders" or "EU tenders".

1. Add the server. In Claude Code: `claude mcp add apify https://mcp.apify.com/ -t http`. In Cursor or Claude Desktop, add `https://mcp.apify.com` as a remote MCP server. Sign in with your Apify account when asked, or send your API token as `Authorization: Bearer <APIFY_TOKEN>`.
2. To expose only this Actor as a tool, use `https://mcp.apify.com/?tools=locaihost/gov-tenders`.
3. Ask in plain language, for example:

> Find open UK and Irish public tenders for cloud or cyber security work published in the last 7 days, worth at least £100,000. List title, buyer, closing date, value and link.

The minimal input an agent should send:

```json
{
  "keywords": ["cloud", "cyber"],
  "countries": ["GB", "IE"],
  "statuses": ["open"],
  "minValue": 100000,
  "daysBack": 7,
  "onlyNew": false
}
```

Set `onlyNew: false` for one-off questions. With the default `true`, asking the same question twice returns an empty second answer, because those notices were already delivered.

### Integrations

Run it from any language with the Apify API. This call waits for the run and returns the tenders as JSON (synchronous runs time out after 5 minutes; use the async run endpoint for bigger jobs):

```bash
curl -X POST "https://api.apify.com/v2/acts/locaihost~gov-tenders/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keywords": ["software"], "countries": ["GB"], "statuses": ["open"], "onlyNew": false}'
```

Python, with `pip install apify-client`:

```python
from apify_client import ApifyClient

client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("locaihost/gov-tenders").call(run_input={
    "keywords": ["software", "cloud"],
    "countries": ["GB", "IE"],
    "statuses": ["open"],
})
for t in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(t["closingAt"], t["value"], t["currency"], t["title"], t["url"])
```

**Schedules:** save your filters as a task, then add a daily schedule in Apify Console → Schedules. Pair it with *Only new* for an alert feed.

**Where the results go:** Apify's built-in integrations send each run's dataset to Slack, email, Google Sheets, Zapier, Make, n8n (the Apify node) or any webhook.

### FAQ

**How fresh is the data?**
Every run reads the sources live. UK Find a Tender and Contracts Finder publish near real-time, CanadaBuys updates daily, and TED publishes once per business day.

**Is this legal? Where does the data come from?**
Only from the official open-data APIs of the four publishers. Their licences allow commercial reuse with attribution: UK Open Government Licence v3.0, Commission Decision 2011/833/EU (TED) and Open Government Licence – Canada. Each row carries the right attribution text in `licence`.

**Does it return personal data?**
Records describe organisations: buyers and winning suppliers. Email addresses and phone numbers in notice text are replaced. The `title` and `description` fields are the buyer's own words, and some notices name a contact officer or, rarely, the person a contract is for. Don't build contact lists from these fields, and remove any names you don't need before you republish the text.

**Why did a short keyword match unrelated notices?**
Keywords match as plain text inside the title, description and category label. `IT` also matches "subm**it**" and "facil**it**ies". Use longer words (`software`, `cyber`) or CPV prefixes (`72` IT services, `48` software) instead.

**Why did my second run return nothing?**
*Only new* (on by default) skips notices this saved configuration already returned. That's what you want for a daily feed. For a full list every time, set `onlyNew` to `false`.

**How far back can I go?**
Up to 90 days with `daysBack`. For alerts, 3 days on a daily schedule never misses a notice.

**Can you add another country?**
Yes, if it publishes an open-licensed API. Open an issue with the portal's name.

### Troubleshooting

| What you see | What it means and what to do |
|---|---|
| Status `Done: 0 new tenders.` | Nothing new matched since the last run. Widen the filters, raise `daysBack`, or set `onlyNew: false` to see everything again. |
| `Done: 100 tenders (free-plan cap of 100 reached).` | The free plan's per-run cap. Narrow the filters or use any paid Apify plan. |
| `Done: … (1 source(s) failed, see log)` | One portal was down or slow. The others still delivered. Each run looks `daysBack` days back, so the next scheduled run picks up what that source missed. |
| Run failed: `All 4 sources failed — see log.` | None of the portals answered. This is usually a short outage on their side. Try again later. |
| A TED or CanadaBuys link shows a browser check | The publisher's site sometimes shows a bot check to browsers. The link is correct; open it again or search the `referenceNo` on the portal. |
| `value` is `null` | The buyer didn't publish a value, or published a placeholder such as 0 or 1. |

### Good to know

- **Coverage.** UK sources are near real-time. TED publishes once per business day. CanadaBuys updates daily. The UK and EU sources include awards; CanadaBuys covers open tenders.
- **Values** are only present when the buyer published one (most open EU and UK tenders, most awards).
- **TED titles** are in English when the buyer provided an English version, otherwise in the original language. Keyword filters also match the category label (e.g. "Construction work").
- **New-only memory** is per saved task and filter set. Changing filters starts a fresh memory, and so does turning *Only new* off.
- **Licences.** All sources are official open-data publications that allow commercial reuse with attribution: UK Open Government Licence v3.0, Commission Decision 2011/833/EU (TED), and Open Government Licence – Canada.

### Feedback

Missing a country or field? Open an issue on the **Issues** tab. Requests for new open-licensed sources are welcome.

# Actor input Schema

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

Which portals to read. Leave empty for all.

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

Keep notices whose title or description contains ANY of these words (case-insensitive). Leave empty for all.

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

Keep notices whose classification starts with any of these. CPV (UK & EU): 72 = IT services, 48 = software, 45 = construction, 79 = business services, 85 = health, 33 = medical equipment. CanadaBuys uses UNSPSC (e.g. 43 = IT equipment, 81 = engineering & IT services).

## `statuses` (type: `array`):

Open = invitations to tender you can still bid on. Awarded = contract award notices (who won, for how much). Planned = prior information notices.

## `countries` (type: `array`):

e.g. GB, IE, DE, FR, CA. Leave empty for all.

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

Skip notices with no stated value or a value below this (in the notice's own currency).

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

How far back to look on each run. With 'Only new' on, a daily schedule with 3 days back never misses a notice.

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

Skip notices this saved configuration already returned. Ideal for daily schedules and alerts — you only pay for fresh notices.

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

Stop after this many notices. 0 = no limit.

## Actor input object example

```json
{
  "sources": [
    "uk-find-a-tender",
    "uk-contracts-finder",
    "eu-ted",
    "ca-canadabuys"
  ],
  "keywords": [
    "software"
  ],
  "statuses": [
    "open",
    "awarded",
    "planned"
  ],
  "daysBack": 3,
  "onlyNew": true,
  "maxResults": 1000
}
```

# Actor output Schema

## `tenders` (type: `string`):

One record per tender or award notice (dataset items, overview view).

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

Per-source counts of fetched, matched and returned notices, and any source 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 = {
    "keywords": [
        "software"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("locaihost/gov-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 = { "keywords": ["software"] }

# Run the Actor and wait for it to finish
run = client.actor("locaihost/gov-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 '{
  "keywords": [
    "software"
  ]
}' |
apify call locaihost/gov-tenders --silent --output-dataset

```

## MCP server setup

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