# TED EU Procurement Scraper - Tenders & Award Notices (`jungle_synthesizer/ted-eu-procurement-full-scraper`) Actor

Scrape EU public procurement from TED: buyer, CPV codes, estimated and awarded value, winner, subcontractors, NUTS region, SME flag. Filter by country, CPV, value band, date.

- **URL**: https://apify.com/jungle\_synthesizer/ted-eu-procurement-full-scraper.md
- **Developed by:** [BowTiedRaccoon](https://apify.com/jungle_synthesizer) (community)
- **Categories:** Business, Lead generation
- **Stats:** 4 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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?

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

## TED EU Procurement Scraper - Public Tenders, Contracts & Award Notices

Scrape EU public procurement and government tenders from [TED (Tenders Electronic Daily)](https://ted.europa.eu/), the official OJEU public contracts portal. This TED API scraper returns tender opportunities, award notices, prior-information notices, and corrigenda with buyer, CPV codes, estimated and awarded value, winner, subcontractors, NUTS region, and SME flag — roughly 1M+ notices published per year across 27 EU member states plus EEA, filterable by country, CPV, and date.

No API key. No proxy. No browser. Pure JSON over the TED Public Expert Search API v3.

***

### TED EU Procurement Scraper Features

- Extracts 30+ fields per notice — buyer, CPV, estimated value, awarded value, winner, SME flag, NUTS region, deadlines, subcontractors, document URLs
- Filters by country, CPV code, NUTS region, publication-date range, minimum estimated value, and SME-winner-only
- Covers four notice kinds in one actor — tender opportunities, award notices, prior information, and modifications
- Normalises multi-language free-text fields to a preferred language (default English) with graceful fallback
- Streams through the full TED Expert Search API with 1-based pagination and total-count termination
- Runs in 512MB memory with no proxy requirement
- Two-view output: one view for bidders (open tenders), one for competitor intelligence (award notices)

***

### What Can You Do With This EU Public Contracts Database by Country?

- **B2G sales teams** — Track new tender opportunities in your CPV codes and countries, and feed them into a CRM
- **Competitive intelligence** — Pull award notices with winner name and awarded value to map who is winning which contracts
- **Lobbying and policy research** — Aggregate public spending patterns across ministries, agencies, and NUTS regions
- **SME market entry** — Filter to SME-winner-only results and see which small firms are landing government contracts
- **Due diligence** — Cross-reference vendors and subcontractors against their EU public-sector revenue

***

### How TED EU Procurement Scraper Works

1. Pick your filters — notice types, countries, CPV codes, NUTS regions, date range, minimum value, SME-only
2. The scraper composes a TED Expert Search query and paginates the API 100 records per page
3. Each notice is flattened into a row-per-notice record with consistent field names across all four notice kinds
4. Results stream into the Apify dataset — you can export to JSON, CSV, or Excel, or feed directly into another actor

***

### Input

```json
{
  "noticeTypes": ["award"],
  "countries": ["DEU", "FRA"],
  "cpvCodes": ["71220000"],
  "publishedAfter": "2024-01-01",
  "publishedBefore": "2024-12-31",
  "minEstimatedValueEur": 100000,
  "onlySmeWinners": false,
  "preferredLanguage": "eng",
  "maxItems": 500
}
```

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `noticeTypes` | array | `[]` (all) | Notice kinds: `prior_info`, `contract`, `award`, `modification` |
| `countries` | array | `[]` (all) | Buyer countries as ISO 3-letter codes (e.g. `POL`, `DEU`, `FRA`) |
| `cpvCodes` | array | `[]` | EU Common Procurement Vocabulary codes, 8 digits |
| `nutsCodes` | array | `[]` | EU NUTS region codes (e.g. `PL418`, `DE268`) |
| `minEstimatedValueEur` | integer | `0` | Lower bound on `estimated-value-glo`, in the notice's currency unit |
| `publishedAfter` | string | 30 days ago | Earliest publication date (`YYYY-MM-DD`) |
| `publishedBefore` | string | today | Latest publication date (`YYYY-MM-DD`) |
| `onlySmeWinners` | boolean | `false` | On award notices, keep only winners flagged as SMEs |
| `preferredLanguage` | string | `eng` | Preferred language for titles, buyer names, descriptions |
| `maxItems` | integer | `100` | Maximum notices to return across the whole run |
| `proxyConfiguration` | object | `{}` | Optional — TED is a public API and does not need proxies |

#### Example: German contracts over €100K from the last year

```json
{
  "noticeTypes": ["contract"],
  "countries": ["DEU"],
  "minEstimatedValueEur": 100000,
  "publishedAfter": "2024-01-01",
  "maxItems": 1000
}
```

#### Example: Award notices to SME winners in architectural services

```json
{
  "noticeTypes": ["award"],
  "cpvCodes": ["71220000", "71200000"],
  "onlySmeWinners": true,
  "preferredLanguage": "eng",
  "maxItems": 500
}
```

***

### TED EU Procurement Scraper Output Fields

Every record is flat, CSV-friendly, and uses the same schema across all four notice kinds. Empty fields are returned as `""` or `null`, not omitted.

```json
{
  "noticeId": "192938-2026",
  "noticeType": "contract",
  "noticeSubtype": "cn-standard",
  "publicationDate": "2026-03-20",
  "deadlineDate": "2026-04-24",
  "awardDate": "",
  "country": "DEU",
  "nutsCode": "DE268",
  "title": "Germany – Telephone and data transmission services – Auswahlverfahren Großlangheim - Gigabit-RL 2.0",
  "titleLanguage": "eng",
  "description": "Der Netzbetreiber, dem nach Abschluss dieses Auswahlverfahrens der Zuschlag erteilt wird, erhält eine Dienstleistungskonzession zum Aufbau und Betrieb eines gigabitfähigen Netzes für das Erschließungsgebiet...",
  "buyerName": "Markt Großlangheim",
  "buyerCity": "Großlangheim",
  "buyerCountryCode": "DEU",
  "buyerLegalType": "la",
  "procedureType": "",
  "cpvMain": "64210000",
  "cpvCodes": ["64210000", "32412000", "32561000", "32562000", "32562100", "32562300", "64215000"],
  "estimatedValueEur": null,
  "estimatedValueCurrency": "",
  "awardedValueEur": 550000,
  "awardedValueCurrency": "EUR",
  "placeOfPerformance": "DE268, DEU",
  "frameworkAgreement": false,
  "winnerName": "",
  "winnerCountry": "",
  "winnerIsSme": false,
  "subcontractors": "",
  "documentUrls": [
    "https://ted.europa.eu/en/notice/-/detail/192938-2026",
    "https://ted.europa.eu/en/notice/192938-2026/xml",
    "https://ted.europa.eu/en/notice/192938-2026/pdf"
  ],
  "url": "https://ted.europa.eu/en/notice/-/detail/192938-2026"
}
```

| Field | Type | Description |
|-------|------|-------------|
| `noticeId` | string | Publication number, e.g. `192938-2026` |
| `noticeType` | string | Category: `prior_info`, `contract`, `award`, or `modification` |
| `noticeSubtype` | string | Raw TED notice-type code (e.g. `cn-standard`, `can-standard`, `pin-only`, `corr`) |
| `publicationDate` | string | ISO 8601 publication date |
| `deadlineDate` | string | Submission deadline (ISO 8601), when present |
| `awardDate` | string | Winner-decision date on award notices (ISO 8601), when present |
| `country` | string | Buyer country ISO 3-letter code |
| `nutsCode` | string | Primary NUTS region code for place of performance |
| `title` | string | Notice title in the preferred language |
| `titleLanguage` | string | Actual language returned for the title |
| `description` | string | Notice description in the preferred language, truncated at 2000 characters |
| `buyerName` | string | Buyer organisation name |
| `buyerCity` | string | Buyer city |
| `buyerCountryCode` | string | Buyer country ISO code |
| `buyerLegalType` | string | Buyer legal-type code (`la` = local authority, `cga` = central government, `8` = regional, etc.) |
| `procedureType` | string | Procedure-type code (`open`, `restricted`, `neg-wo-call`, `comp-dial`, etc.) |
| `cpvMain` | string | Primary CPV code |
| `cpvCodes` | array | All CPV codes on the notice |
| `estimatedValueEur` | number | Estimated total contract value (see currency field for unit) |
| `estimatedValueCurrency` | string | Currency code for estimated value |
| `awardedValueEur` | number | Final awarded value on result notices |
| `awardedValueCurrency` | string | Currency code for awarded value |
| `placeOfPerformance` | string | NUTS codes joined comma-separated |
| `frameworkAgreement` | boolean | Whether this notice is part of a framework agreement |
| `winnerName` | string | Awarded winner organisation name |
| `winnerCountry` | string | Winner country ISO code |
| `winnerIsSme` | boolean | Whether the winner is flagged as an SME |
| `subcontractors` | string | Subcontractor names, comma-separated |
| `documentUrls` | array | Deep-link URLs — HTML detail, XML, PDF |
| `url` | string | Canonical TED detail page URL |

***

### FAQ

#### How do I scrape TED EU procurement data?

TED EU Procurement Scraper uses the public TED Expert Search API v3 — no API key, no account, no proxy. Pick your filters, set `maxItems`, and run. The actor paginates the API 100 records per page until it hits your cap or exhausts the query.

#### How much does TED EU Procurement Scraper cost to run?

Pricing is pay-per-event: a small fee per actor start plus a fraction of a cent per record saved. A full year of German contracts (≈50K records) runs roughly a few dollars. Pulling 100 records costs basically nothing.

#### Can I filter by CPV code or NUTS region?

Yes. Pass `cpvCodes` as an array of 8-digit codes and `nutsCodes` as an array of NUTS identifiers. The filters are applied server-side as OR groups, so `cpvCodes: ["71220000", "71200000"]` returns any notice matching either code.

#### Does this return award notices with the winner?

Yes — that's the point of the actor. Set `noticeTypes: ["award"]` and the output includes `winnerName`, `winnerCountry`, `winnerIsSme`, `awardedValueEur`, `awardedValueCurrency`, and `subcontractors` on every record where TED has that data. Coverage varies by publishing authority; large EU central buyers are most consistent.

#### What languages are the titles and descriptions in?

TED publishes notices in the buyer's language and also provides a translation in each of the 24 EU languages for machine-readable fields. Set `preferredLanguage` to your desired code (`eng`, `fra`, `deu`, `ita`, `spa`, `pol`, `nld`, `por`, `ces`, `swe`). The scraper returns the requested language if available and falls back to English or any other available language. The chosen language is reported in `titleLanguage`.

#### How do I get EU government tenders by country?

Pass the `countries` filter as an array of ISO 3-letter codes — for example `["DEU", "FRA", "POL"]` — to pull public contracts for specific EU member states. Leave it empty to cover all 27 EU countries plus EEA. Combine it with `cpvCodes`, `nutsCodes`, and a publication-date range to narrow to the exact tenders or award notices you want.

#### Does TED EU Procurement Scraper need a proxy?

No. TED is a public EU portal with a rate-friendly API. The actor makes one request every 200ms and handles pagination cleanly up to the API's total-count limit.

***

### Need More Features?

Need row-per-lot output, XML schema parsing, or a different set of fields? [File an issue](https://console.apify.com/actors/issues) or get in touch.

### Why Use TED EU Procurement Scraper?

- **Full coverage** — All four TED notice kinds in one schema: tenders, awards, prior info, modifications
- **Award-notice parsing** — Winner name, awarded value, SME flag, and subcontractor list on every award record — the fields most actors stop before reaching
- **Clean flat output** — One row per notice with consistent field names, ready for CSV, BI tools, or a CRM, instead of the nested XML most TED consumers end up writing their own parser for

***

**Further reading:** [How to Get Government Tender Data From 14 Procurement Portals](https://orbtop.com/articles/government-tender-data-portals/)

# Actor input Schema

## `sp_intended_usage` (type: `string`):

Please describe how you plan to use the data extracted by this crawler.

## `sp_improvement_suggestions` (type: `string`):

Provide any feedback or suggestions for improvements.

## `sp_contact` (type: `string`):

Provide your email address so we can get in touch with you.

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

Which notice kinds to fetch. Leave empty to include all types. prior\_info = planning/PIN. contract = tender opportunities. award = award/result notices. modification = corrigenda.

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

Buyer countries to include. Use ISO 3-letter codes. Leave empty for all EU+EEA. Examples: POL, DEU, FRA, ITA, ESP, NLD.

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

EU Common Procurement Vocabulary codes (8-digit). Leave empty for all. Example: 71220000 (architectural design services).

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

EU NUTS region codes to filter by place of performance. Leave empty for all. Example: PL418.

## `minEstimatedValueEur` (type: `integer`):

Only return notices with estimated value >= this amount. Leave as 0 for no filter.

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

Only return notices published on or after this date. Leave empty to default to 30 days ago.

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

Only return notices published on or before this date. Leave empty for today.

## `onlySmeWinners` (type: `boolean`):

If true, only return award notices whose winner is flagged as an SME. Has no effect on tender-opportunity (non-award) notices.

## `preferredLanguage` (type: `string`):

Language for free-text fields (title, buyer name, description). Falls back to any available language if the preferred one is missing.

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

Maximum number of notices to return. Narrow filters for large datasets.

## Actor input object example

```json
{
  "sp_intended_usage": "Describe your intended use...",
  "sp_improvement_suggestions": "Share your suggestions here...",
  "sp_contact": "Share your email here...",
  "noticeTypes": [],
  "countries": [],
  "cpvCodes": [],
  "nutsCodes": [],
  "minEstimatedValueEur": 0,
  "onlySmeWinners": false,
  "preferredLanguage": "eng",
  "maxItems": 100
}
```

# 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 = {
    "sp_intended_usage": "Describe your intended use...",
    "sp_improvement_suggestions": "Share your suggestions here...",
    "sp_contact": "Share your email here...",
    "noticeTypes": [],
    "countries": [],
    "cpvCodes": [],
    "nutsCodes": [],
    "minEstimatedValueEur": 0,
    "publishedAfter": "",
    "publishedBefore": "",
    "onlySmeWinners": false,
    "preferredLanguage": "eng",
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("jungle_synthesizer/ted-eu-procurement-full-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 = {
    "sp_intended_usage": "Describe your intended use...",
    "sp_improvement_suggestions": "Share your suggestions here...",
    "sp_contact": "Share your email here...",
    "noticeTypes": [],
    "countries": [],
    "cpvCodes": [],
    "nutsCodes": [],
    "minEstimatedValueEur": 0,
    "publishedAfter": "",
    "publishedBefore": "",
    "onlySmeWinners": False,
    "preferredLanguage": "eng",
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("jungle_synthesizer/ted-eu-procurement-full-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 '{
  "sp_intended_usage": "Describe your intended use...",
  "sp_improvement_suggestions": "Share your suggestions here...",
  "sp_contact": "Share your email here...",
  "noticeTypes": [],
  "countries": [],
  "cpvCodes": [],
  "nutsCodes": [],
  "minEstimatedValueEur": 0,
  "publishedAfter": "",
  "publishedBefore": "",
  "onlySmeWinners": false,
  "preferredLanguage": "eng",
  "maxItems": 100
}' |
apify call jungle_synthesizer/ted-eu-procurement-full-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jungle_synthesizer/ted-eu-procurement-full-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/8M3h4Gc1l0n11blVg/builds/IE2L1xb02V9QAxDVz/openapi.json
