# TED Tenders — EU Public Procurement Notices & Awards (`publicdata/ted-tenders-eu-procurement`) Actor

Scrape EU tenders and procurement notices from TED (Tenders Electronic Daily): European public tender notices and contract awards from all EU countries plus Switzerland, with buyer, CPV codes, deadlines, estimated value and winners. Export to JSON, CSV or Excel; schedule a daily feed.

- **URL**: https://apify.com/publicdata/ted-tenders-eu-procurement.md
- **Developed by:** [PublicData](https://apify.com/publicdata) (community)
- **Categories:** Lead generation, Other
- **Stats:** 1 total users, 1 monthly users, 95.8% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.25 / 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.
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?

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

**Stop checking the TED portal by hand: get every EU tender that matches your country, sector and keywords delivered as a structured file — and see who won the comparable contracts, and for how much.**

This Actor turns TED (Tenders Electronic Daily), the official journal of European public procurement, into a filtered JSON, CSV or Excel feed. It covers the contract notices and contract awards published by every EU member state, the EEA countries and Switzerland (Swiss GPA notices appear on TED too — 11,584 of them in 2025), 904,387 notices in the twelve months to 20 August 2026, about 75,000 a month. No login, no API key, no proxy.

It reads the official TED Search API v3 with **iteration paging**, so an export is not capped at the 15,000-result window of the web interface: seven months of one country's call-for-competition notices come out in a single run — all 11,739 of Italy's published between 1 January and 31 July 2026, not a subset, in 104 seconds (drained live on 21 August 2026). Notices come out newest first, ordered by publication number, which TED issues in publication order.

### What you get

Every notice is flattened into one row, ready for Sheets, a database or a BI tool.

**Identification and dates**

- `publicationNumber` — the TED publication number, and a natural deduplication key
- `publicationDate`, `noticeType` (`cn-standard`, `can-standard`, `pin-only`, `qu-sy` …) and `noticeTypeLabel`, the plain-English version — `noticeTypeLabel` is `null` for any code the Actor does not carry a label for, while `noticeType` always holds TED's raw code

**What is being bought**

- `title` and `description` in your preferred language, falling back to the notice's own language when no translation exists
- `cpvMain` and `cpvCodes` — the full Common Procurement Vocabulary list
- `contractNature` (works, supplies or services) and `procedureType` (open, restricted, negotiated …)

**Who is buying, and where the work happens**

- `buyerName`, `buyerCity`, `buyerCountry` (ISO-3)
- `placeOfPerformanceNuts` — NUTS region codes

**The two fields that decide whether you bid**

- **`estimatedValue`** with `currency`
- **`offerDeadline`** — the deadline for receipt of tenders

**On award notices, the competitive intelligence**

- **`winnerNames`**, `winnerCountries` and `awardDecisionDate` — filled on award notices only
- `totalValue` — **not an award-only field, and not proof that anything was awarded.** On an award notice it is the awarded value and normally differs from `estimatedValue`. On an ordinary call-for-competition notice TED fills it too, where it is simply a copy of `estimatedValue`. Measured live on 21 August 2026 over all 11,739 Italian call-for-competition notices published between 1 January and 31 July 2026: `totalValue` was present on 11,367 of them and equal to `estimatedValue` on all 11,365 rows carrying both. Read `noticeType` / `noticeTypeLabel`, never `totalValue`, to tell an awarded contract from an open tender.

**Links and provenance**

- `pdfUrl` and `xmlUrl` — the official notice documents in your chosen language edition
- `tedUrl` — the notice page on ted.europa.eu
- `source` — carried on every record for attribution

### Who uses this

- A **bid manager** at a construction or IT firm runs a daily feed of new tender notices for two countries and three CPV families, and reads the deadlines before the competition does.
- A **sales lead** pulls award notices for their sector to see which rivals win which buyers, and at what price.
- A **compliance or public-affairs analyst** checks whether a counterparty appears as a winner of public contracts, and in which member states.
- A **researcher or journalist** exports several years of European public procurement notices for one CPV branch and compares values by country.
- An **AI agent or developer** calls the Actor as an MCP tool or over the API and passes a raw TED expert query, using the full search grammar without writing a TED client.

### Example output

Both records below were exported from the live API on 21 August 2026 (fields the notice leaves empty are omitted here).

A contract notice (tender you can still bid on):

```json
{
  "publicationNumber": "575842-2026",
  "publicationDate": "2026-08-20",
  "noticeType": "cn-standard",
  "noticeTypeLabel": "Contract notice",
  "title": "Italia – Sistemi diagnostici – fornitura quinquennale in service di un sistema diagnostico per allergologia in vitro su siero con reagenti, materiale di consumo e assistenza tecnica, da destinare alla U.O.C. di Patologia Clinica del P.O. di Paternò (CT)",
  "buyerName": "AZIENDA SANITARIA PROVINCIALE DI CATANIA",
  "buyerCity": "Catania",
  "buyerCountry": "ITA",
  "cpvMain": "33124110",
  "cpvCodes": ["33124110"],
  "contractNature": "supplies",
  "procedureType": "open",
  "estimatedValue": 1360000.0,
  "totalValue": 1360000.0,
  "currency": "EUR",
  "offerDeadline": "2026-10-06",
  "placeOfPerformanceNuts": ["ITA", "ITG17"],
  "pdfUrl": "https://ted.europa.eu/it/notice/575842-2026/pdf",
  "tedUrl": "https://ted.europa.eu/it/notice/575842-2026",
  "source": "TED (Tenders Electronic Daily), Publications Office of the EU"
}
```

An award notice adds the result of the competition (on this one `totalValue` happens to match the estimate; across a July 2026 sample of 800 Italian award notices it differed from `estimatedValue` on 521 of the 712 rows carrying both):

```json
{
  "publicationNumber": "575424-2026",
  "noticeTypeLabel": "Contract award notice",
  "buyerName": "Provincia Autonoma di Trento",
  "winnerNames": "Dolomiti Energia Mercato SpA",
  "winnerCountries": ["ITA"],
  "awardDecisionDate": "2026-08-18",
  "estimatedValue": 89380900.0,
  "totalValue": 89380900.0,
  "currency": "EUR"
}
```

### Input

| Field | What it does |
|---|---|
| `noticeGroup` | `tenders` (open competitions, default), `awards` (winners and values), `planning` (prior information notices), `all`. Each group covers its whole TED form-type; `awards` also carries contract modifications. |
| `buyerCountries` | ISO-3 codes of the contracting authority: `ITA`, `DEU`, `FRA`, `CHE`, `AUT`, `ESP` … Empty means all countries. |
| `cpvCodes` | Full CPV codes (`45000000`) or wildcard prefixes: `45*` construction, `72*` IT services, `33*` medical, `34*` transport equipment. |
| `fullText` | Keyword(s) searched across the whole notice, using TED's `FT~` operator (any word form). |
| `publishedFrom` / `publishedUntil` | Date window, `YYYY-MM-DD`. Must be real calendar dates between 2000-01-01 and 2099-12-31 — the range TED's own `publication-date` filter accepts — and anything else (`2026-13-45`, `2026-02-30`, `1999-01-01`) is refused before the run starts instead of failing mid-run. An empty string, or the field left out entirely, means no bound: `publishedFrom` then defaults to 7 days ago and `publishedUntil` to no upper bound. |
| `expertQuery` | A raw TED expert query for full control, sent to TED untouched. When set, every field above is ignored — including the dates, so add your own `publication-date` clause or you search the whole archive. Sort it with `SORT BY publication-number DESC`. |
| `language` | Preferred language for titles, descriptions and the PDF link. Default `en`. |
| `maxItems` | Safety cap. Default 500; `0` means unlimited, since iteration paging handles any size. Results are newest first, so the cap keeps the newest matches. |

Last week's Italian construction tenders, with Italian titles:

```json
{ "noticeGroup": "tenders", "buyerCountries": ["ITA"], "cpvCodes": ["45*"], "language": "it" }
```

Who has been winning IT contracts in Germany and Austria this year — every award, no cap:

```json
{
  "noticeGroup": "awards",
  "buyerCountries": ["DEU", "AUT"],
  "cpvCodes": ["72*"],
  "publishedFrom": "2026-01-01",
  "language": "de",
  "maxItems": 0
}
```

Anything the TED expert search supports, passed through untouched — which also means nothing is added: no date window, no sort order. Put both in the query yourself, and sort by `publication-number` (unique per notice) rather than `publication-date` (many notices share one date):

```json
{ "expertQuery": "(buyer-country=ITA) AND (FT~(\"fotovoltaico\")) AND (publication-date>=20260101) SORT BY publication-number DESC" }
```

### Run it on a schedule

Save your filters as a Task and leave the two date fields empty (or absent): each run then covers the last 7 days. **Schedule it weekly, not daily** — the window and the cadence then match, and every notice is exported, and charged, exactly once.

A daily schedule on that same 7-day default re-exports the previous six days on every run, and this Actor charges per exported notice, so you pay for each notice about seven times. Measured live on 21 August 2026 on Italian call-for-competition notices: a run with the default window exported and charged 218 notices, of which 34 had been published that day; the other 184 were re-exports of 14–20 August that an earlier run had already paid for. Seven such runs a week charge roughly 1,500 notices for the ~218 a single weekly run would cover.

If you do want a daily feed, set `publishedFrom` to a fixed recent date and move it forward yourself through the API, or accept that the overlap is billed — there is no relative "last 1 day" option, only the fixed 7-day default. The overlap is a billing cost, not a data problem: deduplicate on `publicationNumber`, which is unique and stable per notice, so a rolling window never puts the same tender in your sheet twice.

Attach an Apify integration to the schedule and the results land where you already work: **Google Sheets**, **Slack**, **e-mail**, a **webhook** into your own system, or **Make** and **Zapier** for your CRM.

### Use it from code or from an AI agent

Start a run and read the dataset through the Apify API or CLI, with JSON or CSV export straight from the dataset endpoint. The Actor is also exposed through the Apify MCP server, so an AI agent can call it as a tool — and `expertQuery` lets that agent express a precise question without a purpose-built public tenders API client.

### Pricing

Pay per event: a small fee for each notice exported, shown in the pricing box on this page. There is no browser and no proxy involved — only API calls — so Apify platform usage on top of that is negligible. Every exported row is charged, including a row an overlapping date window makes you export a second time, so match your schedule to your date window (see **Run it on a schedule**).

### Where the data comes from

Every record comes from the official TED Search API of the Publications Office of the European Union. TED data is free for commercial and non-commercial reuse under the Commission's open-data policy (Decision 2011/833/EU) with attribution to the source, and each record carries `source: TED (Tenders Electronic Daily), Publications Office of the EU`.

Honest limits: TED holds notices above the EU publication thresholds, so smaller contracts published only on national portals are not here. Notices appear on their publication day, not in real time. `winnerNames`, `winnerCountries` and `awardDecisionDate` are filled on award notices only; `totalValue` is not, and duplicates `estimatedValue` on ordinary tender notices. Tender documents, buyer contact details and lists of unsuccessful bidders are not in the API response; use `tedUrl` or `pdfUrl` for the full official notice. Some notice types sit outside all three notice groups — voluntary ex-ante transparency (`veat`, an intended direct award rather than an awarded contract), prior market consultations (`pmc`), business-registration notices (`brin-ecs`, `brin-eeig`), completion notices (`compl`) and the discontinued legacy corrigendum (`corr`, last published 2025-04-16): select `all`, or name them in an expert query, if you want them. `noticeTypeLabel` is a convenience lookup rather than an exhaustive index of TED's code list, so it can be `null` if TED introduces a new code; checked on 21 August 2026, it covered every notice type published from 2023-01-01 to 2026-08-21 (3,049,457 notices, none unlabelled). Paging follows TED's iteration cursor, which advances by the query's sort key, so the Actor sorts by `publication-number` — the only notice field guaranteed unique — and logs an error if a run ever ends short of the match count TED reported. This Actor is independent and not affiliated with the EU institutions.

### Frequently asked questions

**Can TED data be reused commercially?**

Yes. TED data is free for commercial and non-commercial reuse under the Commission's open-data policy (Decision 2011/833/EU) with attribution, which every record carries in its `source` field.

**Does the EU Tenders Scraper cover Switzerland and the EEA?**

Yes. Swiss GPA notices are published on TED too, alongside every EU member state and the EEA countries.

**Is there a limit on how much I can export?**

No. The Actor uses TED's iteration paging, so an export is not capped at the 15,000-result window of the web interface. A full year of one country's tenders comes out in a single run.

**Why are winner fields empty on some rows?**

Winner names and awarded values exist only on award notices. On a contract notice — a tender still open for bids — there is no winner yet, so those fields are null rather than guessed.

### Related Actors

Same engine, same official-source approach:

- [**AusTender (Australia)**](https://apify.com/publicdata/austender-australian-government-contracts) — federal contracts, winners and expiry dates
- [**UK Public Tenders**](https://apify.com/publicdata/uk-contracts-finder-find-a-tender) — Contracts Finder and Find a Tender in one run
- [**Swiss Public Tenders (simap.ch)** — tenders and awards with prices, bid counts and weighted criteria](https://apify.com/publicdata/simap-swiss-public-tenders)
- [**Swiss Commercial Register (SHAB)** — new companies, changes, deletions and bankruptcies](https://apify.com/publicdata/shab-swiss-company-gazette)
- [**France Company Register** — SIREN/SIRET, executives, official labels](https://apify.com/publicdata/sirene-siren-french-company-search)
- [**GLEIF LEI** — LEI lookup, lapsed-LEI screening, parent companies](https://apify.com/publicdata/gleif-lei-scraper)
- [**Brazil CNPJ** — Receita Federal company data and partners](https://apify.com/publicdata/cnpj-lookup-receita-federal)

# Actor input Schema

## `noticeGroup` (type: `string`):

Tenders = open competitions you can bid on (every call-for-competition notice type). Awards = results with winners and values, plus contract modifications (competitor intelligence). Planning = prior information notices. Awards does not include voluntary ex-ante transparency notices (veat), which announce an *intended* direct award rather than a result - pick "All notice types" or use an expert query if you want those too.

## `buyerCountries` (type: `array`):

Three-letter country codes of the contracting authority, e.g. ITA, DEU, FRA, CHE (yes, Swiss GPA tenders are on TED too), AUT, ESP. Two-letter codes such as 'IT' are rejected by TED. Empty = all countries.

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

Common Procurement Vocabulary codes. Full codes (45000000) or wildcard prefixes (45\*). Examples: 45\* construction, 72\* IT services, 33\* medical, 34\* transport equipment. Use the 8-digit code without the check digit: TED rejects '45233120-6' but accepts '45233120'.

## `fullText` (type: `string`):

Optional keyword(s) searched in the whole notice, e.g. "ospedale", "software", "photovoltaic". Uses TED's FT~ operator (any word form).

## `publishedFrom` (type: `string`):

Only notices published on/after this day. Must be a real calendar date between 2000-01-01 and 2099-12-31 - that is the range TED's publication-date filter accepts. Leave empty (or omit the field) to fall back to the default, 7 days ago.

## `publishedUntil` (type: `string`):

Only notices published on/before this day. Must be a real calendar date between 2000-01-01 and 2099-12-31. Leave empty (or omit the field) for no upper bound.

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

Optional raw TED expert-search query, passed to TED untouched, e.g. (buyer-country=ITA) AND (classification-cpv IN (45\*)) AND (publication-date>=20260101) SORT BY publication-number DESC. When set, every field above is ignored - including the dates: no default date window is added, so without your own publication-date clause this searches the entire TED archive. Add SORT BY publication-number DESC for newest-first results; do not sort by publication-date, because TED's iteration paging drops notices that share a sort value across a page boundary (~12% of a large export).

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

Titles/descriptions are picked in this language when the notice provides it (fallback to the notice's own language); the PDF link points to this language edition.

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

Safety cap on exported notices (0 = unlimited; the Actor uses TED's iteration paging, so any size works). Results come back newest first (highest publication number), so the cap keeps the newest matches - except with an expert query that has no SORT BY clause, where TED returns the oldest first.

## Actor input object example

```json
{
  "noticeGroup": "tenders",
  "buyerCountries": [
    "ITA"
  ],
  "language": "en",
  "maxItems": 500
}
```

# Actor output Schema

## `dataset` (type: `string`):

Tenders and contract awards from TED. Every exported row is one item in the default dataset.

# 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 = {
    "buyerCountries": [
        "ITA"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("publicdata/ted-tenders-eu-procurement").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 = { "buyerCountries": ["ITA"] }

# Run the Actor and wait for it to finish
run = client.actor("publicdata/ted-tenders-eu-procurement").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 '{
  "buyerCountries": [
    "ITA"
  ]
}' |
apify call publicdata/ted-tenders-eu-procurement --silent --output-dataset

```

## MCP server setup

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

```

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/Nf23WvJmBtPpI7ezL/builds/hDDghxZtfa5TLoBIQ/openapi.json
