# World Bank Indicators — GDP, Inflation, Population & 16k More (`yadroo/world-bank-indicators`) Actor

World Bank macro data for any country: GDP, growth, inflation, population, unemployment, trade, FDI, debt, digital, climate — 16,000+ indicators, 217 economies + aggregates. Presets, latest-value ranking tables with YoY change, wide comparison tables, indicator search. No API key.

- **URL**: https://apify.com/yadroo/world-bank-indicators.md
- **Developed by:** [Samat Makatov](https://apify.com/yadroo) (community)
- **Categories:** AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.35 / 1,000 result items

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

Country × indicator × year data straight from the World Bank Indicators API v2: GDP, GDP per capita, inflation, population, unemployment, trade, FDI, debt, interest rates, internet users, CO2, poverty… for any of 217 economies and 78 aggregates (World, EU, OECD, income groups, regions). Built for analysts, researchers and AI agents that need clean macro data with units, latest-value tables, YoY change and wide comparison tables. No API key, no proxy, no browser.

### Use cases

- **Country due diligence** — pull GDP, growth, inflation, debt, reserves and FX rate for a market before entering it (`indicatorPreset: "finance"`).
- **Market sizing** — population, urbanisation, internet users, GDP per capita PPP for a region (`region: "ECS"`, `incomeLevel: "UMC"`).
- **Country ranking tables** — one row per country with latest value and YoY change (`mode: "latest"`, `countries: ["all"]`).
- **Trade & export research** — exports/imports % GDP, merchandise trade, tariffs, FDI for a set of partners as one wide table (`indicatorPreset: "trade"`, `wide: true`).
- **ESG / climate screening** — CO2 per capita, renewables share, PM2.5, forest area (`indicatorPreset: "energyClimate"`).
- **Monthly macro monitoring** — CPI, industrial production, exchange rates from the Global Economic Monitor (`source: 15`, `frequency: "M"`).
- **Indicator discovery for agents** — search the 1,500 WDI (or 29,500 total) indicators by text and topic, read definitions (`mode: "indicators"`, `mode: "indicatorMeta"`).

### Input

| Field | Type | Default | Allowed values / notes |
|---|---|---|---|
| `mode` | string | `data` | `data` time series · `latest` one row per country×indicator · `indicators` catalogue search · `countries` country metadata · `sources` database list · `indicatorMeta` definitions |
| `countries` | string\[] | — (required for data/latest unless a filter is set) | ISO2 (`KZ`), ISO3 (`KAZ`), English names (`Kazakhstan`), `all` (every economy; aggregates only with `includeAggregates: true`), aggregate codes (`WLD`, `EUU`, `OED`, `HIC`, `ECS`…). Case, accents, spaces and punctuation do not matter. An unknown value → warning + `SUMMARY.errors` with a "did you mean" (not a dataset row, not billed); the other countries are still read. No known value at all → the run stops with that message |
| `indicators` | string\[] | macro set | Any World Bank indicator codes. Empty = `indicatorPreset` |
| `indicatorPreset` | string | `custom` | `macro`, `trade`, `demographics`, `finance`, `digital`, `energyClimate`, `social`, `business`, `custom` (see Reference) |
| `years` | integer | 5 | Most recent N periods (API `mrv`), 1–60. Not used by `mode: latest` |
| `startYear` / `endYear` | integer | — | Explicit range (API `date=start:end`), overrides `years`/`mrnev`. With `mode: latest`: the latest value inside the range |
| `mrnev` | integer | — | N most recent **non-empty** values per country (skips missing years), overrides `years`. Not used by `mode: latest` (it always takes latest + previous non-empty value) |
| `gapfill` | boolean | false | With `years` only: API fills missing years with last value |
| `frequency` | string | `Y` | `Y`, `Q`, `M` — sub-annual only for sources 15 (GEM, monthly) and 20/22/23 (quarterly debt) |
| `source` | integer | 2 | World Bank database id (2 = WDI). List with `mode: "sources"` |
| `includeNulls` | boolean | false | Keep rows with `value: null` |
| `includeChange` | boolean | false | Add `yoyChangePct`, `previousYear`, `previousValue` per row (vs previous non-null period) |
| `wide` | boolean | false | One row per country × period, indicator codes as columns (saved after the last indicator is read) |
| `fields` | string\[] | — (all columns) | Keep only these columns, in this order; `id` is always kept. Columns per mode: see Output. Case, spaces, `_` and `-` do not matter; a name that is not a column of the mode is skipped and named in the status and `SUMMARY.warnings`; if none is a column, the run stops before any request with the list of valid columns |
| `maxItems` | integer | 1000 | Cap on dataset rows (1–50,000); pagination is automatic and stops once the cap is reached |
| `query` | string | — | `mode: indicators`: text to match in code, name, definition |
| `topic` | string | — | `mode: indicators`: topic id 1–21 (see Reference) |
| `searchAllSources` | boolean | false | `mode: indicators`: search all ~29,500 indicators instead of only `source` |
| `region` | string | — | `EAS`, `ECS`, `LCN`, `MEA`, `NAC`, `SAS`, `SSF`, `NA` (aggregates) — selects countries in data/latest modes when `countries` is empty or `all`; filters `mode: countries` |
| `incomeLevel` | string | — | `HIC`, `UMC`, `LMC`, `LIC` |
| `lendingType` | string | — | `IBD`, `IDX`, `IDB`, `LNX` |
| `includeAggregates` | boolean | false | Include the aggregates (World, EU, regions, income and lending groups — region "Aggregates" in the World Bank country metadata) in `countries: ["all"]`, `mode: countries` and region/income selections. Aggregate codes you list explicitly (`WLD`, `EUU`…) are always returned. Every data row has `isAggregate`. |

Backward compatible: `{ "countries": [...], "indicators": [...], "years": N }` works exactly as before.

`mode`, `indicatorPreset`, `frequency`, `topic`, `region`, `incomeLevel` and `lendingType` are fixed lists (values above and in Reference): Apify refuses any other value before the run starts, with the list of allowed values.

### Reference

#### Indicator presets (all codes verified against the API in September 2026)

| Preset | Codes |
|---|---|
| `macro` (default) | `NY.GDP.MKTP.CD` GDP US$ · `NY.GDP.PCAP.CD` GDP per capita · `FP.CPI.TOTL.ZG` CPI inflation % · `SP.POP.TOTL` population · `SL.UEM.TOTL.ZS` unemployment % |
| `trade` | `NE.EXP.GNFS.ZS` `NE.IMP.GNFS.ZS` `NE.TRD.GNFS.ZS` (% GDP) · `TX.VAL.MRCH.CD.WT` `TM.VAL.MRCH.CD.WT` merchandise US$ · `BX.KLT.DINV.CD.WD` FDI inflows · `BN.CAB.XOKA.GD.ZS` current account % GDP · `TM.TAX.MRCH.WM.AR.ZS` tariff % |
| `demographics` | `SP.POP.TOTL` `SP.POP.GROW` `SP.URB.TOTL.IN.ZS` `SP.POP.65UP.TO.ZS` `SP.DYN.LE00.IN` `SP.DYN.TFRT.IN` `SM.POP.NETM` `SL.TLF.TOTL.IN` |
| `finance` | `FR.INR.LEND` `FR.INR.RINR` `FM.LBL.BMNY.GD.ZS` `FS.AST.PRVT.GD.ZS` `FB.AST.NPER.ZS` `PA.NUS.FCRF` `FI.RES.TOTL.CD` `GC.DOD.TOTL.GD.ZS` `GC.TAX.TOTL.GD.ZS` `DT.DOD.DECT.CD` |
| `digital` | `IT.NET.USER.ZS` `IT.CEL.SETS.P2` `IT.NET.BBND.P2` `IT.NET.SECR.P6` `TX.VAL.TECH.CD` `GB.XPD.RSDV.GD.ZS` |
| `energyClimate` | `EG.USE.PCAP.KG.OE` `EG.ELC.ACCS.ZS` `EG.FEC.RNEW.ZS` `EG.ELC.RNEW.ZS` `EN.GHG.CO2.PC.CE.AR5` `EN.GHG.CO2.MT.CE.AR5` `EN.ATM.PM25.MC.M3` `AG.LND.FRST.ZS` |
| `social` | `SE.PRM.ENRR` `SE.TER.ENRR` `SE.ADT.LITR.ZS` `SH.XPD.CHEX.GD.ZS` `SH.MED.PHYS.ZS` `SI.POV.DDAY` `SI.POV.GINI` `SI.DST.10TH.10` |
| `business` | `IC.BUS.NREG` `IC.BUS.NDNS.ZS` `LP.LPI.OVRL.XQ` `GC.TAX.TOTL.GD.ZS` `BX.KLT.DINV.WD.GD.ZS` `FS.AST.PRVT.GD.ZS` `IP.PAT.RESD` `VC.IHR.PSRC.P5` |

The built-in dictionary (`src/lib.ts`, ~110 codes) also carries a `unit` for each of these plus GDP PPP, GNI per capita, GDP deflator, sector value added, remittances, external debt ratios, military spending, reserves in months of imports, market cap, youth unemployment, labour participation, infant mortality, tourism, air passengers, container traffic, cereal production/yield, agricultural land, health spending per capita, hospital beds, national poverty line, women in parliament, R\&D researchers, patents, journal articles, CPIA ratings. For any other code the unit is parsed from the indicator name (`"… (% of GDP)"` → `% of GDP`).

**Archived codes that return no data** (the actor warns): `EN.ATM.CO2E.PC` / `EN.ATM.CO2E.KT` (use `EN.GHG.CO2.PC.CE.AR5` / `EN.GHG.CO2.MT.CE.AR5`), Doing Business `IC.BUS.EASE.XQ`, `IC.REG.DURS`, `IC.REG.COST.PC.ZS`, `IC.TAX.TOTL.CP.ZS` (discontinued 2021). Sparse series: `FR.INR.LEND` / `FR.INR.RINR` / `FR.INR.DPST` (IMF coverage, no KZ; DPST no US), `SI.POV.*`, `SE.ADT.LITR.ZS`, `LP.LPI.OVRL.XQ` (survey years only) — use `mrnev` for these.

#### Regions, income levels, lending types

| Region | Income level | Lending type |
|---|---|---|
| `EAS` East Asia & Pacific | `HIC` High income | `IBD` IBRD |
| `ECS` Europe & Central Asia | `UMC` Upper middle income | `IDX` IDA |
| `LCN` Latin America & Caribbean | `LMC` Lower middle income | `IDB` Blend |
| `MEA` Middle East, North Africa, Afghanistan & Pakistan | `LIC` Low income | `LNX` Not classified |
| `NAC` North America | | |
| `SAS` South Asia | | |
| `SSF` Sub-Saharan Africa | | |

#### Common aggregate codes (usable in `countries`)

`WLD` World · `HIC` `UMC` `LMC` `LIC` `MIC` `LMY` income groups · `OED` OECD · `EUU` European Union · `EMU` Euro area · `ARB` Arab World · `EAS` `ECS` `LCN` `MEA` `NAC` `SAS` `SSF` regions · `ECA` `EAP` `LAC` `MNA` `SSA` regions excl. high income · `CEB` Central Europe & Baltics · `LDC` least developed · `HPC` HIPC · `SST` small states · `IDA` `IBD` lending groups. All 78 aggregates: `{"mode":"countries","region":"NA"}`.

#### Topics (`topic` for indicator search)

1 Agriculture & Rural Development · 2 Aid Effectiveness · 3 Economy & Growth · 4 Education · 5 Energy & Mining · 6 Environment · 7 Financial Sector · 8 Health · 9 Infrastructure · 10 Social Protection & Labor · 11 Poverty · 12 Private Sector · 13 Public Sector · 14 Science & Technology · 15 Social Development · 16 Urban Development · 17 Gender · 18 MDGs · 19 Climate Change · 20 External Debt · 21 Trade

#### Most useful sources (`source`)

| id | Database | Frequency |
|---|---|---|
| 2 | World Development Indicators (default) | annual |
| 3 | Worldwide Governance Indicators | annual |
| 6 | International Debt Statistics | annual |
| 14 | Gender Statistics | annual |
| 15 | Global Economic Monitor (CPI, IP, FX, stock indices…) | monthly / quarterly |
| 16 | Health Nutrition and Population Statistics | annual |
| 20 / 22 / 23 | Quarterly Public Sector Debt / External Debt (SDDS, GDDS) | quarterly |
| 27 | Global Economic Prospects (forecasts) | annual |
| 28 | Global Findex | survey years |
| 31 | CPIA | annual |
| 46 | Sustainable Development Goals | annual |
| 66 | Logistics Performance Index | survey years |
| 75 | ESG Data | annual |

Full list of 71 databases: `{"mode":"sources"}`. Indicator codes differ per source — find them with `{"mode":"indicators","source":15,"query":"cpi"}`.

### Examples

**Default — macro snapshot of three countries, last 5 years** (74 rows)

```json
{ "countries": ["KZ", "US", "CN"] }
```

**Central Asia trade table 2015–2025, one row per country × year** (55 rows, 8 indicator columns)

```json
{ "countries": ["KZ", "UZ", "KG", "TJ", "TM"], "indicatorPreset": "trade", "startYear": 2015, "endYear": 2025, "wide": true }
```

**World ranking of GDP per capita with YoY change** (~214 economies with data; add `"includeAggregates": true` for ~47 more rows of World/regional/income-group aggregates, flagged `isAggregate: true`)

```json
{ "mode": "latest", "countries": ["all"], "indicators": ["NY.GDP.PCAP.CD"], "maxItems": 300 }
```

**Upper-middle-income Europe & Central Asia — digital market sizing, latest non-empty values**

```json
{ "mode": "latest", "region": "ECS", "incomeLevel": "UMC", "indicatorPreset": "digital" }
```

**Sparse series done right — poverty & Gini, 3 most recent available observations**

```json
{ "countries": ["KZ", "UZ", "IN", "BR"], "indicators": ["SI.POV.GINI", "SI.POV.DDAY"], "mrnev": 3 }
```

**Monthly CPI from the Global Economic Monitor with month-over-month change**

```json
{ "countries": ["US", "KZ", "TR"], "indicators": ["CPTOTNSXN"], "source": 15, "frequency": "M", "years": 24, "includeChange": true }
```

**Find indicators about inflation, read one definition**

```json
{ "mode": "indicators", "query": "inflation", "maxItems": 20 }
{ "mode": "indicatorMeta", "indicators": ["FP.CPI.TOTL.ZG", "NY.GDP.DEFL.KD.ZG"] }
```

### Output

Data row (`mode: data`):

```json
{
  "id": "KAZ:NY.GDP.MKTP.CD:2025",
  "country": "Kazakhstan",
  "countryCode": "KAZ",
  "countryIso2": "KZ",
  "indicator": "NY.GDP.MKTP.CD",
  "indicatorName": "GDP (current US$)",
  "year": 2025,
  "period": "2025",
  "value": 306239209650.024,
  "unit": "current US$",
  "obsStatus": null,
  "decimal": 0,
  "source": "World Development Indicators",
  "sourceId": "2",
  "lastUpdated": "2026-07-13",
  "fetchedAt": "2026-09-12T23:40:59.004Z",
  "sourceUrl": "https://api.worldbank.org/v2/country/KAZ;USA;CHN/indicator/NY.GDP.MKTP.CD?format=json&mrv=5&source=2&per_page=1000&page=1"
}
```

| Field | Description |
|---|---|
| `id` | `ISO3:indicator:period` (stable) |
| `country`, `countryCode`, `countryIso2` | Name, ISO3, ISO2 |
| `isAggregate` | `true` for World/regional/income-group/lending-group aggregates (region "Aggregates" in the World Bank country metadata) — filter on it instead of on names |
| `indicator`, `indicatorName` | Code and official name |
| `year`, `period` | Year (number) and raw period (`2025`, `2026M07`, `2024Q3`) |
| `value` | Number or `null` (only with `includeNulls`) |
| `unit` | From the built-in dictionary, else parsed from the name, else `null` |
| `obsStatus`, `decimal` | API observation status (e.g. `E` estimate) and suggested decimals |
| `source`, `sourceId`, `lastUpdated` | Database name/id and its last update date |
| `yoyChangePct`, `previousYear`, `previousValue` | With `includeChange` — % change vs previous non-null period of the same series |
| `fetchedAt`, `sourceUrl` | Fetch time and the exact API URL |

`mode: latest` rows: `country, countryCode, countryIso2, indicator, indicatorName, unit, latestYear, latestPeriod, latestValue, previousYear, previousValue, yoyChangePct, source, isAggregate, fetchedAt, sourceUrl`.
`wide: true` rows: `id (ISO3:period), country, countryCode, countryIso2, year, period, isAggregate, <indicator code>: value…, fetchedAt, sourceUrl`.
`mode: indicators` / `indicatorMeta`: `indicator, indicatorName, unit, sourceId, source, topics, topicIds, sourceNote, sourceOrganization, inDictionary` (+ `dictionaryNote`).
`mode: countries`: `countryCode, countryIso2, country, isAggregate, region, regionName, adminRegion, incomeLevel, incomeLevelName, lendingType, lendingTypeName, capitalCity, latitude, longitude`.
`mode: sources`: `sourceId, code, name, lastUpdated, dataAvailability, metadataAvailability`.
Every row also has `id`, `fetchedAt` and `sourceUrl`. With `fields`, a row keeps `id` plus the listed columns in your order, e.g. `"fields": ["country", "year", "value"]` → `{ "id": …, "country": …, "year": …, "value": … }`.

Problems are not dataset rows (every row is charged): the `SUMMARY` record in the key-value store lists `errors` (`[{ "input": "FOO.BAR", "error": "World Bank API error 120 Invalid value: …" }]`, `{ "input": "Kazakstan", "error": "Unknown country \"Kazakstan\" (did you mean KAZ Kazakhstan?) …" }`), `errorCount`, `notFound` (indicators with no data for the selection, unknown indicator codes in `indicatorMeta`), `notFoundCount`, `indicatorsNotRead` / `indicatorsReadInPart` (a stop at `maxItems`, at your spending limit or before the run timeout), `warnings` and the run counts (`delivered`, `stoppedBy`). The status message sums them up and each is logged as a warning. The run does not fail because of one bad code — only when nothing could be fetched at all.

### Use it from code / agents

```bash
curl -X POST "https://api.apify.com/v2/acts/yadroo~world-bank-indicators/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"mode":"latest","countries":["KZ","UZ","KG"],"indicatorPreset":"macro"}'
```

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('yadroo/world-bank-indicators').call({
    countries: ['KZ', 'US', 'CN'], indicators: ['NY.GDP.MKTP.KD.ZG'], startYear: 2010, endYear: 2025, includeChange: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

```python
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("yadroo/world-bank-indicators").call(run_input={
    "mode": "latest", "countries": ["all"], "indicators": ["SP.POP.TOTL"], "maxItems": 300})
items = client.dataset(run["defaultDatasetId"]).list_items().items
```

MCP: add `https://mcp.apify.com` to your agent (Claude, Cursor, custom) and call the `yadroo/world-bank-indicators` tool with the same JSON input — the input schema descriptions are written for agents.

### Pricing

Pay-per-event: **$0.001 per run start + $0.0005 per dataset item**.

| Run | Items | Cost |
|---|---|---|
| Default (3 countries × 5 indicators × 5 years) | 74 | ≈ $0.038 |
| Trade table, 5 countries × 11 years, wide | 55 | ≈ $0.029 |
| World ranking, 1 indicator, `latest` | ~214 | ≈ $0.108 |
| All countries × 5 indicators × 5 years | ~6,600 | ≈ $3.30 |

Store discounts: Bronze −10 %, Silver −20 %, Gold and above −30 % on the row price; the start event is the same on every plan; platform usage is included. Unknown codes and indicators without data are never rows, so they cost nothing. Use `wide`/`latest` to get more information per row.

Your **Maximum cost per run** is respected: the run stops at it and ends with "Stopped at your spending limit: N rows delivered" (the indicators left unread are named in `SUMMARY`).

### Limits & FAQ

- **Rate limits / politeness** — one request per indicator (per 60-country batch, per 1,000-row page) with a 250 ms pause, up to 3 attempts with backoff on 429/5xx/timeouts (Retry-After honoured). The World Bank API is free and public; a typical run is 1–15 requests.
- **Freshness** — WDI is refreshed a few times a year (the `lastUpdated` field tells you when); GEM (source 15) monthly. Data is not real time — for FX use our fx-rates actor, for yields us-treasury-yields.
- **Empty results** — nulls are dropped by default, so a country with no data simply produces no rows; an indicator with no rows at all is listed in `SUMMARY.notFound` (free, not a dataset row). Use `mrnev` for sparse series, `includeNulls: true` to see the gaps.
- **Invalid codes** — invalid indicator → the API error is logged and listed in `SUMMARY.errors`; unknown country → validated locally against the live country list (the API would silently drop it) and reported the same way with a "did you mean" (never swapped for another country). Neither costs anything.
- **`years` vs `startYear` vs `mrnev`** — the API accepts only one; the actor picks range > mrnev > years and warns about the ignored ones. `mode: latest` takes the latest non-empty value of each series (with `startYear`/`endYear`: the latest inside that range) and warns when `years` or `mrnev` are set.
- **maxItems** — counts final dataset rows. Rows are saved as they arrive (per API page in `mode: data`, per indicator in `mode: latest` or with `includeChange`), and reading stops once `maxItems` rows are saved — nothing is fetched ahead; the indicators left unread are named in the status and `SUMMARY.indicatorsNotRead`. `wide` tables need every indicator, so they are saved after the last one.
- **Run timeout** — a run near its timeout stops starting new requests, saves what it has read and ends SUCCEEDED with "Stopped before the run timeout: N rows saved". A typical run takes seconds; `all` × 10 indicators × 60 years is ~170 requests (a few minutes).
- **Memory** — 256 MB is enough; `all` × many indicators × 60 years can be tens of thousands of rows — raise `maxItems` and expect a longer run.
- **Licence** — World Bank Open Data, CC BY 4.0; cite "World Bank, World Development Indicators".
- **Roadmap** — per-capita/ratio calculators across two indicators, CAGR over the range, CSV-friendly column naming for `wide`.

***

Made by **Yadroo**. Pairs with [fx-rates](https://apify.com/yadroo/fx-rates), [us-treasury-yields](https://apify.com/yadroo/us-treasury-yields), [sec-company-financials](https://apify.com/yadroo/sec-company-financials), [sec-edgar-filings](https://apify.com/yadroo/sec-edgar-filings), [public-holidays](https://apify.com/yadroo/public-holidays), [openalex-works](https://apify.com/yadroo/openalex-works) and [wikipedia-search](https://apify.com/yadroo/wikipedia-search).

# Actor input Schema

## `mode` (type: `string`):

What to fetch. `data` = country × indicator × year rows (default). `latest` = one row per country × indicator with latestYear/latestValue/previousValue/yoyChangePct (cheap country ranking tables): the latest non-empty value of each series, or the latest inside startYear/endYear when they are set (`years` and `mrnev` do not apply to it). `indicators` = search the catalogue with `query`/`topic` (the API has no text search, the actor filters the list of `source` locally). `countries` = metadata of all 200+ economies and 78 aggregates, filterable by region/incomeLevel/lendingType. `sources` = the ~70 World Bank databases with ids (use the id in `source`). `indicatorMeta` = sourceNote/organization/topics for each code in `indicators`.

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

Required for data/latest modes (unless region/incomeLevel/lendingType is set). Accepts ISO2 (KZ), ISO3 (KAZ), English names ("Kazakhstan"), the keyword `all` (every economy; the World/regional/income-group aggregates only with includeAggregates), and aggregate codes: WLD World, EUU European Union, EMU Euro area, OED OECD, HIC/UMC/LMC/LIC income groups, ECS Europe & Central Asia, EAS East Asia & Pacific, LCN Latin America, MEA Middle East & North Africa, NAC North America, SAS South Asia, SSF Sub-Saharan Africa, ARB Arab World, CEB Central Europe & Baltics. Case, accents, spaces and punctuation do not matter. An unknown value is never a dataset row (nothing is billed for it): it is listed in SUMMARY.errors with a "did you mean" hint and the run goes on with the other countries; when no value is known, the run stops with that message. Run mode `countries` for the full list.

## `indicators` (type: `array`):

World Bank indicator codes (any of the ~16,000 WDI codes or codes from another `source`). Empty = the `indicatorPreset` set (default macro: GDP, GDP per capita, CPI inflation, population, unemployment). Common codes: NY.GDP.MKTP.KD.ZG GDP growth %, NY.GDP.PCAP.PP.CD GDP per capita PPP, NE.EXP.GNFS.ZS exports % GDP, BX.KLT.DINV.CD.WD FDI inflows US$, GC.DOD.TOTL.GD.ZS government debt % GDP, IT.NET.USER.ZS internet users %, SP.DYN.LE00.IN life expectancy, SI.POV.GINI Gini, EN.GHG.CO2.PC.CE.AR5 CO2 per capita. Find more with mode `indicators` + `query`. Note: old CO2 codes EN.ATM.CO2E.\* and Doing Business codes (IC.BUS.EASE.XQ, IC.REG.DURS…) are archived and return no data.

## `indicatorPreset` (type: `string`):

Ready-made indicator bundles (6–10 verified codes each). Used only when `indicators` is empty. `custom`/empty `indicators` = macro set (backward compatible).

## `years` (type: `integer`):

Most recent N periods per series (API `mrv`). Default 5. Ignored when startYear/endYear or mrnev is set, and in mode `latest`.

## `startYear` (type: `integer`):

First year of an explicit range (API `date=start:end`). Together with endYear replaces `years`; in mode `latest` the latest value inside the range is returned. Data generally starts in 1960.

## `endYear` (type: `integer`):

Last year of the explicit range. Default = current year when only startYear is given.

## `mrnev` (type: `integer`):

Return the N most recent NON-NULL observations per country (skips years with missing data — ideal for sparse series like Gini, poverty, literacy). Replaces `years`. Not used by mode `latest`, which always takes the two most recent non-empty values (latest + previous).

## `gapfill` (type: `boolean`):

With `years` (mrv) only: the API fills missing years with the last available value (API `gapfill=Y`). Values then carry obsStatus from the source; use with care.

## `frequency` (type: `string`):

Only a few databases are sub-annual: source 15 Global Economic Monitor (monthly CPI, industrial production, exchange rates, e.g. CPTOTNSXN with frequency M), sources 20/22/23 quarterly debt statistics. WDI (source 2) is annual only — a warning is logged if you ask for Q/M there. Periods come back as `2026M07` / `2024Q3` in `period`, `year` holds the year.

## `source` (type: `integer`):

World Bank database id. 2 = World Development Indicators (default, 1,500 indicators). Others: 3 Worldwide Governance Indicators, 6 International Debt Statistics, 14 Gender Statistics, 15 Global Economic Monitor (monthly), 16 Health Nutrition & Population, 20 Quarterly Public Sector Debt, 27 Global Economic Prospects, 28 Global Findex, 31 CPIA, 46 SDGs, 66 Logistics Performance Index, 75 ESG. Full list: mode `sources`. Also scopes mode `indicators` search.

## `includeNulls` (type: `boolean`):

Keep rows whose value is null (years without data). Default false — nulls are dropped, so a country with no data yields no rows (an indicator with no data at all is listed in SUMMARY.notFound — not a dataset row, not billed). Mode `latest` always skips empty values.

## `includeChange` (type: `boolean`):

Data mode: add `yoyChangePct`, `previousYear`, `previousValue` to every row, computed against the previous non-null observation of the same country × indicator series (needs ≥2 periods). Mode `latest` always includes it.

## `wide` (type: `boolean`):

Data mode: pivot indicators into columns — one row per country × period with indicator codes as keys (missing = null). Handy for comparison tables of several countries across several indicators. Not combined with includeChange columns. Rows are saved after the last indicator is read; an indicator a stop left unread gets no column (it is listed in SUMMARY.indicatorsNotRead).

## `fields` (type: `array`):

Keep only these columns, in this order (`id` is always kept and comes first unless you list it elsewhere). Empty = every column. The columns of each mode are listed in README → Output; with `wide`, indicator codes are columns too. Case, spaces, '\_' and '-' do not matter. A name that is not a column of the chosen mode is skipped and named in the status and SUMMARY.warnings (with a "did you mean" for near misses); when none of the names is a column, the run stops before any request with the list of valid columns.

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

Stop after this many dataset rows (after shaping). Rows are saved as they arrive: per API page (1,000 rows) in mode data, per indicator in mode latest or with includeChange, and after the last indicator with wide. Reading stops once maxItems rows are saved — the indicators left unread are named in the status and SUMMARY. Default 1000. A full `all` × 1 indicator × 1 year query is ~265 rows; `all` × 5 indicators × 5 years ≈ 6,600 rows.

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

Mode `indicators`: words to match (all terms, case-insensitive) in indicator id, name or definition, e.g. "inflation", "gdp per capita ppp", "female labor". Results ranked: exact code, name hits, WDI, dictionary codes first. Empty query + topic = browse a topic.

## `topic` (type: `string`):

Mode `indicators`: restrict search to one World Bank topic id (topics are assigned mainly to WDI indicators).

## `searchAllSources` (type: `boolean`):

Mode `indicators`: search the full catalogue of ~29,500 indicators across all ~70 databases (15 paged requests) instead of only the database given in `source` (default WDI, 1 request).

## `region` (type: `string`):

Select economies by World Bank region. In modes data/latest with empty `countries` (or `countries: ["all"]`) it defines which countries are queried; in mode `countries` it filters the metadata list.

## `incomeLevel` (type: `string`):

Select economies by World Bank income classification (same behaviour as `region`). Combine with region, e.g. ECS + UMC.

## `lendingType` (type: `string`):

Select economies by World Bank lending category (same behaviour as `region`).

## `includeAggregates` (type: `boolean`):

Also include the aggregate economies (World, EU, income groups, regions — region "Aggregates" in the World Bank country metadata) in `countries: ["all"]`, mode `countries` and region/income selections. Aggregate codes listed explicitly (WLD, EUU…) are always returned. Every data row carries `isAggregate`. Default false = real economies only.

## Actor input object example

```json
{
  "mode": "data",
  "countries": [
    "KZ",
    "US",
    "CN"
  ],
  "indicators": [
    "NY.GDP.MKTP.CD",
    "NY.GDP.PCAP.CD",
    "FP.CPI.TOTL.ZG",
    "SP.POP.TOTL",
    "SL.UEM.TOTL.ZS"
  ],
  "indicatorPreset": "custom",
  "years": 5,
  "gapfill": false,
  "frequency": "Y",
  "source": 2,
  "includeNulls": false,
  "includeChange": false,
  "wide": false,
  "maxItems": 1000,
  "searchAllSources": false,
  "includeAggregates": false
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "countries": [
        "KZ",
        "US",
        "CN"
    ],
    "indicators": [
        "NY.GDP.MKTP.CD",
        "NY.GDP.PCAP.CD",
        "FP.CPI.TOTL.ZG",
        "SP.POP.TOTL",
        "SL.UEM.TOTL.ZS"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("yadroo/world-bank-indicators").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": [
        "KZ",
        "US",
        "CN",
    ],
    "indicators": [
        "NY.GDP.MKTP.CD",
        "NY.GDP.PCAP.CD",
        "FP.CPI.TOTL.ZG",
        "SP.POP.TOTL",
        "SL.UEM.TOTL.ZS",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("yadroo/world-bank-indicators").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": [
    "KZ",
    "US",
    "CN"
  ],
  "indicators": [
    "NY.GDP.MKTP.CD",
    "NY.GDP.PCAP.CD",
    "FP.CPI.TOTL.ZG",
    "SP.POP.TOTL",
    "SL.UEM.TOTL.ZS"
  ]
}' |
apify call yadroo/world-bank-indicators --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,yadroo/world-bank-indicators"
        }
    }
}
```

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/FcswZLO5FCzHAEtBB/builds/zjw8tK4lkRgDtASXc/openapi.json
