# TED Europa Tenders Scraper (`parseforge/ted-europa-tenders-scraper`) Actor

Scrape TED Europa tender notices and contract award notices: title in English, buyer, country, CPV codes, deadline, value, winner and 245 eForms fields. Daily tender alerts by country, CPV, keyword or expert query.

- **URL**: https://apify.com/parseforge/ted-europa-tenders-scraper.md
- **Developed by:** [ParseForge](https://apify.com/parseforge) (community)
- **Categories:** Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

[![ParseForge](https://raw.githubusercontent.com/ParseForge/apify-assets/main/banner.jpg)](https://apify.com/parseforge?fpr=vmoqkp)

### TED Europa Tenders Scraper

**Scrape EU tender notices and contract award notices from TED (Tenders Electronic Daily) — every notice with its title in English, the buyer, the country, the CPV codes, the submission deadline, the contract value and the winning supplier.** No login, no API key, no browser. Built for daily tender alerts: point it at the last day and it returns only what was published since. Export to CSV, JSON, Excel, or XML.

TED is the EU's official journal supplement for public procurement: every contract above the EU threshold in 27 member states plus Norway, Switzerland, Iceland and the Western Balkans is published there. The website itself sits behind an AWS captcha, and its search API takes an expert query language, an explicit list of 1,830 field names and three different pagination rules. This Actor drives that API and returns one flat row per notice, with the fields you asked for and nothing you did not.

| Who uses it | What they scrape TED tender notices for |
|---|---|
| Bid and capture teams | Daily tender alerts for their CPV codes and countries, with the deadline and the submission portal link |
| Public-sector sales | Which authorities buy what they sell, who they bought it from last time and for how much |
| Competitive and supplier intelligence | Contract award notices naming a competitor, with the awarded value, the ranking and the number of bids received |
| Procurement analysts and researchers | Award rates, framework agreements, green and reserved procurement flags across a country or a whole sector |
| Tender-alert and government-tender platforms | A deduplicated daily feed keyed on TED's own publication number |

### What it does

This Actor searches TED's official API — 7.0 million notices back to 26 August 2016, about 2,500 new ones every working day — and returns one row per notice:

- 📋 **The notice** (always): publication number, title in your language, publication and dispatch dates, OJS issue, notice type and stage, procedure type, contract type, CPV codes, buyer name, country, region and city, total value and currency, tender deadline, and links to TED's own HTML, PDF and XML.
- 🏛️ **Buyer details** (optional): full address, e-mail, phone, contact point, buyer profile URL, legal type and main activity.
- 📦 **Lot details** (optional): per-lot titles, descriptions, estimated values, durations, place of performance, and the award criteria with their weights.
- 🏆 **Award and winner details** (optional): winner name, VAT identifier, address and company size, the awarded value, contract number and date, tender ranks, and how many bids arrived — including how many came from SMEs and from outside the EEA.
- 📑 **Participation conditions** (optional): exclusion grounds, selection criteria, framework agreements, dynamic purchasing systems, e-submission and e-invoicing, guarantees, reserved and green procurement, EU funding.
- 📎 **Tender documents** (optional): links to the procurement documents and the submission portal, their languages and access restrictions.
- ⚖️ **Review and appeal bodies** (optional): the body that hears appeals, its address, and the deadline for lodging one.
- 🏢 **Other organisations, corrections, legacy codes, full text and all 24 title translations** (optional, one block each).

A row with everything switched on carries about 150 columns drawn from 245 TED fields.

Every filter runs inside TED's own index, so a search by country, CPV code or keyword costs a single request instead of a sweep.

### Titles in English, whatever language the buyer filed in

TED machine-translates every notice title into all 24 official EU languages, and this Actor picks the one you asked for. A Czech hospital's notice comes back as *"Czechia – Medical consumables – Dodávky jednorázových bipolárních elektrochirurgických nástrojů…"*: the English summary first, then the buyer's own wording.

Descriptions, lot texts and buyer names exist only in the language the buyer filed in — TED does not translate those. Those fields fall back to the original, and every row carries a `textLanguages` field naming the language buckets it actually used, so a run set to German never silently hands you Polish while claiming otherwise.

### Filter by CPV code

CPV (Common Procurement Vocabulary) codes are how TED classifies what is being bought, and matching is hierarchical: asking for the division `72000000` also returns `72263000`, `72210000` and every other code beneath it. Pick whole divisions from the list — IT services, construction work, medical equipment, transport and 41 more — or put exact eight-digit codes in the expert query.

### What you can do with TED procurement data

**Get a daily tender alert for your sector.**

A construction firm schedules a run every morning with `buyerCountries: ["DEU", "AUT"]`, `cpvCodes: ["45000000"]` and `publishedLastDays: 1`, and pushes the new rows straight into its CRM.

**Only see tenders you can still bid on.**

Switch on **Only tenders still open** and TED drops everything whose submission deadline has passed — 510,000 Spanish notices become the 26,000 that are actually live.

**Watch a competitor.**

Set `winnerName` to a company and switch on the award block to get every contract it has won: the buyer, the value, where it ranked and how many others bid.

**Build a market-sizing dataset.**

Pull every contract award notice in a CPV division for a year with the award and lot blocks on, and total the awarded values by buyer, country and supplier size.

**Search the full text.**

`keywords: "artificial intelligence"` searches the whole notice body, not just the title, across every language.

### Why choose this scraper

|  | What you get |
|---|---|
| **The whole archive** | 7.0M notices back to 26 August 2016, not just what is currently open |
| **245 TED fields** | Eleven optional blocks, each charged only when you switch it on |
| **English titles everywhere** | TED's own translations, so one keyword search reaches all 24 languages |
| **Deduplicated, in order** | Sorted on a unique key, so parallel pages never repeat a row and a deep run never stops early |
| **No 15,000-row ceiling** | Past TED's page window the Actor switches to token iteration and keeps going |
| **Expert query passthrough** | Anything TED's own expert search accepts, including `today(-7)`, `IN (…)` and `NOT` |
| **No browser, no proxy, no key** | The API is open; a run is HTTP requests and nothing else |

### How it compares

| Feature | ParseForge | Other TED scrapers |
|---|---|---|
| Notice, buyer, CPV, deadline, value, winner | Yes | Yes |
| Per-lot descriptions, values and award criteria | Yes | Not listed |
| Participation conditions, e-submission, EU funding flags | Yes | Not listed |
| Review and appeal body with the appeal deadline | Yes | Not listed |
| Bids received, split by SME and non-EEA | Yes | Not listed |
| Title in all 24 EU languages | Yes | Not listed |
| Legacy TED codes for pre-2024 archive notices | Yes | Not listed |
| Only-still-open filter | Yes | Not listed |
| Runs past 15,000 rows | Yes | Not listed |
| Pay only for the blocks you enable | Yes | Single flat price |

### Configure the run

Pick a window, add filters, set the maximum number of notices. Every extra block is off by default.

A first run with the defaults:

```json
{
  "publishedLastDays": 3,
  "maxItems": 50
}
```

Daily tender alerts for one sector:

```json
{
  "publishedLastDays": 1,
  "buyerCountries": ["DEU", "AUT", "CHE"],
  "cpvCodes": ["45000000"],
  "formTypes": ["competition"],
  "maxItems": 500,
  "includeLotDetails": true,
  "includeDocuments": true
}
```

Live tenders you can still bid on, closing next month:

```json
{
  "onlyActive": true,
  "cpvCodes": ["72000000"],
  "deadlineBefore": "2026-10-31",
  "maxItems": 1000,
  "includeLotDetails": true
}
```

Every contract a competitor has won:

```json
{
  "winnerName": "Siemens",
  "formTypes": ["result"],
  "publishedAfter": "2024-01-01",
  "maxItems": 2000,
  "includeAwardDetails": true
}
```

An expert query, exactly as TED's own expert search takes it:

```json
{
  "expertQuery": "buyer-country IN (FRA ESP) AND classification-cpv=33000000 AND total-value>=1000000 AND publication-date>=today(-30)",
  "maxItems": 500,
  "includeAwardDetails": true
}
```

### Limits

- **TED's API caps a page at 250 notices and at 10,000 field-values.** The more blocks you switch on, the smaller the pages get: 250 notices per request with the base fields, 40 with all eleven blocks on. A 5,000-notice run takes 20 requests with the base row and 125 with everything.
- **Page numbers stop working at 15,000 rows.** Past that the Actor switches to TED's iteration token, which is sequential rather than three pages at a time, so very large runs are slower per row. A verified 16,000-notice run took 64 requests and returned no duplicates.
- **Sorting is on the publication number, not the publication date.** TED accepts `SORT BY publication-date DESC`, but the key is not unique: a paged sweep of one month came back 14% duplicated, and a token iteration with that sort silently stopped yielding at 4,750 rows while still reporting 59,945 matches. The publication number is unique and TED orders it by year and sequence, so it is both stable and genuinely newest-first.
- **The archive starts on 26 August 2016.** Earlier dates return nothing rather than an error.
- **Notices before the 2024 eForms switchover carry the legacy two-letter codes**, not the modern field names. Switch on **Legacy TED codes** when scraping the older archive, or those rows will look sparse.
- **Only titles are translated.** Descriptions, lot texts and buyer names come in the buyer's own language; `textLanguages` records which.
- **A handful of fields repeat per lot.** A three-lot notice lists its contract type three times; the Actor deduplicates every field before writing it, and keeps a real array only where the values genuinely differ.
- **A run stops when it reaches its cost ceiling.** Apify caps what a single run may charge, and with every block enabled a notice costs about $0.016, so the default ceiling is reached after roughly a thousand of them. The Actor stops there and says so in the log rather than collecting a result set it cannot bill for; raise **Max cost per run** in the run options to go further.
- **The run needs 256 MB.** The heaviest configuration measured — 5,000 notices with all eleven blocks — peaked at 129 MB, so there is no reason to pay for more.

### Pricing

Pay-per-event. **$4 per 1,000 notices** (`notice`) plus $0.02 per run start. Extras are charged only when enabled, and only on the notices that carry them:

| Event | Price | When |
|---|---|---|
| `notice` | $0.004 | Every row |
| `lot-details` | $0.0015 | Lot details on |
| `award-details` | $0.0015 | Award and winner details on |
| `full-text` | $0.002 | Full notice text on |
| `buyer-details` | $0.001 | Buyer details on |
| `procurement-conditions` | $0.001 | Participation conditions on |
| `tender-documents` | $0.001 | Tender documents on |
| `title-translations` | $0.001 | All 24 title translations on |
| `review-bodies` | $0.0008 | Review and appeal bodies on |
| `related-organisations` | $0.0008 | Other organisations on |
| `notice-history` | $0.0008 | Corrections and previous notices on |
| `legacy-fields` | $0.0008 | Legacy TED codes on |

| Run | Approximate cost |
|---|---|
| 50 notices, base row | $0.22 |
| 500 daily alerts with lots and documents | $3.27 |
| 1,000 notices with lots and awards | $7.02 |
| 5,000 award notices with the award block | $27.52 |

New Apify accounts start with $5 in free credit.

### Free users

Free-plan runs return up to 10 notices as a preview. [Upgrade your Apify plan](https://console.apify.com/sign-up?fpr=vmoqkp) to pull the whole archive.

### Run it

1. [Create a free Apify account with $5 in credit](https://console.apify.com/sign-up?fpr=vmoqkp).
2. Open the [TED Europa Tenders Scraper](https://apify.com/parseforge/ted-europa-tenders-scraper?fpr=vmoqkp).
3. Pick a window and your filters, then click **Start**.
4. Export the results as CSV, Excel, JSON, or XML from the **Dataset** tab, or schedule the run daily.

Run it programmatically through the [Apify API](https://docs.apify.com/api/v2) (`run-sync-get-dataset-items`) or the [ApifyClient](https://docs.apify.com/api/client/js) for JavaScript and Python.

### Use with AI agents (MCP)

Give an AI agent live access to EU procurement through the Model Context Protocol. Add the Actor to Claude, Cursor, or any MCP client:

```bash
claude mcp add --transport http apify "https://mcp.apify.com?tools=parseforge/ted-europa-tenders-scraper"
```

Then ask: *"Which German IT tenders published this week are still open, and when is each deadline?"*

### FAQ

**Is the data public?** Yes. TED is the EU's official publication channel for public procurement; every notice is published for anyone to read. The Actor reads TED's own public search API.

**How current is it?** TED publishes on every working day, and notices appear in the API the same morning they hit the Official Journal. A run with `publishedLastDays: 1` catches them.

**Do I need an API key for TED?** No. TED's search API is open and unauthenticated. The single-notice endpoints do need a key, which is why this Actor reads everything through the search API instead.

**Why is `winnerName` empty on most rows?** Only contract award notices name a winner. Filter with `formTypes: ["result"]` to get only those.

**Why does a notice appear twice with different publication numbers?** TED republishes a corrected notice under a new number. Switch on **Latest version only** to keep one row per notice.

**Can I get more than 15,000 notices in one run?** Yes. Set `maxItems` higher and the Actor switches to TED's iteration token automatically; it is slower per row but has no ceiling.

# Actor input Schema

## `publishedLastDays` (type: `integer`):

Rolling window for daily monitoring: 1 returns yesterday and today. Overrides the published-from and published-to dates below. Leave empty to use exact dates instead.

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

Stop after this many notices. TED publishes roughly 3,000 a day and about 600,000 a year, so always pair a large number with filters. Free-plan runs return up to 10 as a preview.

## `sortOrder` (type: `string`):

Newest first is the publication number descending, which is stable across pages. Sorting by publication date instead looks the same but reshuffles ties between requests and silently truncates deep runs, so it is not offered.

## `onlyActive` (type: `boolean`):

Keep only notices whose submission deadline has not passed — the ones you can still bid on. Turns roughly 510,000 Spanish notices into 26,000.

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

Country of the contracting authority, ISO 3166 alpha-3. Multiple values are ORed. Leave empty for all of Europe.

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

Common Procurement Vocabulary codes. Matching is hierarchical, so the division 72000000 also returns 72263000 and 72210000. Pick divisions here or type exact 8-digit codes in the expert query.

## `keywords` (type: `string`):

Searches the whole notice body, not just the title. Quoted as a phrase, e.g. artificial intelligence.

## `titleKeywords` (type: `string`):

Searches the notice title, including its machine translations, so an English word finds Polish and Greek notices too.

## `formTypes` (type: `array`):

The stage of the procurement. Competition is the live call for tenders, result is the award, planning is the prior information notice.

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

The exact eForms notice subtype. Narrower than the stage above; leave empty unless you need one form.

## `contractNature` (type: `array`):

Works, supplies or services.

## `procedureTypes` (type: `array`):

The award procedure the buyer is running.

## `publishedAfter` (type: `string`):

YYYY-MM-DD. TED's archive starts on 2016-08-26. Ignored when Published in the last N days is set.

## `publishedBefore` (type: `string`):

YYYY-MM-DD, inclusive.

## `deadlineAfter` (type: `string`):

YYYY-MM-DD. Keeps notices whose deadline for receipt of tenders falls on or after this date.

## `deadlineBefore` (type: `string`):

YYYY-MM-DD, inclusive.

## `performanceCountries` (type: `array`):

Where the contract is carried out, which is not always the buyer's country.

## `buyerName` (type: `string`):

Part of the contracting authority's name, e.g. ministry.

## `winnerName` (type: `string`):

Part of an awarded supplier's name. Only matches contract award notices.

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

Total value of the notice, in the currency TED recorded (usually EUR). Notices with no published value are excluded when this is set.

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

Upper bound on the total value.

## `onlyLatestVersions` (type: `boolean`):

Drop superseded versions when a notice has been corrected, keeping one row per notice.

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

TED expert search, passed through untouched and replacing every filter above. Supports =, ~, IN (...), ranges, AND/OR/NOT and today(-7), e.g. buyer-country=DEU AND classification-cpv=72000000 AND publication-date>=today(-7). Sorting is added for you unless you write your own SORT BY.

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

Language for the notice title, which TED machine-translates into all 24 EU languages. Descriptions and buyer names exist only in the language the buyer filed in, so those fall back to the original and the row records which language it used.

## `includeBuyerDetails` (type: `boolean`):

Full contracting authority block: address, e-mail, phone, contact point, buyer profile URL, legal type and main activity. 21 extra fields.

## `includeLotDetails` (type: `boolean`):

Per-lot titles, descriptions, estimated values, durations, place of performance and award criteria with their weights. 35 extra fields.

## `includeAwardDetails` (type: `boolean`):

For contract award notices: winner name, identifier, address, company size, awarded value, contract number and date, tender ranks and how many bids were received. 35 extra fields.

## `includeConditions` (type: `boolean`):

Exclusion grounds, selection criteria source, framework agreement and dynamic purchasing system flags, e-submission and e-invoicing, guarantees, reserved and green procurement, EU funding. 36 extra fields.

## `includeDocuments` (type: `boolean`):

Links to the procurement documents and the submission portal, document languages and restrictions, and the organisations that provide and receive them. 14 extra fields.

## `includeReviewBodies` (type: `boolean`):

The body that hears appeals, its address and the deadline description, plus the review information point and mediator. 15 extra fields.

## `includeRelatedOrganisations` (type: `boolean`):

Additional information point, tender evaluator and the eSender that filed the notice. 13 extra fields.

## `includeNoticeHistory` (type: `boolean`):

Change description and reason, the section that changed, the previous notice in the procedure and the framework notice it belongs to. 12 extra fields.

## `includeLegacyFields` (type: `boolean`):

The pre-eForms two-letter codes (TD, PR, NC, PC, RC, AA…). These are the only shape older archive notices carry, so switch this on when scraping before 2024. 29 extra fields.

## `includeFullText` (type: `boolean`):

The complete notice body as TED indexes it, in the original language. Roughly triples the bytes per notice and the run time.

## `includeTranslations` (type: `boolean`):

Keeps every machine translation of the title as a language-keyed object instead of the one output language.

## `proxyConfiguration` (type: `object`):

The TED API is open and does not need a proxy; runs go direct by default. Turn one on only if your account is throttled.

## Actor input object example

```json
{
  "publishedLastDays": 3,
  "maxItems": 50,
  "sortOrder": "newest",
  "onlyActive": false,
  "onlyLatestVersions": false,
  "language": "eng",
  "includeBuyerDetails": false,
  "includeLotDetails": false,
  "includeAwardDetails": false,
  "includeConditions": false,
  "includeDocuments": false,
  "includeReviewBodies": false,
  "includeRelatedOrganisations": false,
  "includeNoticeHistory": false,
  "includeLegacyFields": false,
  "includeFullText": false,
  "includeTranslations": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Every notice collected by this run, with the optional blocks that were switched on.

## `noticesTable` (type: `string`):

The headline columns only: notice, title, published, stage, buyer, country, CPV, value and deadline.

## `csv` (type: `string`):

The same notices as CSV, ready for a spreadsheet or a CRM import.

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

The expert query TED was actually asked, the scope and language, how many notices matched against how many were written, the API request count, and why the run stopped.

# 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 = {
    "publishedLastDays": 3,
    "maxItems": 50,
    "sortOrder": "newest",
    "language": "eng"
};

// Run the Actor and wait for it to finish
const run = await client.actor("parseforge/ted-europa-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 = {
    "publishedLastDays": 3,
    "maxItems": 50,
    "sortOrder": "newest",
    "language": "eng",
}

# Run the Actor and wait for it to finish
run = client.actor("parseforge/ted-europa-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 '{
  "publishedLastDays": 3,
  "maxItems": 50,
  "sortOrder": "newest",
  "language": "eng"
}' |
apify call parseforge/ted-europa-tenders-scraper --silent --output-dataset

```

## MCP server setup

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