# EU & UK Public Tenders Scraper: TED, Find a Tender (`mrtrelock/public-tenders-scraper`) Actor

Get public procurement tenders and contract awards from TED (all EU countries), UK Find a Tender and Contracts Finder in one clean format. Filter by keyword, CPV code, country, value and deadline, and get only new notices on a schedule. No personal contact data.

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

## Pricing

$2.00 / 1,000 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

### What does EU & UK Public Tenders Scraper do?

**EU & UK Public Tenders Scraper** collects **public procurement notices** (government tenders and contract awards) from three official sources in one run, and returns them in **one clean format**:

- **TED (Tenders Electronic Daily)**: the EU's official tender journal. It covers all 27 EU countries, plus Norway, Iceland, Switzerland and others, and adds roughly 3,000 notices every working day.
- **Find a Tender (UK)**: the UK government's service for public contracts.
- **Contracts Finder (UK)**: smaller UK public contracts, mainly in England.

For each notice you get the title, what's being bought, the buyer, the country, CPV category codes, the estimated or awarded value and currency, the **deadline**, the procedure, and a link to the official notice. Award notices also list the **winning companies**.

### Why use it?

- 🇪🇺🇬🇧 **EU and UK in one tool.** Search 30+ countries at once instead of running a separate scraper for each portal and gluing the results together.
- 🎯 **Filters that matter for bidding:** keywords, CPV codes (a broad code like `72000000` includes every IT services code under it), buyer country, notice type (open tenders, awards, planning), value range, and "hide tenders whose deadline has passed".
- 🔔 **Tender alerts.** Turn on **Only new notices since my last run** and put the tool on a daily schedule. You get, and pay for, only notices you haven't seen.
- 🏆 **Contract awards with winners.** Track who wins public contracts in your market, and for how much.
- 🔒 **Privacy-friendly.** The sources' contact fields (contact names, emails, phone numbers and street addresses) are left out. In description text, emails, phone numbers, UK postcodes and "contact person" sentences are blanked out too, so your dataset holds organisation-level facts.
- ✅ **Official open data, no scraping tricks.** It uses the sources' own public APIs, so it is fast and doesn't break when a website is redesigned.
- 🚫 **No double charges.** Updated versions of the same notice, and the same UK notice published on both UK sites, are saved once.

### Who uses it?

- **Companies that sell to governments** (IT, construction, consulting, cleaning, medical supplies...) looking for new tenders to bid on.
- **Bid managers and tender consultants** running daily alerts for their clients.
- **Sales and market intelligence teams** tracking which competitors win public contracts, and at what price.
- **Researchers and journalists** analysing public spending.
- **Lead-generation and CRM workflows** that want public-sector buyers and opportunities as structured data.

### How to use it

1. Pick your **Sources** (all three are on by default) and **Notice types** (default: open tenders you can still bid on).
2. Narrow it down with **CPV codes**, **Keywords** and/or **Buyer countries**. TED notices are written in the buyer's own language, so for EU-wide searches **CPV codes are the most reliable filter**. Look codes up at https://simap.ted.europa.eu/cpv. On TED, keywords are searched in the full official notice (in every language it is published in), so a match can come from a part of the notice that isn't in the title or description. On the UK sources, keywords are matched in the title and description.
3. Choose how far back to look (**Published within the last N days**, default 7) and, if you like, a **minimum or maximum value**.
4. Click **Start**. Download the results as JSON, CSV, Excel or HTML, or get them through the API.
5. For alerts, tick **Only new notices since my last run** and add a schedule (for example every morning).

### Example output

```json
{
  "source": "ted",
  "noticeId": "722692-2026",
  "noticeType": "open",
  "noticeTypeDetail": "cn-standard",
  "title": "Ausschreibung CITRIX Wartungsverlängerung ab 2027",
  "headline": "Germany – Servers – Ausschreibung CITRIX Wartungsverlängerung ab 2027",
  "description": "Wartungsverlängerung von CITRIX Lizenzen für 3 Jahre",
  "buyerName": "Hannoversche Informationstechnologien AöR / hannIT",
  "buyerCity": "Hannover",
  "buyerCountry": "DE",
  "cpvCodes": ["48820000"],
  "contractNature": "supplies",
  "procedure": "open",
  "estimatedValue": 1568178,
  "awardedValue": null,
  "currency": "EUR",
  "winners": [],
  "publishedAt": "2026-10-20",
  "deadline": "2026-10-23",
  "url": "https://ted.europa.eu/en/notice/-/detail/722692-2026",
  "pdfUrl": "https://ted.europa.eu/en/notice/722692-2026/pdf",
  "scrapedAt": "2026-11-04T16:23:56.124Z"
}
```

A UK contract award (shortened):

```json
{
  "source": "contractsFinder",
  "noticeType": "award",
  "title": "Procurement of Dell laptops 2026/27 - AWARD",
  "buyerName": "West Berkshire Council",
  "buyerCity": "Newbury",
  "buyerCountry": "GB",
  "cpvCodes": [
    "30213000",
    "30213100"
  ],
  "contractNature": "supplies",
  "procedure": "Open procedure",
  "awardedValue": 24112.75,
  "currency": "GBP",
  "winners": [
    {
      "name": "Probrand Ltd",
      "country": null,
      "size": null
    }
  ],
  "publishedAt": "2026-11-04",
  "url": "https://www.contractsfinder.service.gov.uk/Notice/a0ceb58c-5c06-4c5d-8d18-dcffb9a0ca71"
}
```

| Field | Meaning |
|---|---|
| `source` | `ted`, `findATender` or `contractsFinder` |
| `noticeType` | `open` (call for tender), `award`, `planning` or `other` (changes, cancellations) |
| `title` / `headline` | The buyer's title. On TED, `headline` adds the country and category in your chosen language |
| `estimatedValue` / `awardedValue` / `currency` | In the notice's own currency; many buyers don't publish a value |
| `deadline` | Last day to submit a bid (open tenders) |
| `winners` | Winning companies for awards: name, country, size (SME or large) where published |
| `cpvCodes` | EU procurement category codes |
| `url` / `pdfUrl` | The official notice |

The run's **SUMMARY** record (in the key-value store) shows, for each source, how many notices matched, how many were saved, and how many were skipped as duplicates or already seen.

### How much does it cost?

You pay **per notice saved** (see the Pricing tab). Notices removed by your filters, duplicates, and notices skipped by "only new" are free. Use **Max notices per source** and **Max notices in total** to cap the cost of a run.

### Tips

- **Start with CPV codes.** They are the same in every EU language, unlike keywords. Broad codes include everything under them (`45000000` = all construction work).
- **Daily alert recipe:** your CPV codes plus your countries, notice type "Open tenders", 2 days back, "Only new" on, scheduled every morning.
- **Competitor tracking:** notice type "Contract awards", your CPV codes, 30 to 90 days back, then filter the `winners` column.
- Find a Tender only allows about 12 requests a minute, so long date ranges that include awards take a few minutes. TED and Contracts Finder are fast.
- Values are in each notice's own currency; they are not converted.

### FAQ

**Is this legal?** Yes. All three sources are official open-data services. TED notices "can be freely reused, for commercial or non-commercial purposes" (TED legal notice), and the UK sources are published under the Open Government Licence v3.0. Please credit the source if you republish the data.

**Why are some TED titles not in English?** Buyers write notices in their own language. The `headline` field is in the language you choose (default English) and names the country and category, so you can always tell what a notice is about.

**Does it include contact people?** No, on purpose. Contact fields are dropped, and contact sentences, emails and phone numbers are blanked out of descriptions (free text is cleaned automatically, so an unusual format can occasionally slip through). You get the buying organisation, its city and the official notice link, where the contact details for bidding are published.

**Which tenders are on TED?** Public contracts above the EU value thresholds (roughly €140k+ for goods and services from central government, €5.5M+ for works), plus many smaller ones published voluntarily.

**Something's wrong or missing?** Open an issue on the Issues tab and we'll look at it quickly.

# Actor input Schema

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

Where to look. TED covers public tenders from all 27 EU countries plus Norway, Iceland, Switzerland and others (contracts above the EU thresholds). Find a Tender covers UK tenders, mostly larger contracts. Contracts Finder covers smaller UK public contracts, mainly in England.

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

Open = calls for tender you can still bid on. Award = contract award results, with the winning company and value. Planning = early notices about future tenders. Other = changes, cancellations and contract modifications.

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

Keep notices that mention at least one of these words or phrases, e.g. software, cleaning, cyber security. TED notices are written in the buyer's own language, so for EU-wide searches CPV codes (below) work better than English keywords. Leave empty for all notices.

## `excludeKeywords` (type: `array`):

Drop notices whose title or description contains any of these words.

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

EU procurement category codes. A broad code includes every code under it, e.g. 72000000 = all IT services, 45000000 = all construction work, 79000000 = business services, 33000000 = medical equipment. Look codes up at https://simap.ted.europa.eu/cpv

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

2-letter codes or English names, e.g. DE, FR, NL, UK. Leave empty for all countries. The UK sources only run when this is empty or includes UK.

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

1 to 365. Find a Tender only allows about 12 requests a minute, so long ranges that include awards can take several minutes.

## `hideExpired` (type: `boolean`):

Keeps only tenders you can still bid on. Notices without a deadline are kept.

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

In the notice's own currency (EUR, GBP, PLN...). Uses the estimated value, or the awarded value for awards. 0 means no minimum.

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

0 means no maximum.

## `includeNoValue` (type: `boolean`):

Many buyers don't publish a value. This only matters when you set a minimum or maximum value.

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

Put the tool on a schedule to get a daily or weekly tender alert. Notices saved by an earlier run with the same sources, notice types, keywords, CPV codes and countries are skipped, and you don't pay for them again.

## `language` (type: `string`):

2-letter code, e.g. en, de, fr. TED's headline (country, category and title) uses this language. The title and description stay in the language the buyer wrote them in.

## `includeDescription` (type: `boolean`):

Adds the short description of what is being bought.

## `maxResultsPerSource` (type: `integer`):

Newest notices first. You only pay for notices saved.

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

0 means no limit.

## Actor input object example

```json
{
  "sources": [
    "ted",
    "findATender",
    "contractsFinder"
  ],
  "noticeTypes": [
    "open"
  ],
  "keywords": [
    "software"
  ],
  "excludeKeywords": [],
  "cpvCodes": [],
  "countries": [],
  "publishedWithinDays": 7,
  "hideExpired": true,
  "minValue": 0,
  "maxValue": 0,
  "includeNoValue": true,
  "onlyNew": false,
  "language": "en",
  "includeDescription": true,
  "maxResultsPerSource": 1000,
  "maxResults": 0
}
```

# Actor output Schema

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

All tender and award notices found, in one format for every source.

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

What happened for each source.

# 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("mrtrelock/public-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 = { "keywords": ["software"] }

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

```

## MCP server setup

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