# EU Tenders (TED) Extractor and Monitor (`rankoff/ted-tenders-extractor`) Actor

Find EU public tenders on TED, the official EU procurement journal, through its official API. Filter by keyword, CPV code, country and date, keep only tenders still open, and run daily to get only new notices. No contact names, e-mails or phone numbers collected. $0.002 per notice.

- **URL**: https://apify.com/rankoff/ted-tenders-extractor.md
- **Developed by:** [Rankoff B.V.](https://apify.com/rankoff) (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 $2.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 (TED) Extractor and Monitor

Find European public tenders on TED (Tenders Electronic Daily), the official EU journal for public procurement, and get them as clean, structured data. Search by keyword, CPV code, buyer country and publication date, keep only tenders that are still open for bids, and run it on a schedule to receive only the notices you have not seen before.

This EU tenders extractor uses the official TED Search API v3 (`api.ted.europa.eu`), which is public and needs no API key. It does not scrape web pages, does not log in anywhere and does not use proxies.

This actor is independent. It is not affiliated with, authorised or endorsed by the European Union, the European Commission, the Publications Office of the EU or TED.

### What you can use it for

- **Find bids to respond to:** for example IT services (CPV 72000000) or software (CPV 48000000) tenders in the Netherlands that are still open.
- **Daily or weekly tender alerts:** schedule the actor with monitor mode on, then send new notices to e-mail, Slack, Google Sheets or your CRM using Apify's schedules and integrations.
- **Market research:** see which public bodies buy what, where, and for roughly how much (estimated values, where the buyer published one).
- **Pipeline and competitor tracking:** follow award results and contract modifications in your sector.

### Why this TED actor

There are several TED tender actors on Apify Store. This one is built to be:

- **Privacy-safe by design.** It never requests contact names, e-mail addresses, phone numbers, street addresses or the names of winning tenderers. Notices can contain that information; this actor does not collect it, so you have less personal data to look after.
- **Made for monitoring.** Monitor mode remembers which notices earlier runs delivered and skips them. Skipped notices are free.
- **Easy to filter.** Country codes as `NL` or `NLD`, CPV codes with or without the check digit, an "only open for tenders" switch, newest first, and a days-until-deadline field.
- **Readable.** Titles and buyer names in your preferred language where TED has them, with English as the fallback.
- **Polite to the source.** At least one second between API calls (two by default), with automatic back-off if TED is busy.

### How to use it

1. Choose your filters: keywords, CPV codes and/or countries, and how far back to look.
2. Leave "Notice kinds" on calls for competition to see open opportunities, or add award results and other kinds.
3. Set "Maximum notices" to cap the cost of the run.
4. For alerts, switch on monitor mode, give it a monitor key such as `nl-it-tenders`, and add a daily schedule in Apify.
5. Download the results as JSON, CSV or Excel, or use them through the Apify API.

### Input

| Field | What it does |
|---|---|
| Keywords | Full-text search. A notice matches if it contains any keyword. Notices are in many languages, so add translations for better coverage |
| CPV codes | 8-digit codes, for example `72000000` (IT services) or `48000000` (software packages). Matching includes sub-codes |
| Buyer countries | `NL` or `NLD`, `DE` or `DEU`, and so on |
| Notice kinds | Calls for competition (default), planning, award results, contract modifications, direct award pre-announcements, market consultations |
| Published within the last N days / from / to | Publication date range. Default: last 7 days |
| Only notices still open for tenders | Keeps notices with a submission deadline today or later |
| Monitor mode and monitor key | Only notices not delivered by an earlier run with the same key |
| Preferred language | 3-letter code such as `eng`, `nld`, `deu` or `fra` |
| Newest first | On by default |
| Maximum notices | Cap to control cost |
| Advanced | Extra TED expert-search expression (dates as YYYYMMDD), page size, seconds between requests |

Example input:

```json
{
  "countries": ["NL"],
  "cpvCodes": ["72000000", "48000000"],
  "onlyOpenForTenders": true,
  "publishedWithinDays": 14,
  "maxResults": 50
}
```

### Output

One row per notice. Example (a real notice, shortened):

```json
{
  "publicationNumber": "718679-2026",
  "noticeUrl": "https://ted.europa.eu/en/notice/-/detail/718679-2026",
  "publicationDate": "2026-10-19",
  "formType": "competition",
  "formTypeLabel": "Call for competition (open opportunity)",
  "title": "Netherlands – Document management software package – Europese openbare aanbesteding 'Levering, implementatie, beheer en onderhoud van een Record Management Applicatie (RMA)'",
  "titleLanguage": "eng",
  "buyerNames": ["Raad van State"],
  "buyerCountries": ["NLD"],
  "buyerCities": ["Den Haag"],
  "cpvCodes": ["48311000", "48000000", "72263000", "72267000", "72268000"],
  "contractNature": "supplies",
  "procedureType": "open",
  "estimatedValue": null,
  "tenderDeadlines": ["2026-11-25"],
  "nextTenderDeadline": "2026-11-25",
  "daysUntilNextDeadline": 25,
  "source": "TED API v3 (api.ted.europa.eu)",
  "attribution": "Source: TED (Tenders Electronic Daily), Publications Office of the European Union, https://ted.europa.eu. © European Union. ..."
}
```

Other fields: `pdfUrl`, `xmlUrl`, `noticeType`, `noticeVersion`, `procedureTitle`, `placeOfPerformanceCountries`, `estimatedValueCurrency`, `estimatedValueSource` (procedure, or sum of lots), `officialLanguages`, `retrievedAt`.

Each run also saves a `SUMMARY` record in its key-value store: the query sent to TED, the total number of matches, notices saved, notices skipped and requests made.

### Pricing

Pay per event:

- **USD 0.002 per notice** saved to your dataset (USD 2 per 1,000 notices).
- **Notices skipped in monitor mode are free.**
- **Apify's standard start fee** of USD 0.00005 per run applies.
- There is no separate platform usage charge for normal runs; Apify's platform costs are covered by the event prices.

Examples (arithmetic only):

| Use | Cost |
|---|---|
| One run that saves 100 notices | about USD 0.20 |
| A daily monitor for 30 days that saves 10 new notices a day | about USD 0.60, plus 30 start fees of USD 0.00005 each |

Set "Maximum notices" or a maximum cost per run in Apify to stay in control. The actor stops cleanly when your limit is reached.

### Limitations, honestly

- **Data quality is the buyer's.** Many notices have no estimated value, and some calls for competition have no machine-readable deadline. Fields are empty when TED has no value.
- **Titles may be machine-assembled.** TED's English titles often combine country, CPV description and the original-language title.
- **Keyword search is literal.** It does not translate, so add keywords in the languages you care about.
- **TED is the authentic source.** Only notices published in the Supplement to the Official Journal of the EU are legally authentic. Always check the notice on TED before you bid.
- **Coverage is TED only.** National below-threshold tenders, for example many on TenderNed, are not on TED.
- **Speed.** The actor waits at least one second between requests, and each request returns up to 250 notices. Very large exports therefore take a little time.

### FAQ

**Can I use TED data commercially?**
Yes. The TED legal notice says that, unless otherwise noted, procurement notices published in the Supplement to the Official Journal of the EU can be freely reused for commercial or non-commercial purposes. This follows Commission Decision 2011/833/EU on the reuse of Commission documents. Keep the source credit below and do not distort the meaning of the notices.

**Is this a web scraper? Do I need proxies or a TED account?**
No to all three. It calls the official TED Search API, which is public and needs no key.

**Why are there no contact names, e-mails or phone numbers?**
On purpose. Notices can include personal contact details, and many uses do not need them. Open the `noticeUrl` to see the full notice on TED when you are ready to bid.

**How do daily alerts work?**
Turn on monitor mode, set a monitor key, and schedule the actor in Apify (for example every morning). Each run returns only notices that earlier runs with the same key did not deliver, and you can connect an integration to send them where you work. The memory is kept in a key-value store in your Apify account named `rankoff-ted-tenders-monitor`, and holds up to 20,000 notice numbers per key.

**Why do I get a different number of results from the TED website?**
TED's website and this actor may use different default filters, for example on notice kinds, dates or active notices only. The `SUMMARY` record shows the exact query this actor sent, and you can paste it into TED's expert search to compare.

**What does "Only notices still open for tenders" do?**
It keeps notices with at least one tender submission deadline today or later. Notices without a machine-readable deadline are left out when this is on.

**Which CPV codes should I use?**
Use the broad code for a family to include all its sub-codes, for example `72000000` for IT services or `48000000` for software. The official CPV list is published by the EU.

**What happens if TED is busy or rejects my query?**
The actor retries with increasing waits when TED is busy. If TED rejects a query, for example because of a mistake in an advanced expression, the run stops and shows TED's own error message. No notices are charged; only the small start fee applies.

**Who made this actor?**
Rankoff B.V., a small company in the Netherlands (https://rankoff.io). It was built with AI assistance and tested against the live TED API before publishing.

### Data source, licence and credit

Notices come from TED, published by the Publications Office of the European Union. Reuse is allowed under Commission Decision 2011/833/EU, whose Article 6(2) lets the conditions require reusers to acknowledge the source, not to distort the original meaning or message, and accept that the Commission is not liable for any consequence of the reuse.

Every row carries this credit. If you republish the data, please keep it:

> Source: TED (Tenders Electronic Daily), Publications Office of the European Union, https://ted.europa.eu. © European Union. Reused under the Commission reuse policy (Decision 2011/833/EU). Fields were selected and reformatted by this actor; only notices published in the Supplement to the Official Journal of the EU are authentic.

Further notes:

- The European Union, the European Commission and the Publications Office are not responsible for this actor or for any use of its output.
- This actor uses no TED, SIMAP or EU logos or emblems.

### Personal data

The actor requests a fixed list of organisation-level fields and refuses to start if that list ever includes contact, person, e-mail, phone, address, winner or tenderer fields. Buyer names are normally public bodies or companies. If you combine this data with other sources, you are responsible for your own data protection compliance.

### Support

Questions or problems: use the Issues tab on this actor's page.

# Actor input Schema

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

Full-text search terms. A notice matches if it contains any of them. Notices are multilingual, so add translations for better coverage (for example software, logiciel, Software).

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

8-digit Common Procurement Vocabulary codes, for example 72000000 (IT services) or 48000000 (software packages). A check digit suffix such as -5 is accepted and ignored.

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

Country of the buying organisation. ISO alpha-3 (NLD, DEU) or alpha-2 (NL, DE).

## `formTypes` (type: `array`):

Which kinds of notices to include. Default: calls for competition only (open opportunities).

## `publishedWithinDays` (type: `integer`):

Used when Published from is empty. Set to 0 for no lower date limit.

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

Earliest publication date. Overrides Published within the last N days.

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

Latest publication date (inclusive).

## `onlyOpenForTenders` (type: `boolean`):

Keep only notices with a tender submission deadline today or later.

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

Remembers which notices earlier runs with the same monitor key returned and skips them (skipped notices are not charged). Useful with a daily schedule.

## `monitorKey` (type: `string`):

Name for the monitor memory. Leave empty to derive it from the search filters.

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

3-letter code (eng, nld, deu, fra, ...). Falls back to English, then to the original language.

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

Stop after this many notices are saved.

## `newestFirst` (type: `boolean`):

Return the most recently published notices first. Turn off to get oldest first.

## `customQuery` (type: `string`):

Optional TED expert-search expression, combined with the filters above using AND. See https://ted.europa.eu/en/search/expert-search

## `pageSize` (type: `integer`):

Notices requested per API call (TED maximum is 250).

## `requestIntervalSecs` (type: `number`):

Minimum pause between calls to the TED API. Minimum 1.

## Actor input object example

```json
{
  "keywords": [
    "ERP"
  ],
  "countries": [
    "NLD"
  ],
  "formTypes": [
    "competition"
  ],
  "publishedWithinDays": 7,
  "onlyOpenForTenders": false,
  "onlyNew": false,
  "language": "eng",
  "maxResults": 100,
  "newestFirst": true,
  "pageSize": 100,
  "requestIntervalSecs": 2
}
```

# Actor output Schema

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

One item per TED notice found in this run.

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

Counts and query details for this run.

# 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": [
        "ERP"
    ],
    "countries": [
        "NLD"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("rankoff/ted-tenders-extractor").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": ["ERP"],
    "countries": ["NLD"],
}

# Run the Actor and wait for it to finish
run = client.actor("rankoff/ted-tenders-extractor").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": [
    "ERP"
  ],
  "countries": [
    "NLD"
  ]
}' |
apify call rankoff/ted-tenders-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rankoff/ted-tenders-extractor"
        }
    }
}
```

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/p5WmRyoRHkfDaENLJ/builds/l5esj703kItWc6hvN/openapi.json
