# EU & UK Tenders Scraper: TED Procurement + Contracts Finder (`tendoyo/eu-uk-tenders-radar`) Actor

Tenders scraper for EU TED and UK Contracts Finder: public procurement notices and government contracts in one unified schema. Filter by keywords, CPV codes, countries and value; get only new tenders since your last run; optional AI summary + bid fit score.

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

## Pricing

from $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

## EU & UK Tenders Scraper: TED public procurement + UK Contracts Finder government contracts (with AI fit scoring)

Monitor public procurement in **27 EU countries + EEA (TED)** and the **UK (Contracts Finder)** in one feed.
Filter by keyword, CPV code, country, notice stage, value and date. You can switch on **"only new since last run"** for daily alerts. An optional **AI layer** summarises each notice and scores how well it fits *your* company profile.

### Why this Actor

- **One schema for two official sources.** TED Search API v3 and the UK Contracts Finder OCDS feed are normalised into the same fields: title, buyer, country, CPV, value, deadline, stage, links.
- **Built for scheduling.** `onlyNew` remembers what it already delivered, so a daily schedule sends only fresh notices to Slack, e-mail or a CRM via Apify integrations.
- **AI bid/no-bid triage (optional, bring your own key).** You get a plain-English summary, a category and a 0–100 fit score against your `companyProfile`. This works with any OpenAI-compatible endpoint.
- **You pay per result.** You can cap spend with the run's max-charge setting.

### Input highlights

| Field | Example |
|---|---|
| `keywords` | `["cybersecurity", "cloud migration"]` |
| `cpvPrefixes` | `["72", "48"]` (IT services, software) |
| `countries` | `["DE", "FR", "UK"]` |
| `stage` | `tender` / `award` / `all` |
| `daysBack`, `minValue`, `maxItems`, `onlyNew` | |
| `llmEnrichment`, `companyProfile`, `llmApiKey` | optional AI layer |

### Output (one row per notice)

`source, noticeId, noticeType, stage, title, titleOriginal, originalLanguage, description, buyerName, buyerCountry, buyerCity, cpvCodes, contractNature, procedureType, valueAmount, valueCurrency, publishedDate, deadline, smeSuitable, url, pdfUrl, sourceUrl, license`. If the AI layer is enabled, rows also get `llm {summary_en, category, key_requirements, eligibility_flags, fit_score, fit_reason}`.

### Pricing (pay per event)

- Tender notice: **$0.004**
- AI enrichment: **$0.01** per notice (only when enabled)

### Data sources & licences

- TED: EU Publications Office, Search API v3. Reuse is allowed under Commission Decision 2011/833/EU, with attribution.
- UK Contracts Finder: Open Government Licence v3.0.

Each row carries its source URL and licence string. Requests are throttled and send a declared User-Agent.

### Try it in one click

These ready-made example tasks show real output. Open one, click **Try for free** and you get your own copy to edit and run:

- [Find AI and software public tenders in the EU and UK](https://apify.com/Tendoyo/eu-uk-tenders-radar/examples/tenders-ai-software-eu-uk)
- [Get new UK and EU government IT services tenders](https://apify.com/Tendoyo/eu-uk-tenders-radar/examples/tenders-uk-it-services)

### Sample output

Real rows from a recent run (some fields trimmed). The full row schema is shown in the **Output** tab.

```json
[
  {
    "source": "TED",
    "title": "Spain – IT services: consulting, software development, Internet and support – Quinta contratación basada del Acuerdo Marco de homologación de proveedores de ser…",
    "buyerName": "Consorci de Serveis Universitaris de Catalunya (CSUC)",
    "buyerCountry": "ESP",
    "publishedDate": "2026-10-22",
    "deadline": "2026-11-02T13:00:00+01:00",
    "cpvCodes": [
      "72000000"
    ],
    "valueAmount": 373200,
    "valueCurrency": "EUR",
    "procedureType": "restricted",
    "url": "https://ted.europa.eu/en/notice/-/detail/730007-2026",
    "matchedKeywords": [
      "software"
    ]
  },
  {
    "source": "TED",
    "title": "Hungary – Software-related services – UiPath szoftver licenc előfizetés és támogatás",
    "buyerName": "Magyar Nemzeti Bank",
    "buyerCountry": "HUN",
    "publishedDate": "2026-10-22",
    "deadline": "2026-11-24+02:00",
    "cpvCodes": [
      "72260000"
    ],
    "valueAmount": null,
    "valueCurrency": null,
    "procedureType": "open",
    "url": "https://ted.europa.eu/en/notice/-/detail/730047-2026",
    "matchedKeywords": [
      "software"
    ]
  }
]
```

### How much does it cost?

You pay only for results (pay per event). There is no separate compute charge, and you can cap any run with **Max total charge**.

| Scenario | Cost |
|---|---|
| 40 tender notices (one example run) | 40 × $0.004 = **$0.16** |
| Daily alert for one niche, ~15 new notices/day | 450 × $0.004 = **$1.80 / month** |
| Same, with AI bid/no-bid fit score (your own LLM key) | + 450 × $0.01 = **+$4.50 / month** |

A tiny "Actor start" event (about $0.00005) is also charged once per run.

### Use it from your code or tools

Run it and get the results in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/Tendoyo~eu-uk-tenders-radar/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"keywords": ["cybersecurity"], "countries": ["DE", "FR"], "daysBack": 1, "onlyNew": true}'
```

```python
from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("Tendoyo/eu-uk-tenders-radar").call(run_input={"keywords": ["cybersecurity"], "countries": ["DE", "FR"], "daysBack": 1, "onlyNew": true})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

To get alerts, add a **Schedule** (for example daily at 07:00) with `onlyNew: true` where available. Then connect **Slack, e-mail, Google Sheets, Make, Zapier, n8n or a webhook** in the Integrations tab. It also works with AI agents through the Apify MCP server.

### FAQ

**Which countries are covered?**
All countries publishing on TED (EU-27, EEA and others above EU thresholds) plus the UK via Contracts Finder. Use `countries` with ISO codes such as `DE`, `FR`, `UK`.

**Do I get expired tenders?**
Not by default. With `stage: competition`, notices whose submission deadline has already passed are skipped (`excludeExpired`, on by default). Notices without a published deadline are kept.

**Can I get only new notices every day?**
Yes. Set `onlyNew: true` and add a schedule; each notice is delivered once. Connect Slack, e-mail, Google Sheets or a webhook through Apify integrations.

**Are titles translated?**
TED titles are returned in English where TED provides one; the original-language title is kept in `titleOriginal`. The optional AI layer writes an English summary for every notice.

**How do I search by sector instead of keywords?**
Use `cpvPrefixes`, e.g. `["72"]` for IT services, `["48"]` for software packages, `["79"]` for business services.

### Support

Questions, bugs or a source you'd like added: open an issue on the Actor page or e-mail **youcanneverhacktendoyo@gmail.com**. Maintained by [Tendoyo](https://apify.com/Tendoyo).

# Actor input Schema

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

Any-of match. TED: full-text search in all languages (tip: add local-language synonyms). UK: matched in title/description/buyer.

## `cpvPrefixes` (type: `array`):

e.g. 72 (IT services), 48 (software packages), 7222 (IT strategy/consulting). Leave empty for all.

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

ISO 3166-1 alpha-3 codes, e.g. DEU, FRA, IRL, NLD. Applies to TED only.

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

ted = EU Tenders Electronic Daily (27 EU + EEA); uk = UK Contracts Finder.

## `stage` (type: `string`):

tender = open calls; award = contract awards; all = both.

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

Look back this many days (ignored if 'Published since' is set).

## `publishedSince` (type: `string`):

Optional absolute start date.

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

Drop notices with a lower (or unknown) estimated value. Currency as published.

## `excludeExpired` (type: `boolean`):

Only applies when stage is "competition". Drops notices whose submission deadline is already in the past (some feeds republish or amend old notices). Notices without a deadline are kept.

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

Maximum number of notices to output (and charge for).

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

Remember delivered notices (per filter set) and skip them next time. Ideal for scheduled daily runs - you only pay for new notices.

## `llmEnrichment` (type: `boolean`):

Adds an English summary, category, key requirements and a 0-100 fit score. Charged per enriched notice.

## `companyProfile` (type: `string`):

1-5 sentences about what you sell, where, and typical deal size. Used for the fit score.

## `llmApiKey` (type: `string`):

Bring your own key. Stored encrypted by Apify.

## `llmBaseUrl` (type: `string`):

Base URL of an OpenAI-compatible API, e.g. https://api.openai.com/v1.

## `llmModel` (type: `string`):

Model name passed to the OpenAI-compatible endpoint.

## `ukMaxPages` (type: `integer`):

Upper bound on Contracts Finder pages fetched (100 notices each).

## `contactEmail` (type: `string`):

Optional. Sent in the User-Agent header as good API citizenship.

## Actor input object example

```json
{
  "keywords": [
    "artificial intelligence",
    "machine learning",
    "software"
  ],
  "sources": [
    "ted",
    "uk_contracts_finder"
  ],
  "stage": "competition",
  "daysBack": 7,
  "excludeExpired": true,
  "maxItems": 200,
  "onlyNew": false,
  "llmEnrichment": false,
  "llmBaseUrl": "https://api.openai.com/v1",
  "llmModel": "gpt-4o-mini",
  "ukMaxPages": 30
}
```

# Actor output Schema

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

Normalized EU TED and UK Contracts Finder notices, with the optional AI bid/no-bid fit score.

## `runSummary` (type: `string`):

JSON stats for the run: items pushed, sources queried, charged events and warnings.

# 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": [
        "artificial intelligence",
        "machine learning",
        "software"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tendoyo/eu-uk-tenders-radar").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": [
        "artificial intelligence",
        "machine learning",
        "software",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("tendoyo/eu-uk-tenders-radar").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": [
    "artificial intelligence",
    "machine learning",
    "software"
  ]
}' |
apify call tendoyo/eu-uk-tenders-radar --silent --output-dataset

```

## MCP server setup

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

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/YR0zSD6ae3UcJSGKi/builds/wWNhwASbYUzRW99Yb/openapi.json
