# EU Public Tenders Scraper (TED) (`dataservice_comp/eu-public-tenders-scraper`) Actor

Filter and extract public procurement notices from the EU's official TED tender portal - contract notices, awards, values, deadlines and buyer details.

- **URL**: https://apify.com/dataservice\_comp/eu-public-tenders-scraper.md
- **Developed by:** [Ayşenur Özdemir](https://apify.com/dataservice_comp) (community)
- **Categories:** Lead generation, Other
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.01 / actor start

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/platform/actors/running/actors-in-store#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

**Search, filter, and monitor public procurement notices published on [TED (Tenders Electronic Daily)](https://ted.europa.eu)**, the EU's official portal for public tenders above the EU threshold. This Actor queries TED's own Search API directly, so results are always up to date, and returns clean, structured JSON - notice title, buyer, CPV category, estimated value converted to EUR, submission deadline, lots, documents, and (for award notices) the winning bidder.

Run it once for a one-off export, or combine it with an [Apify Schedule](https://docs.apify.com/platform/schedules) in **Monitor mode** to get a recurring feed of only the tenders published since your last run - useful for sales prospecting, market research, and bid-tracking pipelines across all 27 EU member states plus the EEA, UK, and EU candidate countries.

### Why use EU Public Tenders Scraper (TED)?

- **New business leads** - find open contract notices in your industry (by CPV code or keyword) before your competitors do.
- **Competitive intelligence** - contract award notices show who won a tender and for how much, across any EU country.
- **Market sizing** - aggregate public spending by country, buyer type, or category using the normalised EUR value on every row.
- **Compliance & monitoring** - watch a specific country, buyer, or CPV category continuously with monitor mode, and feed new notices into your CRM or Slack via Apify [integrations](https://apify.com/integrations).

### How to use EU Public Tenders Scraper (TED)

1. Click **Try for free** (or **Start**) to open the Actor.
2. On the **Input** tab, set at least one filter - a country, a CPV code, or keywords. Dates default to the last 7 days if you leave them blank.
3. Click **Start** and wait for the run to finish.
4. Open the **Output** tab to preview results, or export the dataset as JSON, CSV, or Excel.
5. Optional: attach an [Apify Schedule](https://docs.apify.com/platform/schedules) and turn on **Monitor mode** to receive only newly published notices on every scheduled run.

No coding is required, but every input field is also available through the [Apify API](https://docs.apify.com/api/v2) and client libraries if you want to automate runs.

### Input

The full list of options is on the **Input** tab in the Apify Console, grouped into sections:

- **Geography** - include/exclude countries, NUTS region codes.
- **Subject matter** - CPV classification codes and free-text keywords.
- **Dates** - a rolling "last N days" window, or absolute publication/deadline dates.
- **Contract value** - minimum/maximum estimated value in EUR (converted from the notice's original currency).
- **Notice type** - contract notices (open opportunities), contract awards (results), prior information, modifications, design contests; plus procedure type and buyer type.
- **Output** - max rows, preferred language, whether to include lot details, document links, contact details, or raw XML.
- **Monitoring** - enable to skip notices already returned by a previous run with the same state key.

All fields are optional except that at least a date range (or its 7-day default) always applies, so a run with no filters at all returns the most recent notices EU-wide.

### Output

Each dataset item is one procurement notice. Example:

```json
{
  "noticeId": "449208-2026",
  "noticeType": "cn-standard",
  "isAwardNotice": false,
  "publicationDate": "2026-07-15",
  "deadline": "2026-08-31T10:00:00Z",
  "isOpen": true,
  "title": "Framework agreement x86 servers and Dell storage with accompanying maintenance",
  "buyerName": "Statens vegvesen",
  "buyerCountry": "NOR",
  "buyerCountryName": "Norway",
  "cpvMain": "30230000",
  "cpvDivisionLabel": "Office and computing machinery, equipment and supplies",
  "estimatedValue": 580000000,
  "estimatedValueCurrency": "NOK",
  "estimatedValueEurApprox": 49880000,
  "noticeUrl": "https://ted.europa.eu/en/notice/-/detail/449208-2026",
  "winnerName": null
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel from the Output tab or via the API.

### Data table

| Field | Description |
| --- | --- |
| `noticeId` / `noticeType` | TED publication number and notice type code |
| `title` / `shortDescription` | Notice title and a trimmed description, in your preferred language |
| `buyerName` / `buyerCountry` / `buyerCity` | Contracting authority and location |
| `cpvMain` / `cpvDivisionLabel` | Procurement classification (CPV code and human-readable category) |
| `estimatedValue` / `estimatedValueEurApprox` | Contract value in its original currency and approximate EUR |
| `deadline` / `isOpen` | Submission deadline and whether it has already passed |
| `lots` | Per-lot title, description, value and deadline (when "Include lot details" is on) |
| `documentUrls` | Direct links to tender documents (when "Include document links" is on) |
| `winnerName` / `winnerCountry` | Winning bidder, for contract award notices |
| `noticeUrl` / `xmlUrl` | Link to the notice on ted.europa.eu and its source XML |

### How much does it cost to scrape TED tenders?

This Actor only calls TED's public Search API - no browser, no proxies - so runs are fast and cheap. A typical run fetching 1,000 notices completes in well under a minute of compute time. Set **Maximum results** to cap the size (and cost) of any single run; the default is 1,000. Check the [Apify pricing page](https://apify.com/pricing) for your plan's included usage.

### Tips and advanced options

- Prefer **CPV codes** over keywords when possible - notices are published in the buyer's own language, so a keyword filter alone will miss non-English results, while CPV codes work regardless of language.
- Use **prefix CPV matching** (e.g. `72`) to cover an entire category instead of listing every sub-code.
- For a recurring "what's new" feed, turn on **Monitor mode** and schedule the Actor daily or weekly; each run remembers what it already returned under your account, so only new notices come through.
- Turn off **Include lot details** / **Include document links** if you don't need them - it trims the output size on large runs.

### FAQ, disclaimers, and support

TED data is published by the Publications Office of the EU and is public information; this Actor only reads it through TED's official Search API and does not bypass any access controls. Contract values are approximate: they're converted to EUR using a static reference rate, not a live feed, so treat `estimatedValueEurApprox` as indicative rather than exact for financial reporting. Some older or non-standard notices omit fields such as value or CPV code - these come through as `null` rather than being dropped.

Found a bug or want a feature? Open an issue on the Actor's **Issues** tab in Apify Console. Need a tailored version - additional fields, a different output shape, integration with your CRM? Reach out via the same tab or through [Apify's custom solutions](https://apify.com/custom-solutions).

# Actor input Schema

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

ISO 3166-1 alpha-2 country codes of the contracting authority, e.g. DE, FR, NL.

## `excludeCountries` (type: `array`):

Country codes to exclude from results.

## `nutsCodes` (type: `array`):

Optional regional targeting, finer than country level. Example: DE212 for Munich. End a code with \* to match a whole region group, e.g. DE21\* for the Oberbayern group.

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

CPV classification codes. With prefix matching, '72' covers all IT services.

## `cpvMatchMode` (type: `string`):

Prefix matches any code starting with the value. Exact requires a full match.

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

Words to search in title and description. Note that notices are written in the buyer's own language, so keyword filters alone will miss results.

## `keywordMatchMode` (type: `string`):

Whether a notice must match any one of the keywords or all of them.

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

Drop notices containing any of these words.

## `relativeDays` (type: `integer`):

Shortcut for recent notices. Overrides the absolute publication dates below when set.

## `publishedSince` (type: `string`):

ISO 8601 date, e.g. 2026-07-01. Ignored when 'Last N days' is set.

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

ISO 8601 date. Defaults to today.

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

Only notices whose submission deadline falls after this date.

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

Only notices whose submission deadline falls before this date.

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

Exclude notices whose submission deadline has already passed.

## `minValueEur` (type: `integer`):

Minimum estimated contract value.

## `maxValueEur` (type: `integer`):

Maximum estimated contract value.

## `includeUnknownValue` (type: `boolean`):

Many authorities do not publish a budget. Turning this off alongside a minimum value removes a large share of otherwise relevant notices.

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

Contract notices are open opportunities. Contract awards show who won.

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

Restrict results to specific procurement procedure types. Leave empty for all.

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

Restrict results to works, supplies or services contracts. Leave empty for all.

## `buyerType` (type: `array`):

Type of contracting authority, using TED's raw legal-type codes, e.g. la (local authority), cga (central government), ra (regional authority), body-pl (body governed by public law). Passed directly to TED, so an unknown code returns zero results rather than an error - leave empty for all buyer types.

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

Hard cap on rows returned. Protects you from an unexpectedly large and expensive run.

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

Preferred language for text fields, as a 2-letter (en, de, fr) or 3-letter (eng, deu, fra) code. Falls back to English, then to whatever language the notice was actually published in, when no translation exists.

## `includeLots` (type: `boolean`):

Attach a 'lots' array to each notice with the per-lot title, description, estimated value and deadline.

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

Attach a 'documentUrls' array with direct links to the tender documents of each lot.

## `includeContactPerson` (type: `boolean`):

Notices may contain the name, email and phone of a contact at the authority. If enabled, you are responsible for handling this data in line with GDPR.

## `includeRawXml` (type: `boolean`):

Attach the source XML to each row. Increases output size significantly. For debugging only.

## `monitorMode` (type: `boolean`):

Return only notices published since the previous run with the same state key.

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

Use different keys to maintain separate watchlists.

## `deduplicate` (type: `boolean`):

Skip notice IDs already returned in earlier runs.

## Actor input object example

```json
{
  "countries": [
    "DE",
    "FR",
    "NL"
  ],
  "excludeCountries": [],
  "nutsCodes": [],
  "cpvCodes": [
    "72"
  ],
  "cpvMatchMode": "prefix",
  "keywords": [],
  "keywordMatchMode": "any",
  "excludeKeywords": [],
  "relativeDays": 7,
  "onlyOpen": false,
  "includeUnknownValue": true,
  "noticeTypes": [
    "contract-notice"
  ],
  "procedureTypes": [],
  "contractNature": [],
  "buyerType": [],
  "maxResults": 1000,
  "language": "en",
  "includeLots": true,
  "includeDocuments": true,
  "includeContactPerson": false,
  "includeRawXml": false,
  "monitorMode": false,
  "stateKey": "default",
  "deduplicate": true
}
```

# Actor output Schema

## `results` (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 = {
    "countries": [
        "DE",
        "FR",
        "NL"
    ],
    "cpvCodes": [
        "72"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("dataservice_comp/eu-public-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 = {
    "countries": [
        "DE",
        "FR",
        "NL",
    ],
    "cpvCodes": ["72"],
}

# Run the Actor and wait for it to finish
run = client.actor("dataservice_comp/eu-public-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 '{
  "countries": [
    "DE",
    "FR",
    "NL"
  ],
  "cpvCodes": [
    "72"
  ]
}' |
apify call dataservice_comp/eu-public-tenders-scraper --silent --output-dataset

```

## MCP server setup

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