# EU Tenders Scraper (TED): Public Procurement & Contract Awards (`manageable_gully/ted-eu-tenders-scraper`) Actor

Search EU public tenders on TED via the official API: open calls, contract awards and planned tenders by keyword, country, CPV code, deadline and value. Buyer, values, deadlines, links. Tender alerts. $1 per 1,000 notices.

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

## Pricing

from $1.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 Tenders Scraper (TED): Public Procurement Notices, Contract Awards & Tender Alerts

Get **EU public tenders as clean JSON, CSV or Excel** from **TED (Tenders Electronic Daily)**, the official EU journal for public procurement, through the **official TED Search API v3**: **open calls for tender** you can still bid on, **contract award notices** (awarded value, winner country), **prior information notices** (planned tenders) and changes. Filter by **keyword, country, CPV code, contract type, procedure, publication date, deadline and value**, and schedule it as a **daily tender alert**.

No browser, no login, no API key, no proxy. **$1 per 1,000 notices**.

### What you can use it for

- **Find tenders to bid on:** every open IT, consulting, construction, cleaning or medical-supply tender in the countries you serve, with deadline and days left.
- **Daily tender alerts:** schedule it with **Only new notices** and get just the notices published since the last run, straight to Slack, e-mail, Google Sheets or your CRM (Make, Zapier, n8n, webhooks).
- **Market and competitor intelligence:** contract award notices with awarded values and winner countries per CPV sector, buyer and country.
- **Sales pipelines and bid teams:** buyer organisation, city, website, CPV codes, estimated value and the submission/documents link of each tender.
- **Pipeline planning:** prior information notices show tenders before they open.
- **Research, journalism and AI agents:** clean, normalised EU procurement data for dashboards, LLMs and RAG.

### How to use it

1. Add **keywords** (full-text, any EU language, e.g. `software`, `cybersecurity`, `Reinigung`) and/or **CPV codes** (e.g. `72000000` = IT services incl. all sub-codes, or a prefix like `45` = construction).
2. Pick **countries** (`DE`, `FR`, `PL`… or names) and **notice types** (default: contract notices = open tenders).
3. Optional: **Only tenders still open for bids**, publication date window (default: last 7 days), deadline window, min/max value, contract type, procedure type.
4. Click **Start**. Export to CSV/Excel/JSON or connect it to your tools. Schedule it daily with **Only new notices** for alerts.

### Why this TED scraper

- **Official API only:** the Publications Office of the EU's TED Search API, published for reuse. No HTML scraping that breaks when the website changes.
- **Every filter that matters:** keyword (any/all), buyer country or place of performance, CPV codes with sub-codes, notice type, contract type, procedure, published date, deadline, value, plus a raw TED **expert query** for anything else.
- **No 15,000 cap:** results are paged with TED's iteration token, newest first (or oldest first).
- **Clean output:** one flat row per notice: title (original + translated notice title in your language), buyer, country, city, dates, ISO deadline, days to deadline, main CPV and all CPV codes, estimated/total/awarded value with currency, NUTS regions, duration, framework flag, description, and TED page / PDF / XML / submission / documents links.
- **Alerts built in:** **Only new notices** remembers what you already received (per State key), and already-seen notices are free.
- **Privacy by design:** only procurement and organisation data. Contact persons, e-mail addresses, phone numbers and winner names are never requested.
- **Cheap and fair:** $1 per 1,000 notices, $0.0003 per run start, 256 MB memory. Most daily alert runs cost a few cents.

### Input examples

Open IT tenders in Germany, Austria and the Netherlands published in the last 14 days:

```json
{ "cpvCodes": ["72000000"], "countries": ["DE", "AT", "NL"], "noticeTypes": ["competition"], "onlyOpen": true, "publishedFrom": "14 days" }
```

Cybersecurity or cloud tenders anywhere in the EU worth at least 500,000:

```json
{ "keywords": ["cybersecurity", "cloud"], "noticeTypes": ["competition"], "minValue": 500000, "publishedFrom": "30 days" }
```

Contract awards for construction work in Poland this year (values + winner country):

```json
{ "cpvCodes": ["45"], "countries": ["PL"], "noticeTypes": ["result"], "publishedFrom": "2026-01-01", "maxItems": 5000 }
```

Tenders closing in the next 10 days for cleaning services in France:

```json
{ "keywords": ["nettoyage"], "countries": ["FR"], "noticeTypes": ["competition"], "deadlineFrom": "+0 days", "deadlineTo": "+10 days" }
```

Daily tender alert (schedule it every morning):

```json
{ "keywords": ["software development"], "countries": ["IE", "BE", "LU"], "noticeTypes": ["competition"], "publishedFrom": "3 days", "onlyNew": true, "stateKey": "it-benelux-ie" }
```

Advanced: any TED expert query, e.g. a buyer city:

```json
{ "expertQuery": "buyer-city=Wien", "noticeTypes": ["competition"], "publishedFrom": "30 days" }
```

### Output

One row per notice. Example (shortened):

```json
{
  "publicationNumber": "737076-2026",
  "title": "Umbau und Sanierung Klosterbräustadl Geisenfeld - LV 22 Medientechnik",
  "noticeTitle": "Germany – Electrical wiring and fitting work – Umbau und Sanierung Klosterbräustadl Geisenfeld - LV 22 Medientechnik",
  "formType": "competition",
  "formTypeLabel": "Contract notice (open tender)",
  "publicationDate": "2026-10-23",
  "deadline": "2026-11-23T10:00:00+01:00",
  "daysToDeadline": 30,
  "buyerName": "Stadt Geisenfeld",
  "buyerCountry": "DEU",
  "buyerCity": "Geisenfeld",
  "buyerWebsite": "https://www.geisenfeld.de/",
  "contractNature": "works",
  "procedureType": "open",
  "mainCpv": "45311000",
  "cpvCodes": ["45311000", "48952000", "45311100", "31527260", "32340000", "32232000"],
  "estimatedValue": null,
  "awardedValue": null,
  "winnerCountries": [],
  "placeOfPerformanceNuts": ["DE21J"],
  "documentsUrl": "https://www.staatsanzeiger-eservices.de/aJs/EFormsBekVuUrl?z_param=331243",
  "noticeUrl": "https://ted.europa.eu/en/notice/-/detail/737076-2026",
  "pdfUrl": "https://ted.europa.eu/en/notice/737076-2026/pdf"
}
```

Award notices also fill `awardedValue`, `awardedValueCurrency` and `winnerCountries`. The run summary (OUTPUT record) shows the TED query used, how many notices matched and how many were saved or skipped as already seen.

### Pricing

Pay per event, no subscription:

| Event | Price |
|---|---|
| Tender notice saved | $0.001 ($1 per 1,000) |
| Actor start | $0.0003 |

| Example | Cost |
|---|---|
| 100 notices | about $0.10 |
| 1,000 notices | about $1.00 |
| Daily alert, ~30 new notices a day for 30 days | about $0.91 |

Set **Max cost per run** in the run options and the Actor stops cleanly at that budget.

### FAQ

**Where does the data come from?** From TED, the online version of the Supplement to the Official Journal of the EU, through its public Search API (`api.ted.europa.eu`), which the Publications Office of the EU provides for data reuse without authentication. TED data can be reused, including commercially, under the Commission's reuse policy; check ted.europa.eu for the exact terms.

**Which countries are covered?** All EU member states plus EEA and other countries that publish on TED (Norway, Iceland, Switzerland, Ukraine, …). Use ISO codes like `DE`/`DEU` or English names.

**Which languages?** Keywords are matched in the full notice text, so use words in the notice's language (e.g. German for German tenders) or several keywords. `noticeTitle` is available in all 24 EU languages (choose **Preferred text language**); the original title and description stay in the notice's own language.

**What is a CPV code?** The EU's Common Procurement Vocabulary. `72000000` covers all IT services and its sub-codes, `45000000` construction work, `79000000` business services. You can also give a 2-7 digit prefix.

**Do you return contact persons or e-mails?** No. To avoid personal data, the Actor never requests contact persons, e-mails, phone numbers or winner names. Use the TED notice link for the official contact details of a specific tender.

**Can I get older notices?** Yes, set `publishedFrom` and `publishedTo`. The TED Search API currently returns notices from the past several years (checked: 2017 onwards).

**Is this an official EU product?** No. It is an independent tool that uses the official public API and links back to TED for every notice.

# Actor input Schema

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

Words or phrases searched in the full notice text (any EU language, e.g. 'cloud', 'cybersecurity', 'Reinigung'). One per line. Empty = no keyword filter.

## `keywordMatch` (type: `string`):

Match notices containing any of the keywords, or all of them.

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

Buyer countries as ISO codes (DE, FR, PL or DEU, FRA) or English names. Covers EU/EEA plus other countries publishing on TED. Empty = all countries.

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

Filter by the buyer's country (default) or by where the contract is performed.

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

Common Procurement Vocabulary codes. 8 digits (72000000 = IT services, includes all sub-codes) or a 2-7 digit prefix (e.g. 45 = construction work). Empty = all sectors.

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

Which kinds of TED notices to return. Default: contract notices you can still bid on.

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

Keep only notices whose tender submission deadline is today or later.

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

Publication date on/after: 2026-10-01, 20261001, or relative like '7 days', '2 weeks', '3 months'. Default: last 7 days.

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

Publication date on/before (same formats). Empty = up to today.

## `deadlineFrom` (type: `string`):

Tender deadline on/after: a date or '+3 days' (from now).

## `deadlineTo` (type: `string`):

Tender deadline on/before: a date or '+30 days' (from now).

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

Only notices whose total/estimated value (in the notice currency) is at least this amount. Notices without a value are excluded when set.

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

Only notices whose total value is at most this amount.

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

Empty = all.

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

Empty = all.

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

Optional extra condition in TED expert-search syntax, ANDed with the filters above, e.g. buyer-city=Wien or classification-cpv IN (79341000 79342000). Do not add SORT BY.

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

Language for the notice title/buyer name when TED has it (notice titles exist in all 24 EU languages; original titles fall back to the notice's own language).

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

Add the procurement description text.

## `maxDescriptionChars` (type: `integer`):

Longer descriptions are cut.

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

Order by publication number.

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

Stop after this many notices (also limits cost).

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

Remember delivered notices (named key-value store) and return only ones not seen in earlier runs with the same State key. Schedule daily for a tender alert feed. Already-seen notices are free.

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

Use different keys for different saved searches.

## Actor input object example

```json
{
  "keywords": [
    "software development"
  ],
  "keywordMatch": "any",
  "countries": [
    "DE",
    "FR"
  ],
  "countryField": "buyer",
  "noticeTypes": [
    "competition"
  ],
  "onlyOpen": false,
  "publishedFrom": "7 days",
  "language": "ENG",
  "includeDescription": true,
  "maxDescriptionChars": 3000,
  "sort": "newest",
  "maxItems": 100,
  "onlyNew": false,
  "stateKey": "default"
}
```

# Actor output Schema

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

One row per TED notice: title, buyer, country, notice type, dates, deadline, CPV codes, estimated/awarded value, winner country, TED/PDF/submission links.

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

The TED query used, matching notices on TED, notices saved and already-seen notices skipped.

# 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 development"
    ],
    "countries": [
        "DE",
        "FR"
    ],
    "publishedFrom": "7 days",
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("manageable_gully/ted-eu-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 development"],
    "countries": [
        "DE",
        "FR",
    ],
    "publishedFrom": "7 days",
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("manageable_gully/ted-eu-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 development"
  ],
  "countries": [
    "DE",
    "FR"
  ],
  "publishedFrom": "7 days",
  "maxItems": 100
}' |
apify call manageable_gully/ted-eu-tenders-scraper --silent --output-dataset

```

## MCP server setup

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