World Bank Indicators Scraper avatar

World Bank Indicators Scraper

Pricing

from $0.84 / 1,000 results

Go to Apify Store
World Bank Indicators Scraper

World Bank Indicators Scraper

Macroeconomic and development data from the World Bank: 29,544 indicators across 217 countries. Flags the 78 aggregate rows the API mixes in with real countries, which otherwise overstate a global total roughly tenfold.

Pricing

from $0.84 / 1,000 results

Rating

0.0

(0)

Developer

Ibnu Adzim

Ibnu Adzim

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Categories

Share

Macroeconomic and development data from the World Bank: 29,544 indicators across 217 countries and 78 aggregates, back to 1960.

Public data. No login, no API key, no WAF.

Input

FieldTypeDefaultMeaning
indicatorsstring[]e.g. NY.GDP.MKTP.CD, SP.POP.TOTL. One request each.
countriesstring[]allISO codes, e.g. USA, IDN.
includeAggregatesbooleanfalseSee below — the setting that matters most.
yearFrom / yearTointegerYear range.
mostRecentValuesintegerLatest N per country. Mutually exclusive with a year range.
skipMissingValuesbooleanfalseGaps stay visible by default.
{ "indicators": ["NY.GDP.MKTP.CD"], "countries": ["IDN","USA"], "mostRecentValues": 5 }

Four things this actor will not let you get wrong

1. 78 of the API's 295 "countries" are aggregates — summing is 10× wrong

/country returns "Arab World", "Africa", "High income", "Euro area" and "World" alongside Argentina and Albania. Measured on 2023 population over country/all:

totalvs the truth
naive sum of every row86,466,868,91110.72×
filtering aggregates by ISO3 code16,102,473,5512.00×
filtering on isAggregate8,039,550,1340.997×
the World row itself8,062,923,4171.00×

The obvious fix — drop rows whose ISO3 code is a known aggregate — still double-counts, exactly 2×. The five income-group aggregates ("High income", "Low income", "Lower middle income", "Upper middle income", "Not classified") come back with a blank countryiso3code, so they slip straight through.

The reliable key is the two-letter country.id, matched against iso2Code in /country where region.id == "NA" marks an aggregate. Every row carries isAggregate; aggregates are excluded by default and counted in the summary when included.

2. Errors arrive as HTTP 200, in an array that is one element short

The response is a two-element array — and it has three shapes:

normal [meta, [rows…]]
valid but empty [meta, null] <- null, not []
INVALID [{"message": []}] <- length 1, and HTTP 200

A bogus indicator or country code is a 200. payload[1] raises IndexError, and guarding with len(payload) > 1 is worse — it turns a rejected query into a silent empty success. One place in this actor (parse_envelope) knows all three, and a rejection becomes an invalid_parameter error row that says the rejection came inside a 200.

3. mostRecentValues is silently dropped by the CDN, intermittently

Asking for mrv=3 on a 66-row series returned 3 rows at almost every page size — but 10 rows at per_page=10, with total reporting 66. The failing responses carried an Age header of several hundred seconds: a cached response computed without mrv. A cache-busting parameter made it apply again, and the same request against other countries worked.

So it is not a rule — it is intermittent, host-dependent and silent, which is worse. mrv is therefore enforced client-side as well as requested, with mrvHonouredUpstream and rowsTrimmedClientSide reporting what happened.

4. The ; multi-indicator syntax silently returns only the first series

/country/USA/indicator/NY.GDP.MKTP.CD;SP.POP.TOTL&source=2 answers HTTP 200 with plenty of rows — all of them GDP. Half the request is discarded with nothing to say so. This actor issues one request per indicator.

Also: missing observations are common, and are not zeros

Tuvalu's GDP series has 10 gaps in 21 years. hasValue is explicit and value stays null, so a gap is never averaged as a zero.

Output

Envelope on every row: _input, _source, _scrapedAt, recordType.

  • OBSERVATION — indicator, country (with region, income level, capital, coordinates), year, value, hasValue, isAggregate, seriesLastUpdated
  • SEARCH_SUMMARYaggregateRowsIncluded vs countryRowsIncluded, rowsWithoutValue, mrvHonouredUpstream, cachedResponses
  • ERROR_error + _errorDetail

If the country/aggregate lookup cannot be loaded, the run stops rather than emitting data that cannot safely be summed.