# World Bank Tenders Scraper (`automatic/worldbank-tenders-scraper`) Actor

Find open World Bank-funded tenders: invitations for bids and requests for expressions of interest in 120+ countries, with buyer, country, sector, method, local deadline and links. Filter by keyword, country, region, sector, category and publish date. Awards on request.

- **URL**: https://apify.com/automatic/worldbank-tenders-scraper.md
- **Developed by:** [Philip Kirkbride](https://apify.com/automatic) (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 $0.90 / 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

## World Bank Tenders Scraper

Find tenders financed by the World Bank: invitations for bids, requests for expressions of interest and prequalification notices from borrower governments in more than 120 countries. By default you get only notices that are **still open**, newest first, one clean row each: title, buyer, country and region, sector, goods/works/consulting category, selection method, publication date, the deadline in the buyer's local time, and the link to the official notice.

Built for contractors, consulting firms, suppliers and bid teams who chase development-funded work. Schedule a daily run with your countries, sectors or keywords and "published in the last 2 days", and send the new rows to email, Slack or a spreadsheet.

### Quick start

The newest open tenders:

```json
{"maxItems": 20}
```

Open works and goods tenders in East Africa, with a short description and the links each notice quotes:

```json
{
  "countries": ["KE", "UG", "TZ"],
  "procurementCategories": ["works", "goods"],
  "includeDetails": true,
  "maxItems": 200
}
```

New consulting assignments on solar energy, published this week:

```json
{
  "keywords": "solar",
  "procurementCategories": ["consulting-services"],
  "publishedWithinDays": 7
}
```

Recent contract awards in health projects (awards are only returned when you ask for them):

```json
{
  "status": "all",
  "noticeTypes": ["contract-award"],
  "sectors": ["Health"],
  "publishedWithinDays": 30
}
```

### Input

| Field | Type | Default | What it does |
|---|---|---:|---|
| `keywords` | string | `""` | Words to find in the notice, in any language. Every word must appear; "double quotes" match a phrase. |
| `countries` | array | `[]` | Project countries as two-letter ISO codes, e.g. `KE`, `NG`, `IN`, `BD`. |
| `regions` | array | `[]` | World Bank regions, e.g. `South Asia`. Use this for regional projects that span several countries. |
| `sectors` | array | `[]` | Project sectors, e.g. `Health`, `Water Supply`, `Renewable Energy Solar` (pick from the list). |
| `procurementCategories` | array | `[]` | `goods`, `works`, `consulting-services`, `non-consulting-services`. |
| `procurementMethods` | array | `[]` | Selection methods, e.g. `RFB` (request for bids), `RFQ` (request for quotations), `QCBS`, `CQS`, `INDV` (individual consultants). |
| `noticeTypes` | array | open notice types | `invitation-for-bids`, `request-for-expression-of-interest`, `invitation-for-prequalification`, `general-procurement-notice`, `contract-award`. |
| `status` | string | `open` | `open`: only notices whose deadline is still ahead. `all`: also notices whose deadline has passed. General procurement notices and contract awards have no deadline, so they need `all`. |
| `publishedSince` | string | none | Only notices published on or after this date, `YYYY-MM-DD`. |
| `publishedWithinDays` | integer | none | Only notices published in the last N days, today included (UTC). Use one of the two date fields, not both. |
| `maxItems` | integer | `50` | Most notices to return, newest first. Up to 50,000. |
| `includeDetails` | boolean | `false` | Adds `descriptionExcerpt` and `documentLinks`. Runs take longer with this on. |

All filters are optional and can be combined. An empty input returns the 50 newest open notices.

### What it returns

Every row has `tenderId`, `url` (the official notice page), `noticeType`, `status` (`open`, `closed` or `awarded`), `title`, `referenceNumber`, `projectId`, `projectName`, `projectUrl`, `buyerName`, `buyerCountry`, `buyerWebsite`, `buyerContactName`, `buyerEmail`, `buyerPhone`, `buyerAddress`, `countryCode`, `countryName`, `region`, `procurementCategory`, `procurementCategoryCode`, `procurementMethod`, `procurementMethodCode`, `sectors`, `sectorCodes`, `language`, `publishedAt`, `deadline`, `deadlineDate`, `deadlineLocalTime`, `deadlineTimezone`, `descriptionExcerpt`, `documentLinks`, `awardValue`, `awardCurrency`, `awardedSuppliers`, `sourceQuery`, `source` and `scrapedAt`.

- `deadline` is ISO 8601 with the local UTC offset, e.g. `2026-11-26T11:00+03:00`, so you can sort and compare deadlines across countries. `deadlineDate` and `deadlineLocalTime` are the date and clock time exactly as published.
- `publishedAt` is a date (`YYYY-MM-DD`): the World Bank publishes the day, not the time.
- `sectors` and `sectorCodes` are the World Bank's own sector names and codes for the financing project.
- `awardValue`, `awardCurrency` and `awardedSuppliers` are filled on contract award notices only.
- `descriptionExcerpt` and `documentLinks` are filled when `includeDetails` is on, and are empty (`null`) otherwise.

### Output example

```json
{"tenderId":"OP00473660","url":"https://projects.worldbank.org/en/projects-operations/procurement-detail/OP00473660","noticeType":"Invitation for Bids","status":"open","title":"Upgrading to Bitumen Standards of Selected Link Roads within Meru Town","referenceNumber":"KE-KENHA-533026-CW-RFB","projectId":"P161305","projectName":"Horn of Africa Gateway Development Project","projectUrl":"https://projects.worldbank.org/en/projects-operations/project-detail/P161305","buyerName":"Kenya National Highways Authority","buyerCountry":"Kenya","buyerWebsite":"http://www.kenha.co.ke","buyerContactName":null,"buyerEmail":null,"buyerPhone":null,"buyerAddress":null,"countryCode":"KE","countryName":"Kenya","region":"Eastern And Southern Africa","procurementCategory":"works","procurementCategoryCode":"CW","procurementMethod":"Request for Bids","procurementMethodCode":"RFB","sectors":["Rural and Inter-Urban Roads","ICT Infrastructure","Public Administration - Transportation"],"sectorCodes":["TI","CI","TF"],"language":"English","publishedAt":"2026-10-13","deadline":"2026-11-26T11:00+03:00","deadlineDate":"2026-11-26","deadlineLocalTime":"11:00","deadlineTimezone":"Africa/Nairobi","descriptionExcerpt":"Specific Procurement Notice (Two-envelope Bidding Process Without Prequalification) Employer: Kenya National Highways Authority (KeNHA) Project: Horn of Africa Gateway Development Project (HoAGDP). Contract title: Upgrading to Bitumen Standards of Selected Link Roads and Construction of 2 No.","documentLinks":["https://www.kenha.co.ke","https://www.tenders.go.ke"],"awardValue":null,"awardCurrency":null,"awardedSuppliers":null,"sourceQuery":"status=open countries=KE|UG|TZ noticeTypes=invitation-for-bids,request-for-expression-of-interest,invitation-for-prequalification","source":"worldbank.org","scrapedAt":"2026-11-03T17:14:02+00:00"}
```

### Empty fields and why

- Some deadlines have no time: a few notices publish only the closing date, with no clock time. For those, `deadline` and `deadlineLocalTime` are empty and `deadlineDate` holds the date. `deadline` is also empty when the project spans several time zones and the buyer's zone cannot be told; `deadlineDate` is still filled. That is about one open notice in nine.
- `countryCode` is empty for regional projects (for example "Western and Central Africa"); `countryName` then holds the region and `buyerCountry` the agency's country.
- `sectors` is empty when the World Bank lists no sector for the project.
- Estimated contract values are not part of World Bank notices, so there is no estimate field; award notices carry the signed contract value.
- `descriptionExcerpt` is empty when the source has no notice text.

### Limits

- Up to 50,000 notices per run, newest first; one search can reach at most 100,000 notices, so split very broad searches by country, region or date.
- Runs deliver about 100 notices a second; with `includeDetails` on they are slower, because each notice's full text is read.
- `status: open` keeps a notice until its deadline has passed in the buyer's time zone.

### Published information

Public notice text and agency contacts are returned as published. `buyerContactName`, `buyerEmail`, `buyerPhone` and `buyerAddress` contain the implementing agency's published contact information when available. Awarded suppliers are returned as published, including firms and the source's own placeholders such as `Individual Consultant`; individual names are only available when the source supplies them. Descriptions may include published beneficial-owner information.

### FAQ

**How do I get only new tenders each day?** Schedule a daily run with `publishedWithinDays: 2` and your filters, and deduplicate on `tenderId`.

**Where do I get the bidding documents?** Open `url` for the official notice; with `includeDetails` on, `documentLinks` lists the document and e-procurement pages the notice quotes.

**What happens when nothing matches?** The run succeeds with an empty dataset and says so in its status message.

### Price

You pay per result: each delivered notice row is one result, plus a small run-start charge. The run-start event is charged per GB of memory; the default 512 MB run is one start event. The start is charged even if the run saves no results. See the Pricing tab for current prices.

### Support

For questions or issues, contact us from the Actor page.

# Actor input Schema

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

Words to find in the notice title and text, in any language. Every word must appear; put a phrase in "double quotes". Leave empty for all notices.

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

Project countries as two-letter ISO codes, for example KE, NG, IN or BD. Leave empty for all countries.

## `regions` (type: `array`):

World Bank regions. Regional projects that span several countries are found here. Leave empty for all regions.

## `sectors` (type: `array`):

World Bank project sectors, for example Health, Water Supply or Renewable Energy Solar. A notice matches if its project lists any of them.

## `procurementCategories` (type: `array`):

Goods, works, consulting services or non-consulting services. Leave empty for all.

## `procurementMethods` (type: `array`):

Selection methods, for example RFB (request for bids), RFQ (request for quotations) or QCBS (quality and cost-based selection). Leave empty for all.

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

Leave empty for invitations for bids, requests for expressions of interest and invitations for prequalification (plus general procurement notices when status is 'all'). Contract awards and general procurement notices have no deadline: select them with status 'all'.

## `status` (type: `string`):

'open' returns only notices whose bid or expression-of-interest deadline is still ahead. 'all' also returns notices whose deadline has passed.

## `publishedSince` (type: `string`):

Only notices published on or after this date (YYYY-MM-DD). Use it, or 'Published within days', to pick up only new notices on each scheduled run.

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

Only notices published in the last N days, today included (UTC). Handy for daily or weekly schedules. Do not combine with 'Published since'.

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

Most notices to return, newest first. Up to 50,000.

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

Adds a short description of each notice as published and the links it quotes, including public contact, bidding-document and e-procurement links. Runs take longer with this on.

## Actor input object example

```json
{
  "keywords": "",
  "countries": [],
  "regions": [],
  "sectors": [],
  "procurementCategories": [],
  "procurementMethods": [],
  "noticeTypes": [],
  "status": "open",
  "maxItems": 20,
  "includeDetails": false
}
```

# 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 = {
    "keywords": "",
    "status": "open",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automatic/worldbank-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 = {
    "keywords": "",
    "status": "open",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automatic/worldbank-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 '{
  "keywords": "",
  "status": "open",
  "maxItems": 20
}' |
apify call automatic/worldbank-tenders-scraper --silent --output-dataset

```

## MCP server setup

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