# EU TED Tenders Scraper & API: Public Procurement (`tuper/ted-tenders`) Actor

EU TED tenders scraper & API, $2 per 1,000 results: paste keywords or a CPV code, get EU public procurement notices, contract awards with winners and a daily new-tender monitor as JSON/CSV/Excel. Official TED API v3.

- **URL**: https://apify.com/tuper/ted-tenders.md
- **Developed by:** [Tuper Ops](https://apify.com/tuper) (community)
- **Categories:** Lead generation, Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

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 TED Tenders API do?

**EU TED Tenders API** gets European public procurement notices from **[TED](https://ted.europa.eu)** (Tenders Electronic Daily, the EU's official journal of public tenders) as clean JSON, CSV or Excel, straight from the **official TED API v3**. **No scraping, no proxies, no login, no API key.** It covers every notice TED publishes (871,149 in 2025) from all 27 EU countries plus Norway, Switzerland and other countries that publish on TED.

Three modes:

- **Search notices**: by **keywords** (full text, any EU language), **CPV codes**, **buyer country** or **place of performance**, **publication date range**, **notice type** (calls for tenders, contract awards, prior information, corrigenda) and **only open tenders** (deadline not passed).
- **Notice details**: give publication numbers (`756266-2026`) or TED links and get each notice as one row.
- **Monitor new tenders**: run it on a daily schedule and each run returns **only the notices published since the last run** for your filters. A tender alert feed for Slack, email, Google Sheets or your CRM through Apify integrations.

Try it: open the Input tab, keep the example (software, CPV 72000000) and click **Start**. A run takes a few seconds.

### Why use it?

- **Reliable**: it calls the Publications Office's own search API, the one ted.europa.eu runs on. No HTML parsing that breaks when the site changes, no browser, no proxy, so runs do not fail on blocks. Errors in your filters come back with TED's own message, and the run fails cleanly without charging for results.
- **Every match, not the first 15,000**: TED's search caps page-by-page results at 15,000; this Actor uses TED's iteration mode and walks through all of them.
- **Ready-to-use columns**: title, buyer, country, city, contact email, CPV codes, contract type, procedure, **tender deadline**, **estimated value and currency**, lots, **documents and submission links**, and for awards the **winners, their countries and the awarded value**. Links to the TED page, PDF and XML for every notice.
- **No per-minute surprises**: $0.002 per result, platform usage included; capped by Max results.

### How to use EU TED Tenders Scraper & API

1. Open the **Input** tab and pick **What to get**: `search`, `notices` (publication numbers or TED URLs you already have) or `monitor` (only notices published since the last run).
2. Set keywords, CPV codes, countries (buyer or place of performance), publication dates and notice types; tick **Only open tenders** to skip closed ones.
3. Set **Max results** and click **Start**.
4. Download the notices from the **Output** tab or the Apify API. For tender alerts, use `monitor` with a daily **Schedule**: each run returns only new notices (see How the monitor works).

### Use from Claude / any MCP client

AI agents can call this Actor through Apify's hosted MCP server and pay per event, no setup beyond an Apify token.

- MCP URL (one Actor as a tool): `https://mcp.apify.com?tools=tuper/ted-tenders` (older clients: `https://mcp.apify.com?actors=tuper/ted-tenders`)
- Auth: send your Apify API token as `Authorization: Bearer <token>`.
- Claude Code: `claude mcp add --transport http apify-ted-tenders "https://mcp.apify.com?tools=tuper/ted-tenders" --header "Authorization: Bearer $APIFY_TOKEN"`
- The tool is named `tuper--ted-tenders`. Example task: Find 10 open German software tenders.
- Example tool arguments: `{"mode": "search", "keywords": ["software"], "countries": ["DEU"], "openOnly": true, "maxResults": 10}`
- Read results with `get-dataset-items` and the `datasetId` the call returns. Set `maxResults` to cap the cost.

### How much does it cost?

Pay per event: **$0.002 per result** ($2 per 1,000 results) plus a $0.00005 start fee. Apify platform usage (compute) is included, you do not pay it on top, and Apify's free plan credit covers your first runs. Set **Max results** and the Actor stops there.

### Input

| Field | Used by | What it does |
|---|---|---|
| `mode` | all | `search`, `notices` or `monitor` |
| `keywords` | search, monitor | full-text search; several = any of them; a multi-word entry is a phrase |
| `cpvCodes` | search, monitor | e.g. `72000000` (IT services), `45000000` (construction), `33000000` (medical); a code includes its sub-codes |
| `countries` | search, monitor | `DE`, `FR`, `PL` or `DEU`, `FRA`; with `countryField` = `buyer` (default) or `place` of performance |
| `dateFrom`, `dateTo` | search | publication date, YYYY-MM-DD, inclusive |
| `noticeTypes` | search, monitor | `competition` (calls for tenders), `result` (awards), `planning`, `change`, `dir-awa-pre`, `cont-modif` |
| `openOnly` | search, monitor | only tenders whose deadline is today or later |
| `expertQuery` | search, monitor | any [TED expert query](https://docs.ted.europa.eu/api/latest/search.html), ANDed with the rest, e.g. `estimated-value-proc>=1000000` |
| `sort` | search | `newest` or `oldest` first |
| `noticeIds` | notices | publication numbers or TED notice URLs |
| `lookbackDays` | monitor | first run returns the last N days (default 7) |
| `monitorKey` | monitor | optional name for the monitor's saved state |
| `language` | all | preferred language for multilingual fields (default English) |
| `maxResults` | all | stop after this many notices (default 100) |

Example: open construction tenders in Poland and Czechia worth 1M+:

```json
{ "mode": "search", "cpvCodes": ["45000000"], "countries": ["PL", "CZ"], "openOnly": true, "noticeTypes": ["competition"], "expertQuery": "estimated-value-proc>=1000000", "maxResults": 500 }
```

Example: a daily alert of new cybersecurity tenders anywhere in the EU (schedule this daily):

```json
{ "mode": "monitor", "keywords": ["cybersecurity", "penetration test"], "noticeTypes": ["competition"], "lookbackDays": 3 }
```

### Sample output

Open IT tenders (CPV 72000000 and 48000000 families) published on TED on 30 October 2026, from a real run:

| Published | Title | Buyer | Country | CPV | Deadline | Estimated value | Notice |
|---|---|---|---|---|---|---|---|
| 2026-10-30 | Framework agreement for the development and further development... | Møre og Romsdal Fylkeskommune | NOR | 72243000 | 2026-12-03 | 32,000,000 NOK | [756324-2026](https://ted.europa.eu/en/notice/-/detail/756324-2026) |
| 2026-10-30 | HRM- ja palkkajärjestelmän hankinta | Espoon kaupunki | FIN | 48000000 | 2026-11-06 | 8,000,000 EUR | [756345-2026](https://ted.europa.eu/en/notice/-/detail/756345-2026) |
| 2026-10-30 | EU aanbesteding Applicatie schuldhulpverlening | Gemeente Helmond | NLD | 72000000 | 2026-12-01 | 560,000 EUR | [755546-2026](https://ted.europa.eu/en/notice/-/detail/755546-2026) |
| 2026-10-30 | Procedura di gara aperta ai sensi degli art. 59 e 71 D. Lgs. ... | Cassa depositi e prestiti S.p.A. | ITA | 72260000 | 2026-11-19 | 4,981,200 EUR | [756167-2026](https://ted.europa.eu/en/notice/-/detail/756167-2026) |
| 2026-10-30 | Contratación de servicios de apoyo en puesta en marcha, operación... | Consejero Delegado de Ingeniería de Sistemas... | ESP | 72000000 | 2026-11-30 | 1,741,350 EUR | [755676-2026](https://ted.europa.eu/en/notice/-/detail/755676-2026) |
| 2026-10-30 | Nová generácia zberu údajov o objektoch a zariadeniach... | Výskumný ústav vodného hospodárstva | SVK | 72223000 | 2026-11-12 | 1,525,309 EUR | [755240-2026](https://ted.europa.eu/en/notice/-/detail/755240-2026) |

One full row (a contract award, trimmed):

```json
{
  "publicationNumber": "755019-2026",
  "formType": "result",
  "noticeType": "can-standard",
  "title": "Przedłużenie subskrypcji oprogramowania Symantec",
  "buyerName": "Urząd Komisji Nadzoru Finansowego",
  "buyerCountry": "POL",
  "cpvMain": "48517000",
  "publicationDate": "2026-10-30",
  "winners": ["Passus S.A."],
  "winnerCountries": ["POL"],
  "awardedValue": 492000,
  "awardedValueCurrency": "PLN",
  "noticeUrl": "https://ted.europa.eu/en/notice/-/detail/755019-2026",
  "pdfUrl": "https://ted.europa.eu/en/notice/755019-2026/pdf",
  "source": "ted-api-v3"
}
```

Titles and names come in the buyer's language; `noticeTitle` adds TED's translated prefix (country and CPV in the language you choose). Fields TED does not have for a notice are `null`.

### How the monitor works

The Actor saves a small state record (newest publication date delivered and which notices of that day it already sent) in a named key-value store in your account, `ted-tenders-monitor`, one record per filter set. Each run asks TED for notices from that date on and returns only the ones not sent before, oldest first. If a run stops at your max results or max charge, the next run picks up exactly where it stopped. Change the filters and a new monitor starts; set `monitorKey` to keep one monitor while you edit its filters. TED publishes on weekdays, so a daily schedule at any hour works.

### Use cases

- **Bid teams and consultancies**: a daily feed of new calls for tenders in your CPV codes and countries, into Slack, email or a sheet.
- **Market research and sales intelligence**: who buys what, at what value, and **who wins** (award notices with winners and values).
- **Tender platforms and AI agents**: a clean, documented source of EU procurement data, callable per request.

### Data source and terms

Data comes from the TED API v3 of the Publications Office of the European Union (anonymous access to published notices). Per the [TED legal notice](https://ted.europa.eu/en/legal-notice): "Unless otherwise noted, the procurement notices published in the Supplement to the Official Journal of the European Union can be freely reused, for commercial or non-commercial purposes." Source: © European Union, TED, https://ted.europa.eu. This Actor is not affiliated with or endorsed by the European Union.

### FAQ

**Is this allowed?** Yes. It reads the official TED API v3 anonymously, and the EU allows free reuse of published notices, also commercially (see Data source and terms below).

**How do I get only new tenders every day?** Use `monitor` mode with a daily Schedule. Each run returns only the notices not delivered before, for the same filters.

**Can I use it from my code or an AI agent?** Yes: call it through the Apify API, the Apify MCP server or any integration (Make, Zapier, n8n, Google Sheets).

**Something is wrong or missing?** Open an issue on the Issues tab; we read every one.

### Other official-API Actors by tuper

Same approach (official public APIs, no scraping, pay per result):

- [Hacker News Scraper & API](https://apify.com/tuper/hacker-news): stories, search, comment trees, Who is hiring jobs
- [UK Companies House Scraper & API](https://apify.com/tuper/companies-house): UK companies, directors, PSC owners, filings
- [OpenAlex Scraper & API](https://apify.com/tuper/openalex-papers): academic papers, authors, citations
- [GitHub Repo Scraper & API](https://apify.com/tuper/github-repos): repository search by language, topic, stars

### Who made this

This Actor is built and maintained by an AI agent of [Tuper](https://tuper.app/open), a small company run by AI agents with every number public. If something is wrong or missing, open an issue on the Issues tab.

# Actor input Schema

## `mode` (type: `string`):

search = all notices matching your filters; notices = specific notices by publication number; monitor = only notices published since this monitor's last run (schedule it daily for tender alerts).

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

Full-text search across the whole notice in any EU language (TED's FT search). Several keywords = any of them. A phrase like 'cloud hosting' is matched as a phrase.

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

Common Procurement Vocabulary codes, e.g. 72000000 (IT services) or 45000000 (construction). A code also matches all its sub-codes. Check digit (72000000-5) is accepted.

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

ISO codes, 2 or 3 letters: DE, FR, PL or DEU, FRA. Several = any of them.

## `countryField` (type: `string`):

buyer = the contracting authority's country; place = where the contract is performed.

## `dateFrom` (type: `string`):

Publication date on TED, YYYY-MM-DD, inclusive. Not used by monitor.

## `dateTo` (type: `string`):

Publication date on TED, YYYY-MM-DD, inclusive. Not used by monitor.

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

Empty = all. competition = open calls for tenders; result = contract awards (winners, values); planning = prior information; change = corrigenda; dir-awa-pre = direct award pre-announcements; cont-modif = contract modifications.

## `openOnly` (type: `boolean`):

Keep only notices whose tender deadline is today or later.

## `expertQuery` (type: `string`):

Any TED expert-search query, ANDed with the filters above, e.g. buyer-name~"university" or estimated-value-proc>=1000000. Syntax: docs.ted.europa.eu.

## `sort` (type: `string`):

newest or oldest publication date first.

## `noticeIds` (type: `array`):

For mode 'notices': TED publication numbers like 756266-2026 or notice URLs like https://ted.europa.eu/en/notice/-/detail/756266-2026.

## `lookbackDays` (type: `integer`):

On a monitor's first run, deliver notices published in the last N days. Later runs deliver only what is new.

## `monitorKey` (type: `string`):

State is kept per filter set automatically. Give a name to keep it stable when you edit filters, or to run several monitors with the same filters.

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

Preferred language for multilingual fields (falls back to English, then the original).

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

Stop after this many notices (each notice = one result you pay for).

## Actor input object example

```json
{
  "mode": "search",
  "keywords": [
    "software"
  ],
  "cpvCodes": [
    "72000000"
  ],
  "countryField": "buyer",
  "openOnly": false,
  "sort": "newest",
  "lookbackDays": 7,
  "language": "eng",
  "maxResults": 100
}
```

# Actor output Schema

## `results` (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 = {
    "keywords": [
        "software"
    ],
    "cpvCodes": [
        "72000000"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tuper/ted-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"],
    "cpvCodes": ["72000000"],
}

# Run the Actor and wait for it to finish
run = client.actor("tuper/ted-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"
  ],
  "cpvCodes": [
    "72000000"
  ]
}' |
apify call tuper/ted-tenders --silent --output-dataset

```

## MCP server setup

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