# EU Public Tenders (TED) Scraper (`davidts/eu-tenders-ted-scraper`) Actor

EU public procurement notices from TED (Tenders Electronic Daily) as clean dataset items: title, buyer, country, CPV codes, values, deadline, procedure type and document links. Filter by country, CPV, keywords, notice type, dates and value, or pass a raw TED expert query. Official open API, no key.

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

## Pricing

from $4.00 / 1,000 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 Public Tenders (TED) Scraper

**EU Public Tenders (TED) Scraper** finds **EU public tenders** and **public procurement notices**
on **TED** (Tenders Electronic Daily, ted.europa.eu, the Supplement to the Official Journal of the
EU) and exports them to JSON, CSV or Excel: title, buyer, country, **CPV codes**, estimated and
awarded values, submission deadline, procedure type and links to the notice and the tender
documents. Filter by **country**, **CPV code**, **keywords**, **notice type** (calls for tenders,
contract awards, prior information), **publication date**, **deadline** and **minimum value**, or
paste your own TED expert query - and schedule it as your own tender alert.

The Actor uses the **official, open TED Search API** published by the Publications Office of the
EU. No scraping of HTML pages, no login, no API key, and the data is official EU open data that
may be reused commercially (see *Data source and licence* below).

### What can you do with it

- **Get a daily tender alert for your sector**: every new call for tenders in your countries and
  CPV codes, in a spreadsheet, Slack channel or CRM each morning after TED's daily publication.
- **Build a bid pipeline**: open tenders with at least two weeks left, above a minimum value,
  sorted by earliest deadline, with links to the tender documents.
- **Research competitors and winners**: contract award notices with awarded values, buyers,
  procedure types and CPV sectors, to see who wins public contracts in your market and for how
  much.
- **Analyse public spending**: bulk exports of notices by country, sector and period for
  research, journalism or market sizing.
- **Feed tender data to software and AI**: clean JSON for an internal tool, a bid/no-bid
  assistant or an LLM, without learning TED's expert query language, pagination and
  multilingual format.

#### Who it is for

- **SMEs and sales teams** tracking tenders in their country and sector (for example every IT
  services tender in Cyprus and Greece published this week) without paying for a tender-alert
  subscription.
- **Bid consultants and tender writers** who need a daily feed of calls for tenders with
  deadlines, values and document links, ready for a CRM, a spreadsheet or an AI assistant.
- **Researchers, journalists and analysts** studying public spending: award notices with winners'
  contract values, buyer types, procedure types and CPV sectors across the EU.
- **Developers** who want TED data in JSON/CSV without implementing the expert query language,
  the iteration-token pagination and the multilingual response format themselves.

Compared with paid tender-alert services (typically EUR 50-300 per month for one country and a
handful of sectors), you pay only for the notices you actually download (from **$0.004 per
notice**, see *Pricing*), you get the raw structured data instead of e-mails, you choose the
filters freely, and you can schedule the Actor to run every morning after TED's daily publication.

### How to use

1. Open [EU Public Tenders (TED) Scraper](https://apify.com/davidts/eu-tenders-ted-scraper) and
   click **Try for free** (or **Start**).
2. Pick your **buyer countries** and **CPV codes** (a 2-digit prefix such as `72` covers a whole
   sector), and optionally keywords, notice types, a deadline or a minimum value.
3. Click **Start**, download the notices as CSV, Excel or JSON from the **Output** tab, and add a
   daily **schedule** to turn it into a tender alert.

#### Sample output (selected columns)

| title | buyer.name | buyer.country | cpvMain | estimatedValue | submissionDeadline | noticeType |
| --- | --- | --- | --- | --- | --- | --- |
| Cyprus - Software maintenance and support services for the hospital information system | Ministry of Health | CYP | 72267000 | 250000 EUR | 2026-11-20 | cn-standard |

(Illustrative row; the full record with links is shown under *Output* below.)

### Input

All filters are optional and combined with AND. TED refuses a query that matches everything, so
when no filter at all is set the Actor returns the newest notices of the last 7 days (the log says
so); set at least one filter to search for what you need.

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `countries` | array | all | Buyer countries as ISO 3166-1 alpha-3 codes, the format TED uses: `CYP`, `GRC`, `DEU`, `FRA`, `ITA`, `ESP`, `POL`, `NLD`, `GBR`, `NOR`, `CHE`, ... Two-letter EU/EEA codes (`CY`, `GR`, `DE`, ...) are converted. |
| `cpvCodes` | array | all | CPV codes (what is being bought). Full 8-digit codes (`72260000`) or prefixes for a whole division (`72` = IT services, `45` = construction, `33` = medical, `79` = business services). |
| `keywords` | string | - | Words that must all appear in the notice text (any language, stemmed). Quote phrases: `"web design" wordpress`. |
| `noticeTypes` | array | all | TED notice type codes, e.g. `cn-standard` (contract notice = call for tenders), `can-standard` (contract award notice), `pin-only` (prior information notice). Full list below. |
| `publishedAfter` / `publishedBefore` | string | - | Publication date window. Absolute (`2026-01-31`, `20260131`) or relative to now (`30 days`, `2 weeks`, `6 months`). |
| `deadlineAfter` | string | - | Only notices whose tender-receipt deadline is on/after this date. Absolute, or relative counted *forward* (`7 days` = at least a week left). |
| `minValue` | number | - | Minimum estimated value (or awarded value for award notices) in EUR. Notices stating another currency or no value are excluded when set. |
| `onlyOpenForSubmission` | boolean | `false` | Only competition notices whose submission deadline has not passed (as of the run start). |
| `maxNotices` | integer | `500` | How many notices to save. `0` = all matching notices (mind the cost: broad queries match hundreds of thousands). |
| `sortBy` | select | `publication-date-desc` | `publication-date-desc` (newest first), `publication-date-asc`, `deadline-asc` (earliest deadline first). |
| `fields` | select | `basic` | `basic` = the fields documented below. `full` adds `description`, identifiers, OJ S number, dispatch date, submission URL and `raw` (every field as returned by TED). |
| `includeDocumentLinks` | boolean | `true` | Add `documentsUrl` (where the buyer publishes the tender documents) when the notice states it. |
| `query` | string (Advanced) | - | Your own TED expert query. Replaces all filters above; the sort order is still appended unless the query has its own `SORT BY`. |
| `scope` | select (Advanced) | `ALL` | `ALL` = last 10 years, `ACTIVE` = TED's active notices (unexpired competitions, recent planning and result notices), `LATEST` = today's OJ S issue only. |
| `preferredLanguage` | string (Advanced) | `eng` | Language for multilingual values (`title`, `buyer.name`, `description`, links): `eng`, `deu`, `fra`, `ell`, `ita`, `spa`, `pol`, `nld`, ... English, then the notice's own language, are the fallbacks. |

#### Example 1: IT tenders in Cyprus and Greece from the last 30 days (the default prefill)

```json
{
    "countries": ["CYP", "GRC"],
    "cpvCodes": ["72"],
    "publishedAfter": "30 days",
    "maxNotices": 100
}
```

Builds the expert query
`(buyer-country IN (CYP GRC)) AND (classification-cpv = 72*) AND (publication-date >= 20260929) SORT BY publication-date DESC`.

#### Example 2: open calls for tenders for construction work above EUR 1 million, earliest deadline first

```json
{
    "countries": ["DE", "AT", "NL"],
    "cpvCodes": ["45"],
    "noticeTypes": ["cn-standard"],
    "onlyOpenForSubmission": true,
    "deadlineAfter": "14 days",
    "minValue": 1000000,
    "sortBy": "deadline-asc",
    "maxNotices": 200
}
```

#### Example 3: who won software contracts in Q3 2026 (award notices), with the raw TED record

```json
{
    "keywords": "ERP \"software licence\"",
    "noticeTypes": ["can-standard", "can-social"],
    "publishedAfter": "2026-07-01",
    "publishedBefore": "2026-09-30",
    "fields": "full",
    "maxNotices": 0
}
```

Or skip the filters and pass an expert query built on
[TED's expert search page](https://ted.europa.eu/en/search/expert-search):

```json
{
    "query": "(buyer-country IN (MLT)) AND (FT ~ (cloud)) AND (publication-date >= 20260101)",
    "scope": "ACTIVE",
    "maxNotices": 50
}
```

### Output

One dataset item per notice (the `basic` preset; `full` adds the keys listed afterwards):

```json
{
    "publicationNumber": "650123-2026",
    "noticeType": "cn-standard",
    "formType": "competition",
    "title": "Cyprus - Software maintenance and support services for the hospital information system",
    "titleLanguage": "eng",
    "buyer": {
        "name": "Ministry of Health",
        "country": "CYP",
        "city": "Nicosia",
        "website": "https://www.moh.gov.cy/",
        "type": "cga"
    },
    "cpvCodes": ["72267000", "72000000", "72260000"],
    "cpvMain": "72267000",
    "placeOfPerformance": ["CY000"],
    "estimatedValue": { "amount": 250000, "currency": "EUR" },
    "awardedValue": null,
    "publicationDate": "2026-10-20",
    "submissionDeadline": "2026-11-20T12:00:00+01:00",
    "procedureType": "open",
    "contractNature": "services",
    "lots": 1,
    "links": {
        "html": "https://ted.europa.eu/en/notice/650123-2026/html",
        "pdf": "https://ted.europa.eu/en/notice/650123-2026/pdf",
        "xml": "https://ted.europa.eu/en/notice/650123-2026/xml",
        "ted": "https://ted.europa.eu/en/notice/-/detail/650123-2026"
    },
    "documentsUrl": "https://www.eprocurement.gov.cy/epps/cft/viewContractNotices.do?resourceId=12345",
    "language": "ell",
    "scrapedAt": "2026-10-29T12:00:00.000Z"
}
```

| Field | Meaning |
| --- | --- |
| `publicationNumber` | TED's unique notice number (`number-year`), the key of every TED URL. |
| `noticeType`, `formType` | What kind of notice it is (codes below) and the procurement stage: `planning`, `competition`, `result`, `cont-modif`, `completion`, `dir-awa-pre`, `consultation`, `bri`. |
| `title`, `titleLanguage` | Title in the preferred language when available (English by default), otherwise in the notice's own language; `titleLanguage` says which. |
| `buyer` | Contracting authority: `name` (several buyers joined with `; `), `country` (alpha-3), `city`, `website`, `type` (legal type code: `cga` central government, `ra` regional, `la` local authority, `body-pl` body governed by public law, `pub-undert` public undertaking, `eu-ins-bod-ag` EU institution, ...). |
| `cpvCodes`, `cpvMain` | All CPV codes of the notice and the main one. |
| `placeOfPerformance` | NUTS and/or country codes where the contract is performed, as TED returns them. |
| `estimatedValue` | Estimated value of the procedure (or the lot estimates added up) as `{ amount, currency }`, or `null`. |
| `awardedValue` | Value of the contracts awarded in this notice (award/modification notices), or `null`. |
| `publicationDate` | Date published on TED (`YYYY-MM-DD`). |
| `submissionDeadline` | Earliest tender-receipt deadline across the lots, ISO 8601 with TED's UTC offset, or `null` (award and planning notices have none). |
| `procedureType` | `open`, `restricted`, `neg-w-call`, `neg-wo-call`, `comp-dial`, `innovation`, `oth-single`, `oth-mult`, ... |
| `contractNature` | `services`, `supplies` or `works`. |
| `lots` | Number of lots, derived from the lot-level values TED returned (best effort; `null` when none). |
| `links` | The notice as HTML, PDF and XML (authentic data) on ted.europa.eu plus the TED detail page. |
| `documentsUrl` | Where the procurement documents are published, when stated (and `includeDocumentLinks` is on). |
| `language` | Official language of the notice (lower-case 3-letter code). |
| `scrapedAt` | When the item was collected. |

With `fields: "full"` every item also has `description` (procedure or first lot description),
`noticeIdentifier` and `procedureIdentifier` (eForms UUIDs; the procedure identifier links the
contract notice, its award notice and modifications), `noticeVersion`, `noticeSubtype`,
`ojsNumber` (OJ S issue, e.g. `205/2026`), `dispatchDate`, `submissionUrl` and `raw`, the record
exactly as the TED API returned it (requested fields only).

The **Overview** tab of a run shows title, buyer, country, deadline, estimated value and the TED
link; the full items are available as JSON, CSV, Excel or through the API like any Apify dataset.

#### Notice type codes

| Code | Meaning |
| --- | --- |
| `pin-only`, `pin-buyer`, `pin-rtl`, `pin-cfc-standard`, `pin-cfc-social`, `pin-tran` | Prior information notices: a buyer announces what it plans to buy (some can be used as a call for competition). |
| `cn-standard`, `cn-social`, `cn-desg` | **Contract notices**: calls for tenders you can bid on (standard regime, light regime for social and other specific services, design contests). |
| `qu-sy`, `subco`, `veat`, `pmc` | Qualification system, subcontracting, voluntary ex-ante transparency and pre-market consultation notices. |
| `can-standard`, `can-social`, `can-desg`, `can-tran` | **Contract award notices**: the result of a procedure, with the awarded value. |
| `can-modif`, `compl` | Contract modification and contract completion notices. |
| `brin-ecs`, `brin-eeig` | Business registration information notices (not procurement). |

### Pricing

This Actor uses Apify's **pay-per-event** model, so you only pay for what you get:

- **$0.004 per saved notice** (one dataset item), and
- **$0.005 per run start**.

1,000 notices therefore cost **$5.005**, whichever filters and presets you choose; `fields: "full"`
costs the same per notice. The exact prices are shown on the Pricing tab of this page. Platform
usage (compute) is covered by these prices and is **not** billed separately. Set a maximum cost per
run in the run options if you want a hard cap; everything saved until then stays in the dataset.

### How it works

1. The structured filters are turned into a TED expert search query (shown in the log), or your
   raw `query` is used as is.
2. The query is validated with TED's syntax check (`checkQuerySyntax`), so a typo produces a clear
   error message instead of an empty dataset. If only the check endpoint objects, the search is
   still attempted; the run fails only when TED rejects the search itself.
3. Notices are fetched from `POST https://api.ted.europa.eu/v3/notices/search` in *iteration*
   mode (TED's scroll pagination, which has no limit on the number of results) in pages of up to
   250 notices, until `maxNotices`, the end of the results or an error. Only organisation-level
   fields are requested; contact persons, e-mail addresses and phone numbers are never requested.
4. Every notice is normalised into the item above: multilingual values are resolved to your
   preferred language, numeric strings become numbers, lot-level deadlines are combined into the
   earliest one, and links are completed from TED's documented URL patterns when missing.

Politeness: at most 2 requests in flight, 200-500 ms between requests, exponential backoff on
HTTP 429 / 5xx (up to 5 retries) - far below TED's fair-usage limit of 700 requests per minute.
A run with 500 notices usually takes well under a minute. The log ends with a summary: pages
fetched, notices received and saved, duplicates skipped and the total number of matching notices.

### Limitations

- **Update cadence**: TED publishes one OJ S issue per working day (Monday to Friday, around
  06:00 CET; nothing on weekends and EU holidays). A notice sent by a buyer appears on TED a few
  days later. Running the Actor more often than once a day does not surface more notices.
- **Language coverage**: TED stores titles, buyer names and descriptions in the languages the
  buyer provided. Many notices carry an English title, but a lot of them (and most descriptions
  and buyer names) are available only in the notice's own language; `titleLanguage`/`language`
  tell you what you got, and `preferredLanguage` lets you pick another language first.
- **Values**: `estimatedValue` and `awardedValue` are what the buyer declared. Many notices
  (especially prior information and light-regime notices) state no value; `minValue` only matches
  values declared in EUR.
- **Lots**: TED's search index is notice-based, so lot-level data comes back as lists without lot
  identifiers; `submissionDeadline` is the earliest lot deadline and `lots` is a best-effort count.
- **Below-threshold tenders** (national procurement below the EU thresholds) are mostly not on TED
  and therefore not in this Actor.
- **Pre-2024 notices** (the old TED schema) have fewer fields than eForms notices; some values may
  be `null` for them.
- The TED API is occasionally unavailable during maintenance; the Actor retries with backoff and
  reports a clear error if the API stays down.

### Data source and licence

All data comes from the **TED Search API** (`api.ted.europa.eu`), the official public interface
of TED operated by the Publications Office of the European Union, used within its
[fair usage policy](https://ted.europa.eu/en/simap/developers-corner-for-reusers). According to
the [TED legal notice](https://ted.europa.eu/en/legal-notice), the procurement notices published
in the OJ S **can be freely reused, for commercial or non-commercial purposes**, under the
Commission's reuse policy (Commission Decision 2011/833/EU on the reuse of Commission documents);
the editorial content of the TED website is licensed under CC BY 4.0 and its metadata under CC0.
Reuse of content that depicts identifiable private individuals or includes third-party works may
require additional rights, and TED's logos may not be used without the Publications Office's
consent. Only the electronically signed notices in the OJ S are authentic; the `links.xml` and
`links.pdf` of every item point at the source notice.

Personal data: the Actor requests only organisation-level fields and discards any field that could
hold contact persons, e-mail addresses or phone numbers. Buyer names and cities are public bodies,
not people.

### Integrations

- **Make, Zapier, n8n and other automation tools**: add the Apify integration (the official
  "Apify" app/node), choose *Run an Actor* with this Actor and your input, and use *Get dataset
  items* (or the "Actor run finished" trigger) to pass the records on - for example to a CRM or a Google Sheet of new tenders every morning after TED's daily publication.
  Each tool also accepts Apify webhooks: Console -> Actor -> Integrations -> Webhooks, event
  `Run succeeded`.
- **AI agents (MCP)**: Apify's MCP server (`https://mcp.apify.com`, or the `@apify/actors-mcp-server`
  package) exposes this Actor as a tool to Claude, ChatGPT, Cursor and other MCP clients: the
  agent calls `eu-tenders-ted-scraper` with an input such as `{"countries": ["CYP"], "cpvCodes": ["72"], "publishedAfter": "7 days"}` and reads the dataset
  items back.
- **API and SDKs**: `POST https://api.apify.com/v2/acts/davidts~eu-tenders-ted-scraper/run-sync-get-dataset-items`
  with the input as JSON body returns the records directly; the Apify client libraries for
  JavaScript and Python wrap the same call.
- **Schedules**: Console -> Schedules runs the Actor daily or weekly with a saved input and, combined
  with a webhook or integration, delivers only what is new.

### Troubleshooting

| Log message | What it means |
| --- | --- |
| `No filter was given, so the newest notices of the last 7 days are returned` | Set at least one filter (or a raw `query`) to search for what you need. |
| `Input field "countries" contains "..."` | Use alpha-3 codes (`CYP`, `GRC`) or two-letter EU codes, not country names. |
| `TED rejected the query: Syntax error ...` | The raw `query` (or keywords) is not valid expert syntax; the message gives the column. Test queries on TED's expert search page. |
| `TED's syntax check rejected the query ... Trying the search anyway` | The check endpoint objected but the search may still work; if the search is rejected too, the run fails with TED's message. |
| `TED rejected the field(s) ...` | TED changed a field name; the Actor continues without that field (its value is `null`) - please report it. |
| `TED rejected the request ("...") without naming a field; retrying with the field names known to work live` | TED refused the request without saying which field it dislikes; the Actor retries once with the field names a public client uses live and lists the left-out fields at the end - please report it. |
| `The query matched no notices` | Widen the filters (dates, CPV prefix) or check the country codes. |
| `TED rate-limited the requests (HTTP 429)` / `server error` | TED's fair-usage limit or maintenance; the Actor already retried with backoff. Run again later. |
| `maxNotices is 0 (no limit)` | A reminder that every matching notice will be saved and charged. |

### FAQ

**How much does it cost per 1,000 tenders?**
**$4** per 1,000 notices ($0.004 each) plus $0.005 per run, whatever filters or field preset you
choose. Platform usage is included. A daily alert for one sector that returns a few dozen notices
costs a few cents per run. You can cap the cost of any run in the run options.

**Is it legal to use TED data? What about GDPR?**
Yes - the Actor does not scrape web pages; it calls TED's official open API within its fair-usage
policy, and the Publications Office states that OJ S notices can be freely reused, commercially or
not (see *Data source and licence*). The Actor never requests contact persons, e-mail addresses or
phone numbers. This is not legal advice.

**Can I export tenders to CSV, Excel or Google Sheets?**
Yes. Every run's dataset downloads as CSV, Excel, JSON, XML or HTML from the Output tab. For
Google Sheets, import the CSV, use the *Google Sheets Import & Export* Actor from the Apify Store or a Make/Zapier scenario, or
point `=IMPORTDATA()` at the API URL of the last run's dataset (the URL contains your API token,
so keep the sheet private).

**How do I get a daily tender alert?**
Create a schedule in Apify Console (Schedules) that runs Monday to Friday after about 07:00 CET
with your filters plus `scope: "LATEST"` (only the latest daily OJ S issue, so each run returns
just that day's new notices) and `noticeTypes: ["cn-standard"]` (calls for tenders). Add an e-mail/Slack integration or webhook to receive the new
notices. Running more than once a day does not find more notices, because TED publishes once per
working day.

**Can I use it from my code, a CRM or an AI agent?**
Yes. `POST https://api.apify.com/v2/acts/davidts~eu-tenders-ted-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN`
with the input as JSON returns the notices directly; the Apify JavaScript and Python clients and
Apify's MCP server (for Claude, ChatGPT, Cursor and other agents) work too. See *Integrations*.

**Does it include national tenders below the EU thresholds?**
Mostly not - they are usually published only on national portals, not on TED. See *Limitations*.

If this Actor saves you time, a short **review on its Store page** helps other people find it -
thank you! Missing a filter or field? Open an issue on the Issues tab and I will look at it.

### Changelog

The full history is in the Actor's `CHANGELOG.md` (also shown in the Information tab in Apify
Console).

- **0.1** (2026-10) - first release: structured filters and raw expert queries, iteration-mode
  pagination, multilingual normalisation, `basic`/`full` presets, document links, pay-per-event
  pricing.

# Changelog

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

# Actor input Schema

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

Only notices whose buyer is in one of these countries. Use the ISO 3166-1 alpha-3 codes TED uses (`CYP` Cyprus, `GRC` Greece, `DEU` Germany, `FRA` France, `ITA` Italy, `ESP` Spain, `POL` Poland, `NLD` Netherlands, `GBR` United Kingdom, `NOR` Norway, `CHE` Switzerland, ...). Two-letter EU/EEA codes (`CY`, `GR`, `DE`, ...) are converted automatically. Leave empty for all countries.

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

Common Procurement Vocabulary codes that classify what is being bought. Give full 8-digit codes (`72260000` software-related services, `45000000` construction work) or just a prefix to cover a whole division (`72` = all IT services, `33` = medical equipment, `79` = business services). Leave empty for all sectors. Not sure which code? Look it up in the official CPV list or use Keywords instead.

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

Words that must all appear in the notice text (title, descriptions, buyer name ... in any language, stemmed). Put phrases in double quotes, e.g. `"software maintenance" ERP`. Leave empty for no text filter.

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

Only notices of these TED notice types. The most useful ones: `cn-standard` = contract notice (a call for tenders you can bid on), `can-standard` = contract award notice (who won and for how much), `pin-only` = prior information notice (a buyer announcing what it plans to buy). Leave empty for all types. To find tenders you can still bid on, choose `cn-standard` (or tick Only tenders open for submission).

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

Only notices published on TED on or after this date. Absolute date (`2026-01-31` or `20260131`, UTC) or a period counted back from now (`30 days`, `2 weeks`, `6 months`).

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

Only notices published on TED on or before this date. Absolute date (`2026-03-31`) or a period counted back from now (`7 days`).

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

Only notices whose deadline for receipt of tenders is on or after this date, so you skip tenders you can no longer bid on. Absolute date (`2026-11-15`) or a period counted forward from now (`7 days` = deadline at least a week away). Only competition notices have a deadline.

## `minValue` (type: `number`):

Only notices whose estimated value (or awarded value for award notices) is at least this amount in EUR. Notices that state their value in another currency or do not state a value are excluded when this filter is set.

## `onlyOpenForSubmission` (type: `boolean`):

Keep only competition notices (calls for tenders) whose submission deadline has not passed yet, as of the day the run starts.

## `maxNotices` (type: `integer`):

Maximum number of notices to save. Use `0` for all matching notices (careful: broad queries match hundreds of thousands of notices). Each saved notice is one dataset item and one paid result. For a first test, 20-100 is plenty.

## `sortBy` (type: `string`):

`publication-date-desc` = newest first (default), `publication-date-asc` = oldest first, `deadline-asc` = earliest submission deadline first (notices without a deadline, such as award notices, come last or first depending on TED's ordering).

## `fields` (type: `string`):

`basic` = the curated fields documented in the README (title, buyer, CPV, values, dates, links). `full` adds the description, notice and procedure identifiers, OJ S number, dispatch date, submission URL and a `raw` object with every field exactly as the TED API returned it.

## `includeDocumentLinks` (type: `boolean`):

Add `documentsUrl`, the address where the buyer publishes the tender documents (specifications, forms), when the notice states one.

## `query` (type: `string`):

Your own TED expert search query, e.g. `(buyer-country IN (CYP GRC)) AND (classification-cpv = 72*) AND (publication-date >= 20260101)`. When set, it replaces all the filters above (sorting is still applied unless the query has its own `SORT BY`). Build and test queries on https://ted.europa.eu/en/search/expert-search and paste them here.

## `scope` (type: `string`):

`ALL` = every notice published in the last 10 years (default). `ACTIVE` = TED's active notices: planning notices from the last 364 days, competition notices whose deadline has not passed and result notices from the last 99 days. `LATEST` = only the latest OJ S issue (TED's daily publication). Use `LATEST` for a daily scheduled tender alert that returns only the newest day's notices.

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

3-letter language code for multilingual values (`title`, `buyer.name`, `description`, links): `eng` English (default), `deu` German, `fra` French, `ell` Greek, `ita` Italian, `spa` Spanish, `pol` Polish, `nld` Dutch, ... When a notice has no text in this language, English is tried, then the notice's own language; `titleLanguage` tells you which one you got.

## Actor input object example

```json
{
  "countries": [
    "CYP",
    "GRC"
  ],
  "cpvCodes": [
    "72"
  ],
  "publishedAfter": "30 days",
  "onlyOpenForSubmission": false,
  "maxNotices": 20,
  "sortBy": "publication-date-desc",
  "fields": "basic",
  "includeDocumentLinks": true,
  "scope": "ALL",
  "preferredLanguage": "eng"
}
```

# Actor output Schema

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

One item per TED procurement notice (JSON, CSV or Excel via the format parameter)

# 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": [
        "CYP",
        "GRC"
    ],
    "cpvCodes": [
        "72"
    ],
    "publishedAfter": "30 days",
    "maxNotices": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("davidts/eu-tenders-ted-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": [
        "CYP",
        "GRC",
    ],
    "cpvCodes": ["72"],
    "publishedAfter": "30 days",
    "maxNotices": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("davidts/eu-tenders-ted-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": [
    "CYP",
    "GRC"
  ],
  "cpvCodes": [
    "72"
  ],
  "publishedAfter": "30 days",
  "maxNotices": 20
}' |
apify call davidts/eu-tenders-ted-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,davidts/eu-tenders-ted-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/9tbjI7jSV9NKutOdi/builds/4hY0wIeueKldSnzSv/openapi.json
