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

Scrape EU public procurement tenders from TED (Tenders Electronic Daily). Filter by CPV code, country, notice type, keywords and date — get buyer, title, value, currency, CPV, deadline, country and notice/PDF/XML links as clean JSON/CSV. One row per notice. Official open API, no browser.

- **URL**: https://apify.com/memo23/ted-tenders-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Business
- **Stats:** 13 total users, 12 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## 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/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

## EU Tenders (TED) Scraper — Public Procurement Notices

<p align="center"><img src="https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/ted-tenders-scraper-card.png" alt="EU Tenders (TED) Scraper" width="640"></p>

Pull **EU public-procurement tenders** from **TED (Tenders Electronic Daily)** — the official EU journal of contract notices and awards. Filter by CPV code, country, keyword, notice type and date, and get one clean row per notice: buyer, title, value, currency, CPV, deadline, country and links to the notice, PDF and XML. Runs on TED's official open API — no key, no browser.

### Why use this scraper

- **The official source** — reads TED's own v3 API (`api.ted.europa.eu`), so the data is complete and authoritative across all EU member states.
- **Powerful filtering** — CPV product/service codes, buyer country, full-text keywords, notice type, and publication date range — or paste a raw TED expert query for total control.
- **Drains the full result set** — token-based pagination pages past the web UI's limits; set `maxItems: 0` to pull everything that matches.
- **Clean, English-first output** — multilingual titles/buyers resolved to English where available, one row per notice, JSON or CSV.
- **No key, no browser, no anti-bot** — plain HTTP against an open government API. Fast and cheap.

### Supported inputs

| Filter | Example |
|---|---|
| CPV codes | `72000000` (IT services), `45000000` (construction) |
| Buyer country (ISO-3) | `DEU`, `FRA`, `POL`, `ESP` |
| Keywords (full-text) | `cloud hosting` |
| Notice type | `cn-standard` (call for tenders), `can-standard` (award) |
| Date range | `publishedAfter: 2026-01-01` |
| Expert query | `classification-cpv=72000000 AND buyer-country=DEU` |

### Use cases

- **Bid discovery** — find live tenders in your sector/country to bid on.
- **Competitive intelligence** — track contract *awards* (who won, how much) in a market.
- **Lead generation** — build a list of public-sector buyers by category and geography.
- **Market sizing** — aggregate tender values by CPV, country or time.

### How it works

<p align="center"><img src="https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-ted.png" alt="How the EU Tenders (TED) Scraper works" width="900"></p>

1. Your filters are composed into a TED expert query (or your raw query is used as-is).
2. The actor calls TED's official `/v3/notices/search` API and pages through results with token pagination.
3. Each notice is mapped to a flat, English-first row and pushed to the dataset.

### Input configuration

| Field | Description |
|---|---|
| `cpvCodes` | CPV category codes to match (OR'd together). |
| `countries` | Buyer countries, ISO-3166 alpha-3 (OR'd). |
| `keywords` | Full-text search across notice content. |
| `noticeTypes` | TED notice types (e.g. `cn-standard`, `can-standard`). |
| `publishedAfter` / `publishedBefore` | Publication date bounds (YYYY-MM-DD). |
| `expertQuery` | Raw TED expert query — overrides all the filters above. |
| `maxItems` | Max notices per run (0 = unlimited). |
| `flatten` | Flatten nested fields for CSV/Excel. Default on. |

### Output — key fields

| Field | Description |
|---|---|
| `publicationNumber` | TED notice id (e.g. `161-2026`). |
| `title` | Notice title (English where available). |
| `noticeType`, `formType`, `contractNature` | Notice classification (tender vs award; supplies/services/works). |
| `buyerName`, `buyerCountry` | Contracting authority and its country. |
| `publicationDate`, `deadlineDate` | Published date and tender-submission deadline. |
| `totalValue`, `currency` | Contract value and currency. |
| `cpvCodes` | CPV category codes on the notice. |
| `placeOfPerformance` | Where the contract is performed. |
| `noticeUrl`, `pdfUrl`, `xmlUrl`, `htmlUrl` | Links to the full notice in each format. |

#### Output sample

```json
{
  "portal": "ted",
  "type": "tender-notice",
  "publicationNumber": "161-2026",
  "title": "Germany – IT services: consulting, software development, Internet and support",
  "noticeType": "can-standard",
  "buyerName": "Bundesagentur für Arbeit (BA)",
  "buyerCountry": "DEU",
  "publicationDate": "2026-01-02+01:00",
  "totalValue": null,
  "currency": "EUR",
  "cpvCodes": ["72000000"],
  "contractNature": "services",
  "noticeUrl": "https://ted.europa.eu/en/notice/-/detail/161-2026",
  "pdfUrl": "https://ted.europa.eu/en/notice/161-2026/pdf"
}
```

### 🤖 For AI Agents & LLM Apps

**Purpose:** Query the official EU public-procurement register (TED) and return structured tender notices. No key, no browser.

**Minimal input (tested):**

```json
{ "cpvCodes": ["72000000"], "countries": ["DEU"], "publishedAfter": "2026-01-01", "maxItems": 50 }
```

**Output fields (flat):** `publicationNumber`, `title`, `noticeType`, `formType`, `buyerName`, `buyerCountry`, `publicationDate`, `deadlineDate`, `totalValue`, `currency`, `cpvCodes[]`, `contractNature`, `placeOfPerformance[]`, `noticeUrl`, `pdfUrl`, `xmlUrl`, `htmlUrl`.

**Behaviors agents should know:**

- Filters (`cpvCodes`, `countries`, `noticeTypes`, `keywords`, date bounds) are AND-combined; multiple values within one filter are OR'd. `expertQuery` overrides them with raw TED syntax.
- `noticeType` distinguishes calls for tenders (`cn-standard`) from awards (`can-standard`).
- Multilingual titles/buyers are resolved to English when available.
- Billing is per notice row plus one `apify-actor-start` per run. Cap with `maxItems`.

### Support

Found a bug or want an extra TED field surfaced? Open an issue on the actor's Issues tab.

### ⚠️ Disclaimer

This actor reads publicly available data from the European Union's official TED open API. TED data is EU public-sector information; use it in compliance with the EU's reuse terms and applicable law. You are responsible for how you use the data.

### SEO Keywords

TED scraper, EU tenders scraper, Tenders Electronic Daily, public procurement API, EU procurement data, contract notices scraper, contract award scraper, CPV code search, government tenders, bid discovery, tender leads, ted.europa.eu API, EU public sector data, JSON CSV tenders, Apify TED.

# Actor input Schema

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

Free-text search across the tender notice content (title, description, buyer). Example: "cloud hosting". Leave empty to match everything in your other filters.

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

EU Common Procurement Vocabulary codes to filter by (product/service category). Example: 72000000 = IT services, 45000000 = construction. Add several to OR them.

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

Filter by the buyer's country using ISO-3166 alpha-3 codes. Example: DEU (Germany), FRA (France), POL (Poland), ESP (Spain). Add several to OR them.

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

Filter by TED notice type. Common: cn-standard (contract notice / call for tenders), can-standard (contract award notice), pin-only (prior information). Leave empty for all.

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

Only notices published on or after this date. Format YYYYMMDD or YYYY-MM-DD. Example: 2026-01-01.

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

Only notices published on or before this date. Format YYYYMMDD or YYYY-MM-DD. Leave empty for no upper bound.

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

A raw TED expert-search query. If set, it replaces all the friendly filters above. Example: classification-cpv=72000000 AND buyer-country=DEU AND publication-date>=20260101. See TED's expert-search docs for the full field/operator list.

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

Maximum number of tender notices to return per run. Set to 0 for unlimited (drains the whole result set).

## `flatten` (type: `boolean`):

Flatten nested fields (CPV list, place-of-performance) into dotted columns for tabular export. Turn off to keep nested JSON.

## Actor input object example

```json
{
  "cpvCodes": [
    "72000000"
  ],
  "countries": [],
  "noticeTypes": [],
  "publishedAfter": "2026-01-01",
  "maxItems": 500,
  "flatten": true
}
```

# 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": "",
    "cpvCodes": [
        "72000000"
    ],
    "countries": [],
    "noticeTypes": [],
    "publishedAfter": "2026-01-01"
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/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": "",
    "cpvCodes": ["72000000"],
    "countries": [],
    "noticeTypes": [],
    "publishedAfter": "2026-01-01",
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/ted-tenders-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": "",
  "cpvCodes": [
    "72000000"
  ],
  "countries": [],
  "noticeTypes": [],
  "publishedAfter": "2026-01-01"
}' |
apify call memo23/ted-tenders-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=memo23/ted-tenders-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/6c3FisLQ0jVQwHBHp/builds/pbQjocyh7LCxyurNL/openapi.json
