# EU Tenders Scraper - TED Notices, Deadlines & Contract Values (`maydit/eu-tenders-scraper`) Actor

Search official EU TED tenders by CPV, country, date or keyword. Get buyers, notice stages, published deadlines, separate estimated and awarded values, currencies and source links. No API key.

- **URL**: https://apify.com/maydit/eu-tenders-scraper.md
- **Developed by:** [Brandt May](https://apify.com/maydit) (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 $1.20 / 1,000 procurement notices

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 Scraper — TED notices, deadlines and contract values

Search the official EU TED procurement feed and get one row per notice. Filter by CPV category, buyer country, publication date, notice type or a word/phrase. Each result keeps the source notice number, original language, published deadlines, estimated value and awarded value with their separate currencies.

No API key, browser or proxy is needed. Empty input returns up to 20 recent notices from the last 30 days. Notices are ordered by publication date, newest first, and only the latest notice versions are requested.

### Useful searches

```json
{"cpvCodes":["72000000"],"lookbackDays":30,"maxItems":20}
```

This finds IT services procurement notices in TED's CPV hierarchy. To focus on German competition notices:

```json
{"buyerCountries":["DEU"],"noticeTypes":["cn-standard"],"maxItems":20}
```

For software notices across countries:

```json
{"keywords":"software","maxItems":20}
```

### What the results mean

| Output | Meaning |
| --- | --- |
| `publicationNumber`, `noticeId`, `noticeVersion` | Stable source identifiers. One publication number per row. |
| `publicationDate`, `publicationDateRaw` | Calendar date plus the source value, which may include an offset. |
| `title`, `titleLanguage`, `description` | Preferred language when published; otherwise an explicitly identified fallback. No translation. |
| `noticeType`, `noticeStage` | Source code and broad planning/competition/award-or-result/other grouping. This is not a bidding-eligibility decision. |
| `buyerNames`, `buyerCountries` | Buying organizations and where they are based. Countries may differ from the place of performance. |
| `cpvCodes` | Deduplicated procurement classification codes. |
| `estimatedValue`, `estimatedCurrency` | Procedure-level estimate when published. |
| `awardedValue`, `awardedCurrency` | Notice-level result value when published. Kept separate from the estimate; never converted to another currency. |
| `deadlineDates`, `deadlineDatesRaw`, `deadlineTimesRaw` | Published lot submission dates and times. TED's search response does not reliably pair these arrays to individual lots; the Actor does not invent that relationship. |
| `earliestFutureDeadlineDate`, `daysUntilEarliestFutureDeadline` | Earliest published date on or after today's UTC calendar date, and calendar days until it. A deadline today may already have passed at its local time. |
| `deadlineStatus` | Whether a date is absent, unparseable, all past, or includes today/future. This does not assert that a procedure is open. |
| `sourceUrl`, `xmlUrl`, `retrievedAt` | Official records to verify details and the collection time. |

Budget and awarded values are frequently absent, especially for planning/competition notices. Missing values are `null`, never zero. The Actor does not add personal contact details or download procurement attachments.

### Inputs

| Input | Default | Meaning |
| --- | --- | --- |
| `keywords` | empty | Full-text search. Multiple words are one exact phrase. |
| `cpvCodes` | empty | 8-digit codes or prefixes such as `72*`; any may match. Parent codes include the source's CPV hierarchy. |
| `buyerCountries` | empty | Any three-letter country codes, e.g. `DEU`, `FRA`, `IRL`. |
| `noticeTypes` | empty | Any TED codes, e.g. `cn-standard`, `can-standard`, `pin-only`. |
| `fromDate`, `toDate` | recent window / no end | Inclusive publication dates, `YYYY-MM-DD`. |
| `lookbackDays` | 30 | Recent window used when `fromDate` is absent. |
| `preferredLanguage` | `eng` | Three-letter language code; fallback language is shown. |
| `maxItems` | 20 | Maximum saved notices, 1–10,000. |
| `pageSize` | 50 | API results per request, 1–100. |
| `includeRaw` | false | Include selected API fields, not full XML. |
| `maxRunSeconds` | 240 | Wall-clock budget, at least 30 seconds. |

Filters are combined with AND; entries within a list use OR. `SUMMARY` records the exact query sent to TED, so results can be audited against the source.

### Coverage and recurring use

The Actor follows TED iteration tokens and deduplicates publication numbers. `SUMMARY` reports the source match count, scanned and saved counts, pages, skipped malformed records, field fill counts and the stop reason. `complete: true` means the requested source query was exhausted without detected errors. The default 20-row sample is usually capped and therefore has `complete: false`; this is expected. A larger limit or narrower filters returns more of the query. When the platform's spending cap is reached, `stoppedOnChargeLimit: true` identifies the stop, only notices actually saved are counted, and the run warns rather than reporting a source outage or an empty search.

Schedule the same search for current snapshots. This version does not keep a cross-run change baseline; deduplicate or compare `publicationNumber` and `noticeVersion` in your workflow. A broad newest-first query can contain award notices, planning notices and corrections as well as bidding opportunities. Read the official notice before acting on a deadline.

An honestly empty search warns and returns no rows. Transient network/server failures and rate limits retry up to three attempts while honoring `Retry-After` and the run budget. An API outage, malformed response or exhausted time budget before the first usable notice fails visibly. Later failures preserve already collected rows and mark the coverage partial.

### Data source and reuse

The [TED Search API](https://docs.ted.europa.eu/api/latest/search.html) is public and requires no authentication. TED's [legal notice](https://ted.europa.eu/en/legal-notice) allows commercial and noncommercial reuse of procurement notices unless otherwise noted and dedicates system metadata to CC0. Source: TED / Publications Office of the European Union. Fields are selected, normalized and derived as described above. This Actor is independent of TED.

### Pricing

Launch price: $0.002 per saved notice on FREE/BRONZE, with plan discounts. Actor Start: $0.00005. Check the live Pricing tab for the applied rate. A 20-notice run costs $0.04 in result charges; empty searches have no result charge. Run summaries and errors are not dataset result rows.

# Actor input Schema

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

Search the full notice with TED's FT operator. Multiple words form one exact phrase. Leave blank for recent notices. Quotes and backslashes are rejected to keep the filter unambiguous.

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

Any of these 8-digit CPV codes or 2–7 digit prefixes followed by *, e.g. 72000000 or 72*. TED treats parent CPV codes hierarchically. Combined with the other filters using AND.

## `buyerCountries` (type: `array`):

Three-letter country codes such as DEU, FRA, IRL or ESP. Filters where buyers are based, not where work is performed. Any listed country may match.

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

Optional TED notice-type codes, e.g. cn-standard (competition), can-standard (award), pin-only (planning). Leave empty for all types. Award notices are not open bids.

## `fromDate` (type: `string`):

Inclusive YYYY-MM-DD. If absent, use the last lookbackDays days. This is publication date, not the submission deadline.

## `toDate` (type: `string`):

Optional inclusive YYYY-MM-DD. Must be on or after fromDate.

## `lookbackDays` (type: `integer`):

Used only when fromDate is blank. Defaults to the last 30 days so an empty input produces a representative recent sample.

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

Three-letter TED language code, e.g. eng, deu, fra. If absent in a record, the Actor uses the first available language and reports it. It never translates text.

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

Maximum distinct notice rows to save. SUMMARY tells you whether the source had more results. Latest versions only; newest publication date first.

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

API page size. The Actor uses iteration tokens to paginate and stops on repeated tokens or unusable data.

## `includeRaw` (type: `boolean`):

Attach the untouched values of the selected API fields as raw. Personal contact fields are not requested. This is not the complete XML notice.

## `maxRunSeconds` (type: `integer`):

Stops requests and paging within this budget or 25 seconds before the platform timeout. Partial results and the reason appear in SUMMARY.

## Actor input object example

```json
{
  "lookbackDays": 30,
  "preferredLanguage": "eng",
  "maxItems": 20,
  "pageSize": 50,
  "includeRaw": false,
  "maxRunSeconds": 240
}
```

# Actor output Schema

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

One row per TED notice, with source links, published deadlines, separate estimated and awarded values, and notice stage.

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

Exact source query, matched and saved counts, pagination status, field coverage, skipped records and time-limit diagnostics.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("maydit/eu-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("maydit/eu-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 '{}' |
apify call maydit/eu-tenders-scraper --silent --output-dataset

```

## MCP server setup

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