Search API¶
Search API for accessing Our World in Data charts and content pages powered by Algolia.
This API allows you to search through:
- Charts: Interactive data visualizations with country-specific filtering
- Pages: Articles, data insights, and other content pages (filter by type via
pageTypes) - Topics: The topic pages to recommend for a query, as on the site's search page
Semantic Search
We also offer semantic search for indicators via the Semantic Search API. This allows natural language queries like "deaths from air pollution" to find relevant indicators.
API Information
Version: 0.1.0
Base URL: https://ourworldindata.org/api — Site API
License: CC BY 4.0
GET /search¶
Search for charts, pages or topics
Search through Our World in Data's collection of charts and pages.
- For chart search: Filter by countries, topics, and entity availability
- For page search: Find articles, research papers, and informational content
- For topic recommendations: Find the topic pages a query is about
Parameters not listed below are ignored, and named in the response's
warnings field (except utm_* tracking tags). So are parameters the
chosen type doesn't read, such as pageTypes with type=topics or
topics with type=pages. In particular, the
search page's resultType parameter isn't read here: use type=pages
to search writing.
Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
q |
string | Search query text default: ""Example: population |
|
type |
string (charts, pages, topics) |
Type of content to search. charts and pages are text searches.topics recommends topic pages: with a query, they are the topics ofthe best-ranked charts matching it, weighted by rank, so q=gdpleads with the Economic Growth page. countries, topics andrequireAllCountries apply to that chart search. Without a query,or when no chart matches, topic pages are searched by their own text, filtered by topics; countries andrequireAllCountries don't apply there. Topic pages come in two layouts (aresult's type is topic-page or linear-topic-page), and bothare returned. closestMatches is never set on a topics response.default: chartsExample: charts |
|
page |
integer | Page number for pagination (0-indexed) default: 0 |
|
hitsPerPage |
integer | Number of results per page default: 20 |
|
countries |
string | Country names separated by ~ (tilde). Only applicable when type=chartsor type=topics.Example: United States~China |
|
topics |
string | Topic name for filtering charts. Only applicable when type=chartsor type=topics.View all available topics Example: Health |
|
requireAllCountries |
boolean | If true, only return charts that include ALL specified countries.Only applicable when type=charts or type=topics and countriesparameter is provided. default: FalseExample: False |
|
pageTypes |
string | Comma-separated list of page content types to search. Only applicable when type=pages. Defaults to article,about-page when omitted.This is a text search whatever types are requested, topic pages included, and each type is matched as named: topic-page andlinear-topic-page are the two layouts of topic page, so ask forboth to get every topic page. To find the topic pages a query is about, use type=topics.default: article,about-pageExample: data-insight |
Responses¶
✅ 200 - Successful search response
Content-Type: application/json
Request: GET https://ourworldindata.org/api/search?q=gdp
Code samples:
{
"query": "gdp",
"results": [
{
"title": "GDP per capita",
"slug": "gdp-per-capita-worldbank",
"subtitle": "GDP per capita is a country's gross domestic product divided by its population. This data is adjusted for inflation and differences in living costs between countries.",
"variantName": "World Bank, constant international-$",
"type": "chart",
"availableEntities": [
"United States",
"China",
"India"
],
"originalAvailableEntities": [
"Bosnia and Herzegovina",
"United States",
"China",
"India"
],
"availableTabs": [
"LineChart",
"Table",
"WorldMap"
],
"publishedAt": "2016-05-03T21:44:14.000Z",
"updatedAt": "2025-12-20T15:23:24.000Z",
"url": "https://ourworldindata.org/grapher/gdp-per-capita-worldbank"
}
],
"nbHits": 360,
"page": 0,
"nbPages": 18,
"hitsPerPage": 20
}
Request: GET https://ourworldindata.org/api/search?q=climate+change&type=pages
Code samples:
{
"query": "climate change",
"results": [
{
"type": "article",
"slug": "climate-change-support",
"title": "More people care about climate change than you think",
"content": "You’ll get more clicks by making people angry at others for disagreeing. “Both sides” debates, for example in talk shows, can also give people the impression that they accurately reflect balance among the public. People think that far more people are opposed to climate action as a result.The debate is now about the merits of different solutions, not whether we should actFor decades, the world debated whether climate change was happening, if humans were causing it, and if we should do something. If you look at levels of concern in the UK since the millennium, for example, you find an interesting decline-then-rise. In the first decade of the 2000s, environmental concerns were very high. In 2005/06, 82% of Brits said they were concerned about “global warming”. This was around the time that Al Gore’s film An Inconvenient Truth was released. The Stern Report on the impacts and economics of climate change was published. And not far ahead of the release of the UK’s Climate Change Act.",
"date": "2024-03-25T10:48:30.000Z",
"modifiedDate": "2024-03-25T10:48:41.000Z",
"thumbnailUrl": "https://ourworldindata.org/cdn-cgi/imagedelivery/qLq-8BTgXU8yG0N6HnOy8g/e5956f18-560f-4639-ad7e-c18553856600/w=512",
"authors": [
"Hannah Ritchie"
],
"url": "https://ourworldindata.org/climate-change-support"
}
],
"nbHits": 104,
"offset": 0,
"length": 20
}
Request: GET https://ourworldindata.org/api/search?q=gdp&type=topics
Code samples:
{
"query": "gdp",
"results": [
{
"type": "topic-page",
"slug": "economic-growth",
"title": "Economic Growth",
"content": "On this page, you can find all our data, visualizations, and writing on the topic.",
"date": "2023-07-14T11:37:00.000Z",
"modifiedDate": "2026-06-19T18:14:04.000Z",
"thumbnailUrl": "https://ourworldindata.org/cdn-cgi/imagedelivery/qLq-8BTgXU8yG0N6HnOy8g/217caa41-002d-4436-52d9-a51501c42300/w=512",
"authors": [
"Max Roser",
"Bertha Rohenkohl"
],
"url": "https://ourworldindata.org/economic-growth"
}
],
"nbHits": 40,
"offset": 0,
"length": 20
}
❌ 400 - Bad request - invalid parameters
Content-Type: application/json
Example:
❌ 500 - Internal server error
Content-Type: application/json
Example:
Schemas¶
ChartSearchResponse¶
Response object for chart search queries, containing search results and pagination metadata.
Properties
| Property | Type | Required | Description |
|---|---|---|---|
query |
string | ✓ | The search query that was executed Example: population |
results |
array[ChartResult] | ✓ | Array of chart search results |
nbHits |
integer | ✓ | Total number of results found. Exception: when closestMatches istrue this is the number of closest matches actually returned, not the number that exist — relaxed results come back as one non-paginated page (see closestMatches).Example: 125 |
page |
integer | ✓ | Current page number (0-indexed) Example: 0 |
nbPages |
integer | ✓ | Total number of pages available Example: 7 |
hitsPerPage |
integer | ✓ | Number of results per page Example: 20 |
closestMatches |
boolean | Present and true when the query itself had no exact match and these results were relaxed (Algolia's removeWordsIfNoResults), keeping only the tier of hits that matched the most query words. Absent for a normal exact-match response. A relaxed response is deliberately a single page: nbPages is 1and nbHits counts only the hits returned, so requesting a smallhitsPerPage/length yields a correspondingly small nbHitseven when more equally-ranked matches exist. Ask for a larger page if you want more of them; do not treat nbHits as a total or pagepast the first page. Example: True |
|
warnings |
array[string] |
Present when the request carried parameters this endpoint doesn't read, or that the chosen type doesn't read. They were ignored;each warning names them, and says which parameters or types they belong to. utm_* tracking tags never produce a warning.Example: Ignored unknown parameter(s): "resultType". Valid parameters: type, q, countries, topics, requireAllCountries, pageTypes, page, hitsPerPage. Use "type=pages" to search writing, "type=topics" for topic pages, or "type=charts" for charts. |
ChartResult¶
Individual chart search result with metadata about the visualization.
Properties
| Property | Type | Required | Description |
|---|---|---|---|
title |
string | ✓ | Chart title Example: Life expectancy at birth |
slug |
string | ✓ | URL-friendly identifier for the chart Example: life-expectancy |
subtitle |
string | Chart subtitle providing additional context Example: Period life expectancy at birth, measured in years |
|
variantName |
string | Name of the chart variant (if applicable) Example: Default |
|
type |
string (chart, explorerView, multiDimView) |
✓ | Type of visualization Example: chart |
queryParams |
string | URL query parameters for explorer or multi-dimensional views Example: tab=chart&time=2020 |
|
availableEntities |
array[string] |
✓ | List of countries/entities available in this chart Example: United States, China, India |
originalAvailableEntities |
array[string] |
Original list of entities before filtering Example: United States, United Kingdom |
|
availableTabs |
array[string (Table,WorldMap,LineChart,ScatterPlot,StackedArea,DiscreteBar,StackedDiscreteBar,SlopeChart,StackedBar,Marimekko)] |
✓ | Available visualization tabs Example: Table, WorldMap, LineChart, ... |
publishedAt |
string (date-time) | Publication date of the chart (ISO 8601 format) Example: 2016-05-03T21:44:14.000Z |
|
updatedAt |
string (date-time) | Last update date of the chart (ISO 8601 format) Example: 2025-12-20T15:23:24.000Z |
|
url |
string (uri) | ✓ | Full URL to access the chart Example: https://ourworldindata.org/grapher/life-expectancy |
PageSearchResponse¶
Response object for page searches (type=pages) and topic recommendations
(type=topics), containing search results and pagination metadata.
closestMatches is never set on a type=topics response.
Properties
| Property | Type | Required | Description |
|---|---|---|---|
query |
string | ✓ | The search query that was executed Example: climate change |
results |
array[PageResult] | ✓ | Array of page search results |
nbHits |
integer | ✓ | Total number of results found. Exception: when closestMatches istrue this is the number of closest matches actually returned, not the number that exist — relaxed results come back as one non-paginated page (see closestMatches).Example: 42 |
offset |
integer | ✓ | Current offset in the result set Example: 0 |
length |
integer | ✓ | Number of results returned Example: 20 |
closestMatches |
boolean | Present and true when the query itself had no exact match and these results were relaxed (Algolia's removeWordsIfNoResults), keeping only the tier of hits that matched the most query words. Absent for a normal exact-match response. A relaxed response is deliberately a single page: nbPages is 1and nbHits counts only the hits returned, so requesting a smallhitsPerPage/length yields a correspondingly small nbHitseven when more equally-ranked matches exist. Ask for a larger page if you want more of them; do not treat nbHits as a total or pagepast the first page. Example: True |
|
warnings |
array[string] |
Present when the request carried parameters this endpoint doesn't read, or that the chosen type doesn't read. They were ignored;each warning names them, and says which parameters or types they belong to. utm_* tracking tags never produce a warning.Example: Ignored unknown parameter(s): "resultType". Valid parameters: type, q, countries, topics, requireAllCountries, pageTypes, page, hitsPerPage. Use "type=pages" to search writing, "type=topics" for topic pages, or "type=charts" for charts. |
PageResult¶
Individual page/article search result with metadata about the content.
Properties
| Property | Type | Required | Description |
|---|---|---|---|
title |
string | ✓ | Page title Example: CO₂ emissions |
slug |
string | ✓ | URL-friendly identifier for the page Example: co2-emissions |
type |
string (article, topic-page, fragment, linear-topic-page, data-insight, homepage, about-page, author, announcement, profile) |
✓ | Type of page content Example: article |
thumbnailUrl |
string (uri) | URL to page thumbnail image Example: https://ourworldindata.org/images/co2-thumbnail.jpg |
|
date |
string (date-time) | Publication of the article (ISO 8601 format) Example: 2024-09-30T08:57:00.000Z |
|
modifiedDate |
string (date-time) | Last update date (ISO 8601 format) Example: 2025-08-21T15:57:34.000Z |
|
content |
string | Excerpt or snippet of page content Example: Carbon dioxide emissions are the primary driver of global climate change... |
|
authors |
array[string] |
List of page authors Example: Hannah Ritchie, Max Roser |
|
url |
string (uri) | ✓ | Full URL to access the page Example: https://ourworldindata.org/co2-emissions |
Error¶
Error response object returned when a request fails.
Properties
| Property | Type | Required | Description |
|---|---|---|---|
error |
string | ✓ | Error type or category Example: Invalid parameter |
message |
string | Detailed error message Example: The 'page' parameter must be between 0 and 1000 |