# Estimate the population of an area

> Index of the TerraLab docs for agents: [llms.txt](https://terra-lab.ai/docs/llms.txt). Every docs page is also served as markdown: add .md to its URL.

A modelled estimate of the people living in a circle, a bounding box, a travel area or an administrative boundary, from the GHS-POP 2025 grid.

| | |
| --- | --- |
| REST | `POST https://mcp.terra-lab.ai/v1/tools/estimate_population` |
| MCP tool | `estimate_population` on `https://mcp.terra-lab.ai/mcp` |
| Group | Imagery and land |

## Request

```bash
curl -X POST https://mcp.terra-lab.ai/v1/tools/estimate_population \
  -H "Authorization: Bearer $TERRALAB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"area":{"place":"Gare de Lyon Part-Dieu","radius_m":1000}}'
```

```python
import os
import requests

response = requests.post(
    "https://mcp.terra-lab.ai/v1/tools/estimate_population",
    headers={"Authorization": f"Bearer {os.environ['TERRALAB_API_KEY']}"},
    json={
        "area": {
            "place": "Gare de Lyon Part-Dieu",
            "radius_m": 1000,
        },
    },
    timeout=120,
)
response.raise_for_status()
print(response.json()["structuredContent"])
```

```javascript
const response = await fetch('https://mcp.terra-lab.ai/v1/tools/estimate_population', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.TERRALAB_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "area": {
      "place": "Gare de Lyon Part-Dieu",
      "radius_m": 1000
    }
  }),
});
const data = await response.json();
console.log(data.structuredContent);
```

Other valid request bodies:

```json
{"travel":{"start":"Nairobi Central railway station","minutes":15,"mode":"walk"}}
```

```json
{"area":{"place":"Villeurbanne","level":"municipality"}}
```

## Parameters

A JSON object in the request body; in an MCP client, the arguments of the tool call.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `area` | object | No | The area: a bbox, or a place (name, address or coordinates) with an optional radius in metres. The place the user asks about, not the user's own location. |
| `area.bbox` | array of number | No | [west, south, east, north] in decimal degrees (WGS 84). Exactly 4 items. |
| `area.place` | string or object | No | A place name or address, or a point. |
| `area.radius_m` | number | No | Radius around the place in metres. From 1 to 100000. |
| `area.level` | string | No | With a place and no radius: use its administrative boundary at this level (Overture divisions). One of `"country"`, `"region"`, `"county"`, `"municipality"`. |
| `travel` | object | No | The area reachable from a start along the roads (Valhalla on the OpenStreetMap network), instead of area. |
| `travel.start` | string or object | No |  |
| `travel.minutes` | number | No | At most 120. |
| `travel.km` | number | No | At most 200. |
| `travel.mode` | string | No | One of `"walk"`, `"drive"`, `"bike"`. Default `"walk"`. |
| `source` | string | No | ghs_pop: GHS-POP 2025, 100 m. worldpop_1km: WorldPop, 1 km, to compare. One of `"ghs_pop"`, `"worldpop_1km"`. Default `"ghs_pop"`. |

## Response

`structuredContent` holds the result, `content` the same result as text for a model, and `isError` is `true` when the tool refused the request or failed; then `structuredContent.code`, `message` and `hint` say what to change.

```json
{
  "structuredContent": {
    "sources": [{ "name": "...", "licence": "...", "url": "..." }],
    "downloads": [{ "label": "...", "format": "...", "url": "...", "name": "..." }]
  },
  "content": [{ "type": "text", "text": "..." }],
  "isError": false
}
```

Every result lists its `sources` with their licence. File results come as `downloads`: each link builds its file when opened.

## Errors

A missing key answers `401`, an empty balance `402`, too many calls `429`. A call that fails or finds nothing is not counted. See [Errors and rate limits](https://terra-lab.ai/docs/errors).

## Description for agents

The text the server gives an agent to decide when to call this tool:

> Use this when the user asks how many people live in an area: "how many people live within 1 km of Lyon Part-Dieu?", "within 15 minutes' walk of Nairobi Central station", "population of the commune of Villeurbanne". Give exactly one of: area with a place and radius_m (a circle) or a bbox; area with a place and level (municipality, county, region, country) for its administrative boundary; or travel (start, minutes or km, mode walk, drive or bike) for the area reachable along the roads. Sums the GHS-POP 2025 grid (100 m cells, EC JRC, CC BY 4.0) over the polygon, or worldpop_1km with source. Returns the population rounded to 10, the density per km², the area, and the polygon used as a GeoPackage. This is a modelled estimate from satellite-derived built-up areas and census totals, not a census count: say so, and never present it as an official figure. Limits: 50,000 km² per call; travel at most 120 minutes or 200 km. Never use the user's current location unless they type it. Download links build their file when opened; no file is saved. Never pass these links to open_gis_file.


Source: https://terra-lab.ai/docs/api/estimate_population · Updated 2026-10-27
