# TED EU Tenders Scraper - Public Procurement & Awards (`tinyrex/ted-tenders-scraper`) Actor

Search EU public tenders and contract awards on TED (Tenders Electronic Daily) via the official API: keywords, CPV, countries, dates, deadlines, values, winners. Only-new mode. Pay per notice.

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

## Pricing

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

## TED EU Tenders Scraper – Public Procurement Notices & Contract Awards

Search **EU public tenders and contract awards** from **TED (Tenders Electronic Daily)**, the official EU procurement journal, and get clean, structured data: title, buyer, country, CPV codes, estimated and awarded values, deadlines, winners and direct links to the notice, PDF and tender documents. Filter by keywords, CPV codes, countries, dates, notice type, procedure and value. Schedule it daily with **Only new notices** to get a tender alert feed.

**Why this one:** it uses the **official TED Search API**, so there is no fragile HTML scraping and no blocking. Pay only for notices saved to your dataset, at a lower price per 1,000 than popular TED actors on the Store. Runs that find nothing cost you only the tiny start fee, and notices skipped as *already seen* are **free**.

### Why this scraper

- **Official source.** Data comes straight from the TED Search API (ted.europa.eu), covering all EU and EEA tenders above the EU thresholds.
- **Rich, flat fields.** Buyer name, city, country, type and website; main CPV with label; place of performance (countries and NUTS); estimated value; awarded value, winners and award date for result notices; lots; deadline and an `isOpen` flag.
- **Filters that matter.** Keywords (full text or title), excluded words, CPV codes with sub-codes, buyer or performance country, publication date range, open tenders only, notice category (competition / result / planning), contract type, procedure type, buyer names and value range. Power users can pass a raw **TED expert query**.
- **Tender alerts built in.** Turn on *Only new notices* and schedule the Actor. Each run returns only notices you have not received before.
- **English first.** Titles and descriptions come in your preferred language when TED has them, with the original language kept.

### Use cases

- **Bid and sales teams.** Daily feed of new tenders in your CPV codes and countries, e.g. IT services (72000000) in Germany and Austria.
- **Market and competitor intelligence.** Who wins which contracts, for how much, in which countries.
- **Lead generation.** Public buyers actively purchasing in your category, with their websites.
- **Consultants and tender portals.** Feed your own alerting product or CRM from the official source.

### How to use

1. Enter keywords and/or CPV codes, pick countries and a date range (default: last 7 days).
2. Set **Max notices** (default 100, `0` = all matches).
3. Run it, or schedule it daily with **Only new notices** on.

#### Example input

```json
{
  "cpvCodes": ["72000000", "48000000"],
  "countries": ["DE", "AT"],
  "publishedWithinDays": 7,
  "noticeCategories": ["competition"],
  "onlyOpen": true,
  "maxResults": 200
}
```

#### Example output (shortened)

```json
{
  "publicationNumber": "681061-2026",
  "title": "LC - MSMS",
  "noticeTitle": "Germany – Laboratory, optical and precision equipments (excl. glasses) – LC - MSMS",
  "publicationDate": "2026-10-02",
  "deadline": "2026-11-04T08:00:00+01:00",
  "isOpen": true,
  "noticeCategory": "competition",
  "procedureType": "open",
  "contractType": "supplies",
  "buyerName": "LAVES",
  "buyerCountry": "DE",
  "buyerCity": "Oldenburg",
  "mainCpv": "38000000",
  "mainCpvLabel": "Laboratory, optical and precision equipments (excl. glasses)",
  "estimatedValue": 302000,
  "estimatedValueCurrency": "EUR",
  "winners": [],
  "noticeUrl": "https://ted.europa.eu/en/notice/-/detail/681061-2026",
  "documentsUrl": "https://vergabe.niedersachsen.de/Satellite/notice/CXQ6YYERS9M/documents"
}
```

Run totals, the exact TED query used and any warnings are saved to the `SUMMARY` record in the run's key-value store.

### Pricing

Pay per event:

- **Notice** (`notice`): one charge per notice saved to your dataset.
- **Free:** notices skipped as already seen in *Only new notices* mode, and duplicates within a run.

See the *Pricing* tab for the current price. Set a maximum cost per run and the Actor stops gracefully when it is reached.

### Limitations

- TED publishes notices above the EU procurement thresholds. Smaller national tenders that are not sent to TED are not included.
- Values, winners and descriptions are only as complete as the buyer's notice. Many competition notices have no estimated value.
- Very broad searches (all of TED for months) can return hundreds of thousands of notices. Use **Max notices** or a maximum cost per run to stay in budget.

### Use with AI agents (MCP)

This Actor works as a tool for AI agents through the **Apify MCP server** at `https://mcp.apify.com`. Connect Claude, Cursor, VS Code, n8n or any other MCP client to `https://mcp.apify.com?tools=tinyrex/ted-tenders-scraper` and the agent can run it from a plain-language request, for example: *"Find open IT services tenders in Austria published this week"*. Results come back as clean, structured JSON at the same pay-per-result price.

📘 **Step-by-step guide with Python, JavaScript, curl and MCP examples:** [How to export EU public tenders from TED (Tenders Electronic Daily) to CSV or JSON](https://emirmrkaljevic.github.io/tinyrex-data-tools/ted-tenders-api-export/)

### Related actors

- [EU Grants Scraper](https://apify.com/tinyrex/eu-grants-scraper): Open and upcoming EU funding calls (Horizon Europe, Digital Europe, LIFE, Erasmus+, cascade funding) with deadlines and budgets, the grants side of EU public money.
- [Tech Stack Detector](https://apify.com/tinyrex/tech-stack-detector): Check the technologies behind buyer or winner websites (CMS, analytics, hosting, email provider).
- [ATS Jobs Scraper](https://apify.com/tinyrex/ats-jobs-scraper): See who winning companies are hiring: jobs from Greenhouse, Lever, Ashby, Personio and more.
- [Workday Jobs Scraper](https://apify.com/tinyrex/workday-jobs-scraper): Jobs from enterprise Workday career sites.
- [Shopify Products Scraper](https://apify.com/tinyrex/shopify-products-scraper) and [WooCommerce Products Scraper](https://apify.com/tinyrex/woocommerce-products-scraper): Export products and prices from online stores.

### FAQ

**Is this legal?** TED is the EU's official open-data procurement journal, and its Search API is public and free to use. This Actor only reads public notices.

**How fresh is the data?** TED publishes new notices every working day (Monday to Friday). A daily schedule with *Only new notices* catches everything.

**Can I get older notices?** Yes. Use *Published from* / *Published to* for any historical range.

# Actor input Schema

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

Words to find in the notice (any language, TED stems and transliterates them). Each line is one search: all its words must appear; use "quotes" for an exact phrase and \* as a wildcard (softw\*). Several lines = any of them. Leave empty to get all notices matching the other filters.

## `searchIn` (type: `string`):

Full text searches every field of the notice, including CPV labels in all languages. Title only searches the buyer's own procedure and lot titles (eForms notices, published since late 2023).

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

Common Procurement Vocabulary codes, e.g. 72000000 (IT services), 45000000 (construction), 33000000 (medical equipment). The check digit (72000000-5) is accepted. By default sub-codes are included: 72000000 also finds 72212100.

## `includeCpvSubcodes` (type: `boolean`):

On: 72000000 matches every code in division 72. Off: exact code only.

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

Buyer countries as 2- or 3-letter codes or English names: DE, FRA, Poland. EL/UK aliases work. Empty = all countries.

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

Filter on the contracting authority's country or on where the contract is performed.

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

Notices published in the last N days (TED publishes Monday to Friday). Ignored when a date range is set. 0 = no date limit.

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

Start of the publication date range (YYYY-MM-DD). TED has notices since 2016 via the API.

## `publishedTo` (type: `string`):

End of the publication date range (YYYY-MM-DD), inclusive.

## `onlyOpen` (type: `boolean`):

Keep only notices whose deadline for tenders or requests to participate is today or later.

## `noticeCategories` (type: `array`):

Empty = all. Pick Competition for open business opportunities, Result for awards and winners.

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

Optional, more detailed than categories. Empty = all.

## `contractTypes` (type: `array`):

Empty = all.

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

Empty = all.

## `buyerNames` (type: `array`):

Contracting authorities, e.g. Deutsche Bahn or Stadt Wien. All words of a line must appear in the buyer name. Several lines = any of them.

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

Minimum estimated or total value as published by TED, in the notice's own currency (no conversion). Notices without a value are excluded when set. 0 = no limit.

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

Maximum estimated or total value (notice currency). 0 = no limit.

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

Drop notices that contain any of these words anywhere in the text.

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

Optional native TED expert query, combined with the filters above using AND, e.g. NL >= 10 or place-of-performance IN (FRK) or winner-name ~ (Siemens). Syntax: https://ted.europa.eu/en/help/search-browse#expert-search. Results are newest first; keep the default sort for complete paging.

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

Maximum number of notices saved (one charge per notice). 0 = all matching notices. Newest notices come first.

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

Language for the notice title (TED translates it into all EU languages), links and buyer names where available. The buyer's own title is kept in the original language when no translation exists.

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

Add the short description of the procurement (usually in the original language).

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

Hide notices that were later replaced by a change notice (corrigendum).

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

Return only notices you have not received in earlier runs with the same state key. Perfect for daily schedules and alerts. The first run returns everything that matches and remembers it.

## `stateKey` (type: `string`):

Name of the memory used by 'Only new notices'. Use a different key for each schedule or search.

## Actor input object example

```json
{
  "keywords": [
    "software"
  ],
  "searchIn": "fullText",
  "cpvCodes": [
    "72000000"
  ],
  "includeCpvSubcodes": true,
  "countries": [
    "DE",
    "AT"
  ],
  "countryField": "buyer",
  "publishedWithinDays": 7,
  "onlyOpen": false,
  "noticeCategories": [],
  "noticeTypes": [],
  "contractTypes": [],
  "procedureTypes": [],
  "buyerNames": [],
  "minValue": 0,
  "maxValue": 0,
  "excludeKeywords": [],
  "expertQuery": "",
  "maxResults": 100,
  "language": "en",
  "includeDescription": true,
  "onlyLatestVersions": false,
  "onlyNew": false,
  "stateKey": "default"
}
```

# Actor output Schema

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

Tenders and award notices with title, buyer, country, CPV, values, deadline, winners and links.

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

TED expert query used, total matching notices, notices saved, already-seen notices skipped, errors.

# 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"
    ],
    "countries": [
        "DE",
        "AT"
    ]
};

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

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

```

## MCP server setup

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