API Documentation
A public API is available for testing at api.opentopodata.org.
GET /v1/<dataset_name>
Reads the elevation from a given dataset.
The dataset name must match one of the options in config.yaml.
Multiple datasets can be provided separated by commas: in this case, for each point, each dataset is queried in order until a non-null elevation is found. For more information see Multi datasets.
Latitudes and longitudes should be in EPSG:4326 (also known as WGS-84 format), they will be converted internally to whatever the dataset uses.
Query Args
locations: Required. Eitherlatitutde,longitudepairs, each separated by a pipe character|. Example:locations=12.5,160.2|-10.6,130.- Google polyline format. Example:
locations=gfo}EtohhU.
samples: If provided, instead of usinglocationsdirectly, query elevation forsampleequally-spaced points along the path specified bylocations. Example:samples=5.interpolation: How to interpolate between the points in the dataset. Options:nearest,bilinear,cubic. Default:bilinear.nodata_value: What elevation to return if the dataset has a NODATA value at the requested location. Options:null,nan, or an integer like-9999. Default:null.- The default option
nullmakes NODATA indistinguishable from a location outside the dataset bounds. NaN(not a number) values aren't valid in json and will break some clients. Thenanoption was default before version 1.4 and is provided only for backwards compatibility.- When querying multiple datasets, this NODATA replacement only applies to the last dataset in the stack.
- The default option
format: Eitherjsonorgeojson. Default:json.
Response
A json object, compatible with the Google Maps Elevation API.
status: Will beOKfor a successful request,INVALID_REQUESTfor an input (4xx) error, andSERVER_ERRORfor anything else (5xx). Required.error: Description of what went wrong, whenstatusisn'tOK.results: List of elevations for each location, in same order as input. Only provided forOKstatus.results[].elevation: Elevation, using units and datum from the dataset. Will benullif the given location is outside the dataset bounds. May benullfor NODATA values depending on thenodata_valuequery argument.results[].location.lat: Latitude as parsed by Open Topo Data.results[].location.lng: Longitude as parsed by Open Topo Data.results[].dataset: The name of the dataset which the returned elevation is from.
Some notes about the elevation value:
- If the raster has an integer data type, the interpolated elevation will be rounded to the nearest integer. This is a limitation of rasterio/gdal.
- If the request location isn't covered by any raster in the dataset, Open Topo Data will return
null. - Unless the
nodata_valueparameter is set, anullelevation could either mean the location is outside the dataset bounds, or a NODATA within the raster bounds.
Example
GET api.opentopodata.org/v1/srtm90m?locations=-43.5,172.5|27.6,1.98&interpolation=cubic
{
"results": [
{
"dataset": "srtm90m",
"elevation": 45,
"location": {
"lat": -43.5,
"lng": 172.5
}
},
{
"dataset": "srtm90m",
"elevation": 402,
"location": {
"lat": 27.6,
"lng": 1.98
}
}
],
"status": "OK"
}
GeoJSON response
If format=geojson is passed, you get a FeatureCollection of Point geometries instead. Each feature has its elevation as the z coordinate, and a dataset property specifying the source (corresponding to results[].dataset in the regular json response):
GeoJSON example
GET api.opentopodata.org/v1/srtm90m?locations=-43.5,172.5|27.6,1.98&interpolation=cubic&format=geojson
{
"features": [
{
"geometry": {
"coordinates": [
172.5,
-43.5,
45
],
"type": "Point"
},
"properties": {
"dataset": "srtm90m"
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
1.98,
27.6,
402
],
"type": "Point"
},
"properties": {
"dataset": "srtm90m"
},
"type": "Feature"
}
],
"type": "FeatureCollection"
}
POST /v1/<dataset_name>
When querying many locations in a single request, you can run into issues fitting them all in one url. To avoid these issues, you can also send a POST request to /v1/<dataset_name>.
The arguments are the same, but must be provided either as json-encoded data or form data instead of url query parameters.
The response is the same.
Other solutions for fitting many points in a URL are polyline encoding and rounding your coordinates.
Example
With json:
import requests
url = "https://api.opentopodata.org/v1/srtm90m"
data = {
"locations": "-43.5,172.5|27.6,1.98",
"interpolation": "cubic",
}
response = requests.post(url json=data)
With form data:
import requests
url = "https://api.opentopodata.org/v1/srtm90m"
data = {
"locations": "-43.5,172.5|27.6,1.98",
"interpolation": "cubic",
}
response = requests.post(url data=data)
The response is the same as for GET requests:
{
"results": [
{
"dataset": "srtm90m",
"elevation": 45,
"location": {
"lat": -43.5,
"lng": 172.5
}
},
{
"dataset": "srtm90m",
"elevation": 402,
"location": {
"lat": 27.6,
"lng": 1.98
}
}
],
"status": "OK"
}
GET /health
Healthcheck endpoint, for use with load balancing or monitoring.
Response
A json object.
status: Will beOKfor a successful request.
The status code is 200 if healthy, otherwise 500.
Example
GET api.opentopodata.org/health
GET /datasets
Details of the datasets available on the server.
Response
A json object.
datasets: List of datasets.datasets[].name: Dataset name, used in the elevation query URL.datasets[].child_datasets: If the dataset is a MultiDataset, names of the child datasets. Otherwise, an empty list[].status: Will beOKif the server is running and the config file can be loaded. Otherwise the value will beSERVER_ERROR.