# EU Tenders Scraper – TED Public Procurement Notices (`glidepath/ted-tenders-scraper`) Actor

Find open EU public tenders on TED, the official EU procurement journal. Input: keywords, countries, CPV codes, dates. Output: title, buyer, CPV, estimated value, deadline, notice + PDF links. $3.40/1k notices.

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

## Pricing

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

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

**Find open EU public tenders in seconds.** This Actor searches TED (Tenders Electronic Daily), the official journal where every public buyer in the EU, the EEA and partner countries publishes tenders above the EU thresholds. Filter by keywords, buyer country, CPV code and publication date, and get one clean row per tender: title in English, buyer, CPV codes, estimated value, bid deadline and links to the notice page, PDF and XML.

It reads TED's official open-data search API, so there is no browser, no scraping of web pages and no login: a run of 100 tenders takes a few seconds.

### Who uses it

- **Companies that sell to governments:** a daily list of new tenders in your sector (CPV) and countries, before your competitors see them.
- **Bid consultants and tender alert services:** feed many clients' keyword profiles from one source.
- **Market researchers and analysts:** what public buyers purchase, where, and for how much (estimated values, procedure types).
- **Sales teams:** find public organisations planning purchases with prior information notices, months before the tender.

### How to use it

1. Enter **Keywords** (any EU language; a notice matches if it contains at least one), and optionally **Buyer countries** (DE, FR, PL …) and **CPV codes** (72000000 = all IT services).
2. Keep **Only tenders still open for bids** on for live opportunities, or turn it off and set **Published on or after / before** to search past notices. Choose **Notice types** to include prior information notices.
3. Run it and download the tenders as JSON, CSV or Excel, or send them to Google Sheets, Slack or your CRM through the Integrations tab.

### Input example

```json
{
  "keywords": ["software", "cloud services"],
  "countries": ["DE", "AT", "NL"],
  "cpvCodes": ["72000000", "48000000"],
  "noticeTypes": "tenders",
  "onlyOpen": true,
  "publishedFrom": "2026-10-01",
  "maxItems": 500
}
```

CPV codes match everything below them: `72000000` covers all IT services, `4873` all security software, `45233141` exactly road maintenance works. Country codes can be 2 letters (`DE`) or 3 letters (`DEU`); Greece is `GR` or `EL`.

### Output example

```json
{
  "noticeId": "693103-2026",
  "title": "Finland – Software package and information systems – Digital service platform",
  "titleOriginal": "Digitaalisen palvelualustan hankinta",
  "originalLanguage": "fin",
  "description": "Hankinnan kohteena on …",
  "noticeType": "cn-standard",
  "noticeKind": "contract notice",
  "procedureType": "open",
  "contractNature": ["services"],
  "buyerName": "Helsingin kaupunki; DigiHelsinki Oy",
  "buyerCountry": "FIN",
  "buyerCity": "Helsinki",
  "performanceCountries": ["FIN"],
  "mainCpv": "48000000",
  "cpvCodes": ["48000000", "72000000"],
  "estimatedValue": 1200000,
  "currency": "EUR",
  "publicationDate": "2026-10-07",
  "deadline": "2026-11-09",
  "noticeUrl": "https://ted.europa.eu/en/notice/-/detail/693103-2026",
  "pdfUrl": "https://ted.europa.eu/en/notice/693103-2026/pdf",
  "xmlUrl": "https://ted.europa.eu/en/notice/693103-2026/xml",
  "source": "TED",
  "extractedAt": "2026-10-08T04:00:00Z"
}
```

| Field | Type | Description |
|---|---|---|
| `noticeId` | string | TED publication number, e.g. `693103-2026` |
| `title` | string / null | English notice title: country – CPV subject – the buyer's own title |
| `titleOriginal` | string / null | The buyer's title in the original language |
| `originalLanguage` | string / null | Language code of the original title and description (`deu`, `fra`, `fin` …) |
| `description` | string / null | Procedure description in the original language (up to 5,000 characters; e-mails and phone numbers removed) |
| `noticeType` | string | TED notice type code, e.g. `cn-standard` |
| `noticeKind` | string | Notice type in words |
| `procedureType` | string / null | `open`, `restricted`, `neg-w-call`, `comp-dial`, `innovation` … |
| `contractNature` | array | `supplies`, `services` and/or `works` |
| `buyerName` | string / null | Contracting authority (organisation); several are joined with `; ` |
| `buyerCountry` | string / null | ISO 3166 alpha-3 country of the buyer |
| `buyerCity` | string / null | City of the buyer |
| `performanceCountries` | array | Countries where the contract is performed |
| `mainCpv` | string / null | Main CPV code of the procedure |
| `cpvCodes` | array | All CPV codes in the notice |
| `estimatedValue` | number / null | Estimated value of the procedure, excluding VAT (when the buyer publishes it) |
| `currency` | string / null | Currency of `estimatedValue` |
| `publicationDate` | string / null | Date published on TED (YYYY-MM-DD) |
| `deadline` | string / null | Earliest bid deadline over all lots (YYYY-MM-DD) |
| `noticeUrl` | string | Notice page on ted.europa.eu |
| `pdfUrl` | string / null | English PDF of the notice |
| `xmlUrl` | string / null | eForms XML of the notice |
| `source` | string | `TED` |
| `extractedAt` | string | ISO 8601 UTC |

The run's key-value store also has a `SUMMARY` record with the exact TED query used and how many notices matched in total.

### Use it with

- **Schedules:** save your search as a Task with **Published on or after** set to a recent date and run it every morning for a daily tender alert.
- **Make, Zapier, n8n, Google Sheets, Slack, e-mail:** through the Integrations tab.
- **API and code:** the Apify API, the JavaScript and Python clients, or CSV/JSON/Excel downloads.
- **AI agents:** the Apify MCP server exposes this Actor as a tool; inputs are plain keywords, country codes and CPV codes.

### Pricing

Pay per notice: **$3.40 per 1,000 notices** on the Apify Free plan; on paid plans **$3.40** (Starter), **$2.90** (Scale) and **$2.40** (Business and higher) (the price for your plan is shown on the Pricing tab). The examples below use the Free-plan price. Only saved notices are charged; searches that fail or match nothing are free.

- A daily alert for one sector in five countries (about 1,000 tenders/month) → about **$3.40/month**.
- A full month of all new EU tenders for a market study (about 20,000 notices) → about **$68.00**.

A small start fee of $0.00005 per run applies. Set a **maximum cost per run** in the run options and the Actor stops cleanly when it is reached; **Max notices** does the same by count.

### Limits and notes

- **TED only (for now):** notices published in the Official Journal of the EU, i.e. tenders above the EU thresholds plus those buyers choose to publish there. National below-threshold portals are not included.
- **Contract award notices (who won) are not included,** because winners can be sole traders (personal data). Tenders and prior information notices only.
- Titles in English come from TED's own translation of the notice heading; descriptions are in the buyer's language.
- `estimatedValue` is empty when the buyer did not publish one (common). `deadline` is the earliest lot deadline; check the notice for lot details and times.
- Up to 50,000 notices per run, newest first. The API is queried politely, about one request per second (250 notices per request).
- Contact persons, e-mail addresses and phone numbers are never requested; any that appear in description text are removed.

### FAQ

**Is it legal to use TED data?** Yes. TED is published by the Publications Office of the European Union as open data, and its reuse, including commercial reuse, is allowed under Commission Decision 2011/833/EU with attribution ("Source: TED, © European Union"). This Actor uses TED's official public search API, without logging in or getting around any protection, and outputs no personal data.

**How do I get only new tenders every day?** Schedule a Task with your filters and **Published on or after** set to a date close to today, or keep **Only tenders still open for bids** on and de-duplicate on `noticeId` in your sheet or database.

**Which CPV code should I use?** Search "CPV code" plus your product on the web, or run the Actor once with a keyword and look at the `cpvCodes` of the tenders you like. Shorter codes cover more.

**Does it include UK tenders?** Not yet. Since 2021 UK tenders are on Find a Tender, not TED; UK support is planned.

**Why did my run return 0 notices?** No notice matches all filters at once. Remove a filter (for example the country or the open-deadline option) or use more general keywords.

### Changelog

See [CHANGELOG.md](CHANGELOG.md).

### Support

Found a problem or need a feature? Open an issue on the Actor's Issues tab. We read every one.

# Changelog

This Actor's version history is a separate document: https://apify.com/glidepath/ted-tenders-scraper/changelog.md

# Actor input Schema

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

Words or phrases searched in the full notice text in any EU language (e.g. 'software', 'road maintenance', 'Reinigung'). A notice matches if it contains at least one of them. Up to 20. Leave empty for all notices.

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

ISO country codes of the contracting authority, e.g. DE, FR, PL, IE (2 or 3 letters). Leave empty for all countries that publish on TED (EU, EEA and partners).

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

Common Procurement Vocabulary codes. A code also matches everything below it: 72000000 = all IT services, 4873 = all security software. Up to 50.

## `noticeTypes` (type: `string`):

Tenders are notices that invite bids. Prior information notices announce purchases a buyer plans to make, often months ahead.

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

Keep only notices whose bid deadline (of at least one lot) is today or later. Turn off to search past tenders too. Ignored for prior information notices, which have no bid deadline.

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

Only notices published on TED on or after this date (YYYY-MM-DD). For a daily feed, set it to yesterday or schedule with a fixed recent date.

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

Only notices published on or before this date (YYYY-MM-DD).

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

Stop after saving this many notices (each saved notice is charged). Newest notices come first.

## Actor input object example

```json
{
  "keywords": [
    "software"
  ],
  "noticeTypes": "tenders",
  "onlyOpen": true,
  "maxItems": 100
}
```

# Actor output Schema

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

No description

## `summary` (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"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("glidepath/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"] }

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

```

## MCP server setup

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