# Satellite image 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 recent Sentinel-2 image of an area in true colour, false colour or NDVI, or an IGN aerial photo in France, as a GeoTIFF.

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

## Request

```bash
curl -X POST https://mcp.terra-lab.ai/v1/tools/get_satellite_image \
  -H "Authorization: Bearer $TERRALAB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"area":{"place":"Annecy, France","radius_m":300}}'
```

```python
import os
import requests

response = requests.post(
    "https://mcp.terra-lab.ai/v1/tools/get_satellite_image",
    headers={"Authorization": f"Bearer {os.environ['TERRALAB_API_KEY']}"},
    json={
        "area": {
            "place": "Annecy, France",
            "radius_m": 300,
        },
    },
    timeout=120,
)
response.raise_for_status()
print(response.json()["structuredContent"])
```

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

Other valid request bodies:

```json
{"area":{"place":"Annecy, France","radius_m":2000},"source":"sentinel2","date_from":"2026-09-01","date_to":"2026-09-30"}
```

```json
{"area":{"place":"Beauce, France","radius_m":3000},"product":"ndvi"}
```

## Parameters

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

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `area` | object | Yes | 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. |
| `source` | string | No | ign_ortho: IGN orthophotos, France only, true colour. sentinel2: Copernicus Sentinel-2, worldwide, 10 m. Default: ign_ortho inside metropolitan France for true colour without a date, sentinel2 otherwise. One of `"sentinel2"`, `"ign_ortho"`. |
| `product` | string | No | Sentinel-2 only. true_color; false_color (B08, B04, B03: vegetation in red); ndvi (float32, NaN where cloud, shadow, snow or no data). One of `"true_color"`, `"false_color"`, `"ndvi"`. Default `"true_color"`. |
| `date` | string | No | Sentinel-2: one day, YYYY-MM-DD. |
| `date_from` | string | No | Sentinel-2: start of the date range, YYYY-MM-DD. Default: 60 days before date_to. |
| `date_to` | string | No | Sentinel-2: end of the date range, YYYY-MM-DD. Default: today. |
| `max_cloud_percent` | number | No | Sentinel-2: highest cloud cover of the whole scene, in percent. From 0 to 100. Default `20`. |

## 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 wants a satellite image or aerial photo of an area as a GIS file: a recent true colour picture, a false colour image, or NDVI to see vegetation, crops or forest health. The area is a bbox, a place, or a place with a radius. Two sources: IGN orthophotos (France only, about 0.5 to 1 m pixels, areas up to 2 x 2 km, radius_m 900 or less; the default inside metropolitan France for true colour) and Copernicus Sentinel-2 L2A (worldwide, 10 m, a scene every few days, areas up to 20 x 20 km, radius_m 9,500 or less; the default elsewhere and for false colour, NDVI or a date). For Sentinel-2 it picks the least cloudy scene covering the whole area in the date range (default: the last 60 days, at most 20 % cloud) and says its date, id and cloud cover. Returns a GeoTIFF in the source's own projected CRS (UTM or Lambert-93) with the licence in the file, and a preview on a map. Not for street-level photos, live weather or a picture more recent than a few days; to explain what NDVI or a band is, answer without this tool. 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/get_satellite_image · Updated 2026-10-27
