# EBRD ECEPP Procurement Notices Scraper (`automation-lab/ebrd-ecepp-procurement-notices-scraper`) Actor

🔎 Search public EBRD ECEPP tenders, deadlines, projects, clients, awards, values, contractors, lots, and source links as structured data.

- **URL**: https://apify.com/automation-lab/ebrd-ecepp-procurement-notices-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Business
- **Stats:** 2 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## EBRD ECEPP Procurement Notices Scraper

Turn public EBRD procurement opportunities and contract awards into structured, monitor-ready data.

The **EBRD ECEPP Procurement Notices Scraper** searches `ecepp.ebrd.com`, applies practical procurement filters, and optionally enriches every selected notice from its detail page.

Use it to watch tender deadlines, identify projects and clients, research awarded contracts, or feed procurement intelligence systems without manually reviewing a large portal table.

- 🔎 Search notices by keyword, country, type, status, and dates
- 📅 Normalize publication and closing times from UK time to ISO 8601
- 📄 Enrich projects, methods, sectors, award values, contractors, and lots
- 🔗 Preserve ECEPP IDs and source links for verification
- ⚙️ Schedule repeat runs and export JSON, CSV, Excel, XML, or RSS

### What does the EBRD ECEPP Procurement Notices Scraper do?

The Actor downloads the anonymous public ECEPP notice index, filters its structured rows, and returns up to your requested limit.

When detail enrichment is enabled, it also opens the chosen public notice pages and extracts fields that are not present in the result list.

It supports both broad discovery and exact notice URLs.

No EBRD account is required.

The Actor does not submit bids, respond to opportunities, or access private procurement documents.

### Who is it for?

#### Suppliers and bid teams

Find open notices relevant to products, services, countries, and target sectors.

#### Procurement intelligence teams

Create a repeatable feed of notices and awards with stable IDs and source evidence.

#### Consultants

Track project implementation support, supervision, engineering, and advisory opportunities.

#### Market researchers

Analyze countries, clients, methods, sectors, signed values, and successful contractors.

#### Data product builders

Use the API or MCP output as a source for alerts, dashboards, CRMs, warehouses, and tender products.

### Why use this EBRD tender scraper?

ECEPP exposes useful public data, but the search page contains a very large table and browser-side filters.

This Actor converts that surface into clean records with typed values and normalized dates.

- ✅ No login or browser automation
- ✅ Strict ECEPP URL validation
- ✅ Conservative request concurrency
- ✅ Search records survive an individual detail-page error
- ✅ Search layout failures stop visibly instead of returning misleading success
- ✅ Dataset output works with all Apify integrations

### What EBRD procurement data can I extract?

| Field | Meaning |
|---|---|
| `displayNoticeId` | ID used by the public detail URL |
| `eceppId` | ECEPP notice identifier shown by the source |
| `title` | Procurement exercise or notice title |
| `projectName` | EBRD project name |
| `ebrdProjectId` | EBRD project identifier |
| `country` | Project country |
| `clientName` | Procuring client or executing agency |
| `noticeType` | Invitation, award, addendum, or other source type |
| `status` | Opportunity state shown in search results |
| `publicationDate` | ISO UTC publication timestamp |
| `closingDate` | ISO UTC response deadline when available |
| `procurementType` | Goods, works, consultancy, or other type |
| `procurementMethod` | Tendering method |
| `businessSector` | EBRD business sector |
| `contractValue` | Numeric signed contract value when published |
| `contractCurrency` | Three-letter award currency |
| `contractorName` | Awarded contracting party when published |
| `lotTitle` | Award lot title when published |
| `detailUrl` | Original public ECEPP notice URL |

Optional fields are omitted when ECEPP does not publish them for that notice.

### How to scrape EBRD ECEPP notices

1. Open the Actor input page.
2. Leave the default ECEPP search URL or provide exact public notice URLs.
3. Enter a keyword such as `water`, `energy`, or `consultant`.
4. Optionally add countries, notice types, statuses, or date boundaries.
5. Choose whether to enrich notice detail pages.
6. Set a result limit appropriate for the workflow.
7. Click **Start**.
8. Open the Dataset tab to review or export records.

Start with 10 notices while refining filters.

### Input parameters

| Input | Type | Default | Purpose |
|---|---|---:|---|
| `searchUrls` | array | ECEPP search page | Search or exact public notice URLs |
| `keyword` | string | `water` prefill | Case-insensitive text match |
| `countries` | string\[] | empty | Exact source country names |
| `noticeTypes` | string\[] | empty | Partial notice-type matches |
| `statuses` | string\[] | empty | Exact opportunity states |
| `publishedFrom` | date | empty | Inclusive publication lower bound |
| `publishedTo` | date | empty | Inclusive publication upper bound |
| `closingFrom` | date | empty | Inclusive closing lower bound |
| `closingTo` | date | empty | Inclusive closing upper bound |
| `includeDetails` | boolean | `true` | Enrich project and award fields |
| `maxItems` | integer | `25` | Maximum emitted notices |
| `maxConcurrency` | integer | `4` | Simultaneous detail requests |

Only `https://ecepp.ebrd.com/delta/noticeSearchResults.html` and public `viewNotice.html` URLs are accepted.

### Example input

```json
{
  "keyword": "water",
  "countries": ["Tajikistan", "Uzbekistan"],
  "statuses": ["Open"],
  "includeDetails": true,
  "maxItems": 25,
  "maxConcurrency": 4
}
```

For contract-award intelligence:

```json
{
  "countries": ["Ukraine"],
  "noticeTypes": ["Contract Award"],
  "includeDetails": true,
  "maxItems": 50
}
```

### Example output

```json
{
  "displayNoticeId": "44331859",
  "eceppId": "38630996",
  "title": "Tender #1 - Supply of containerized Gas Engine Power Plants (5 lots)",
  "projectName": "RLF - UZ Energy",
  "ebrdProjectId": "55879",
  "country": "Ukraine",
  "clientName": "Ukrainian Railways PJSC (UZ)",
  "noticeType": "Ebrd Contract Award Notice",
  "publicationDate": "2026-04-28T17:05:00.000Z",
  "procurementType": "Goods",
  "procurementMethod": "Open Tender Single Stage",
  "contractValue": 87001444,
  "contractCurrency": "EUR",
  "contractorName": "JV RSE-Kaltimex-UECL",
  "detailUrl": "https://ecepp.ebrd.com/delta/viewNotice.html?displayNoticeId=44331859"
}
```

Exact fields depend on what ECEPP publishes for each notice.

### How much does it cost to scrape EBRD tenders?

The Actor uses pay-per-event pricing: a small **$0.005 start charge** plus a charge for each procurement notice saved.

Per-notice rates decrease by Apify plan tier: **$0.00011899 on Free, $0.00010347 on Bronze, $0.000080706 on Silver, $0.000062081 on Gold, $0.000041388 on Platinum, and $0.000028971 on Diamond**.

Because filtering happens before detail enrichment, narrow searches avoid unnecessary detail requests.

A 10-notice monitoring run pays for 10 output records, not for every row in the source table.

Use a low `maxItems` value while testing a new workflow.

### Search and filter behavior

Keyword matching covers the structured search record, including title, project, country, client, procurement type, method, sector, notice type, and identifiers.

Countries and statuses use exact case-insensitive matches.

Notice types use partial case-insensitive matches, so `Contract Award` can match a longer source label.

Date boundaries are inclusive.

If valid filters match no records, the run succeeds with an empty dataset.

### Detail enrichment

Set `includeDetails` to `true` to retrieve richer public notice fields.

This is particularly useful for contract awards, where ECEPP may publish:

- 💶 signed value and currency
- 🏢 contracting party
- 📦 lot number, title, and description
- 🗓️ signature and scheduled completion dates
- 🧭 project and business-sector context
- ✉️ contact details when included in the public notice

Set it to `false` for fast index-only monitoring.

### Scheduling tender monitoring

Use an Apify schedule to run the Actor daily or weekly.

Apply a recent `publishedFrom` boundary and stable keyword/country filters.

Send the resulting dataset to a webhook, email workflow, Slack automation, database, or change-detection process.

Use `displayNoticeId` or `eceppId` as a downstream deduplication key.

Store previous records if you need to detect deadline, status, addendum, or award changes over time.

### Integrations

#### Google Sheets

Export a recurring notice feed for bid qualification and ownership.

#### Webhooks and Make

Trigger an alert when a new record matches a target country or notice type.

#### Zapier

Create CRM opportunities or tasks from new tender records.

#### Data warehouses

Load JSON or CSV into BigQuery, Snowflake, PostgreSQL, or another analytics system.

#### Slack and Microsoft Teams

Post concise deadline alerts with the original `detailUrl`.

### Use with the Apify API in Node.js

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/ebrd-ecepp-procurement-notices-scraper').call({
  keyword: 'energy',
  statuses: ['Open'],
  includeDetails: true,
  maxItems: 25,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Use with the Apify API in Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("automation-lab/ebrd-ecepp-procurement-notices-scraper").call(
    run_input={"keyword": "consultant", "maxItems": 20, "includeDetails": True}
)
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)
```

### Use with cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~ebrd-ecepp-procurement-notices-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keyword":"water","maxItems":10,"includeDetails":true}'
```

Retrieve items from the run's default dataset after it finishes.

### Use EBRD procurement data with MCP

Connect Claude Code:

```bash
claude mcp add --transport http apify "https://mcp.apify.com?tools=automation-lab/ebrd-ecepp-procurement-notices-scraper"
```

Claude Desktop, Cursor, and VS Code can use this MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/ebrd-ecepp-procurement-notices-scraper"
    }
  }
}
```

Example prompts:

- “Find open EBRD water tenders and summarize their closing dates.”
- “Extract recent Ukraine contract awards and rank them by signed value.”
- “Create a table of consultancy notices by country, client, and method.”

### Tips for reliable results

- Use ECEPP's exact country wording.
- Start broad when discovering source terminology, then add filters.
- Keep detail concurrency at 4 unless a larger workload requires more.
- Use index-only mode when project and award fields are unnecessary.
- Keep source IDs and URLs in downstream systems for traceability.
- Remember that source publication and deadline availability varies by notice type.

### Troubleshooting

#### Why did my run return no notices?

Remove filters one at a time. An exact country or status value may not match ECEPP wording, or the selected date window may contain no matching public records.

#### Why is a contract value or contractor missing?

Those fields appear only when ECEPP publishes an award or contract section. Enable `includeDetails` and verify the source notice contains the field.

#### Why was my URL rejected?

The Actor accepts only the supported public ECEPP search and notice-detail routes. External URLs and other ECEPP paths fail closed to preserve product scope.

### Data quality and source changes

The Actor extracts public source data as published by EBRD ECEPP.

It preserves both display and ECEPP identifiers because they can differ.

Dates labeled as UK time are converted to UTC with daylight-saving awareness.

If the source search table disappears or changes so completely that no notices can be parsed, the run fails rather than silently returning a false success.

Individual detail failures fall back to the valid search record.

### Is scraping EBRD ECEPP legal?

This Actor accesses anonymous public procurement pages.

Users are responsible for complying with applicable laws, EBRD terms, source licenses, and privacy obligations.

Do not use the Actor to overload the site, automate bid submission, access restricted materials, or republish personal contact data without a lawful purpose.

Use conservative limits and retain source attribution.

This information is not legal advice.

### FAQ

#### Does it require an EBRD account?

No. The supported search and public notice pages are anonymous.

#### Can it submit a tender response?

No. It is a public-data extraction and monitoring tool only.

#### Can I scrape one exact notice?

Yes. Add its public `viewNotice.html?displayNoticeId=...` URL to `searchUrls`.

#### Can I monitor awards?

Yes. Filter `noticeTypes` with `Contract Award` and enable details.

#### Are dates strings or timestamps?

Output dates are ISO 8601 UTC strings suitable for sorting and integrations.

#### Does it use a proxy or browser?

No proxy or browser is required for the current anonymous server-rendered ECEPP pages.

### Related procurement scrapers

Combine EBRD intelligence with other public procurement sources:

- [UNGM Tender Opportunities Scraper](https://apify.com/automation-lab/ungm-tender-opportunities-scraper)
- [World Bank Procurement Notices Scraper](https://apify.com/automation-lab/world-bank-procurement-notices-scraper)
- [TED EU Tenders Scraper](https://apify.com/automation-lab/ted-eu-tenders-scraper)
- [UK Contracts Finder Scraper](https://apify.com/automation-lab/uk-contracts-finder-scraper)

Always verify related Actor availability and choose the portal matching your target procurement authority.

### Source and support

Source: [EBRD ECEPP](https://ecepp.ebrd.com/delta/noticeSearchResults.html).

For a reproducible support request, include the Actor run ID, input, expected notice, and source URL.

Do not include private bid documents, credentials, or confidential procurement information.

# Actor input Schema

## `searchUrls` (type: `array`):

Optional ECEPP search-results or viewNotice URLs. Leave empty to search all public notices.

## `keyword` (type: `string`):

Keep notices containing this text in any search field, such as water, energy, or consultant.

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

Exact ECEPP country names, for example Ukraine or Tajikistan.

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

Partial notice-type matches, for example Invitation For Tenders or Contract Award.

## `statuses` (type: `array`):

Exact statuses from search results, such as Open or Closed.

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

Include notices published on or after this date (YYYY-MM-DD).

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

Include notices published on or before this date (YYYY-MM-DD).

## `closingFrom` (type: `string`):

Include notices closing on or after this date (YYYY-MM-DD).

## `closingTo` (type: `string`):

Include notices closing on or before this date (YYYY-MM-DD).

## `includeDetails` (type: `boolean`):

Open each selected notice to collect project, award, lot, value, contractor, and contact fields.

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

Stop after this many matching procurement notices.

## `maxConcurrency` (type: `integer`):

Maximum simultaneous notice-detail requests. Keep conservative for ECEPP.

## Actor input object example

```json
{
  "searchUrls": [
    {
      "url": "https://ecepp.ebrd.com/delta/noticeSearchResults.html"
    }
  ],
  "keyword": "water",
  "includeDetails": true,
  "maxItems": 10,
  "maxConcurrency": 4
}
```

# Actor output Schema

## `overview` (type: `string`):

Open the default dataset table containing one structured record per ECEPP notice.

# 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 = {
    "searchUrls": [
        {
            "url": "https://ecepp.ebrd.com/delta/noticeSearchResults.html"
        }
    ],
    "keyword": "water",
    "includeDetails": true,
    "maxItems": 10,
    "maxConcurrency": 4
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/ebrd-ecepp-procurement-notices-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 = {
    "searchUrls": [{ "url": "https://ecepp.ebrd.com/delta/noticeSearchResults.html" }],
    "keyword": "water",
    "includeDetails": True,
    "maxItems": 10,
    "maxConcurrency": 4,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/ebrd-ecepp-procurement-notices-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 '{
  "searchUrls": [
    {
      "url": "https://ecepp.ebrd.com/delta/noticeSearchResults.html"
    }
  ],
  "keyword": "water",
  "includeDetails": true,
  "maxItems": 10,
  "maxConcurrency": 4
}' |
apify call automation-lab/ebrd-ecepp-procurement-notices-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=automation-lab/ebrd-ecepp-procurement-notices-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/PhK7acZ1Fj1aurWVU/builds/gAsYP0psI8QXSUaT0/openapi.json
