Weather Data API
Access & limitsPublic, no key needed · Medium▾
Open to everyone. A free API key from your profile raises the limits: send it in an X-API-Key header, or as api_key= in the address.
| 5 minutes | Hour | Day | |
|---|---|---|---|
| Without a key | 10 | 60 | 300 |
| With a key | 30 | 200 | 1,500 |
Log in to create a free key on your profile page.
Every answer carries X-RateLimit-Remaining and X-RateLimit-Reset. Over a limit, the answer is error 429 with retry_after in seconds. Refused requests do not count.
One request returns everything this server holds about the weather for a place and a day: every hour of the NOAA GFS model from the ground to about 31 km, the NOAA GEFS ensemble's spread every 3 hours, and the ground height from our own terrain store. It is the data behind the LoRa expectations check, offered openly for rocketry and anything else it helps with.
lat lon dateParameters
| Parameter | Required | Meaning |
|---|---|---|
lat | Yes | Latitude in decimal degrees, -90 to 90 |
lon | Yes | Longitude in decimal degrees, -180 to 180 (lng also accepted) |
date | Yes | The calendar day where the place is, as YYYY-MM-DD. The answer covers that day's 24 hours in the place's own time zone. GFS is held from 50 days back to 16 days ahead, GEFS from 50 days back to 10 days ahead. |
ensemble | No | members (the default) returns every ensemble member and a summary; summary returns only the summary; none leaves the ensemble out. The full answer is about 800 KB, the summary about 220 KB, none about 180 KB. |
Example
https://www.altimetercloud.com/api/weather/?lat=52.64&lon=-1.50&date=2026-09-18&ensemble=summary
How the answer is laid out
The answer is one JSON object for the whole day. The GFS part is a list of the day's hours, one entry per hour from 00:00 to 23:00 local time, each entry holding that hour's surface weather and its levels from the ground upwards. The GEFS part is a list of the ensemble's times, one entry every 3 hours (00, 03, 06 ... 21 UTC, the ones that fall in the local day), each holding a summary and, if asked for, every member.
{
"success", "date",
"location": { "lat", "lon", "elevation_m", "elevation_ft",
"terrain_has_data", "terrain_tier", "terrain_cell_m",
"timezone", "utc_offset_seconds" },
"gfs": {
"available", "model", "ground_height_used_m",
"hours": [ 24 entries: hours[0] is 00:00 local, hours[23] is 23:00
{
"time_local", "time_utc", "unixtime",
"surface": {
"temperature_c", "relative_humidity_pct", "dew_point_c",
"pressure_msl_hpa", "surface_pressure_hpa", "air_density_kg_m3",
"precipitation_mm", "cloud_cover_pct", "cloud_cover_low_pct", "cloud_cover_mid_pct",
"visibility_m", "cape_j_kg",
"wind_10m": { "speed_ms", "direction_deg", "gust_ms" },
"wind_80m": { "speed_ms", "direction_deg", "temperature_c" },
"wind_100m": { "speed_ms", "direction_deg", "temperature_c" }
},
"levels": [ one entry per pressure level above the ground, lowest first
{ "pressure_hpa", "height_msl_m", "height_agl_m",
"wind_speed_ms", "wind_direction_deg", "temperature_c", "air_density_kg_m3" }
]
}
]
},
"gefs": {
"available", "model", "region", or "available": false with a "reason"
"times": [ 8 entries, one every 3 hours in the day
{
"time_local", "time_utc", "unixtime", "available",
"source", "forecast" (with "run" and "lead_hours") or "history"
"summary": {
"members",
"levels": [ one entry per pressure level above the ground, lowest first
{ "pressure_hpa", "members",
"height_agl_m": { "mean", "sd", "min", "max" },
"wind_speed_ms": { "mean", "sd", "min", "max" },
"wind_direction": { "mean_deg", "spread_deg" },
"temperature_c": { "mean", "sd", "min", "max" } }
],
"wind_10m": { "speed_ms": {...}, "direction": {...}, "gust_ms": {...} },
"wind_80m": { "speed_ms": {...}, "direction": {...} },
"wind_100m": { "speed_ms": {...}, "direction": {...} },
"temperature_2m_c": { "mean", "sd", "min", "max" }
},
"members": [ 31 entries (ensemble=members only): c00, p01 ... p30
{ "member",
"levels": [ { "pressure_hpa", "height_msl_m", "height_agl_m",
"wind_speed_ms", "wind_direction_deg", "temperature_c" } ],
"wind_10m": { "speed_ms", "direction_deg", "gust_ms" },
"wind_80m": { "speed_ms", "direction_deg" },
"wind_100m": { "speed_ms", "direction_deg" },
"temperature_2m_c" }
]
}
]
},
"units": { ... }, "notes": [ ... ], "credits": [ ... ]
}
Reading it
- An hour:
gfs.hours[14]is 14:00 local time. Itstime_utcandunixtimegive the same moment in UTC. - A height: each hour's
levelsrun from the lowest level above the ground upwards, to about 31 km (10 hPa). The number of levels varies with the ground height: levels that would be underground are left out, so pick levels byheight_agl_mrather than by position. The winds at 10, 80 and 100 m are insurface. - The ensemble:
gefs.timesis 3-hourly, so an hour between two of its times sits between two entries. The GEFS levels are the 17 the ensemble carries (1000, 975, 950, 925, 900, 850, 800, 750, 700, 500, 400, 300, 250, 200, 100, 50 and 10 hPa), again only those above the ground. - Missing values are
null. A GEFS time the server does not hold carries only its times and"available": false.
Example: the wind for each hour of the day
// JavaScript
const url = 'https://www.altimetercloud.com/api/weather/?lat=52.64&lon=-1.50&date=2026-09-18&ensemble=none';
const d = await (await fetch(url)).json();
for (const h of d.gfs.hours) {
const w = h.surface.wind_10m;
const km1 = h.levels.find(l => l.height_agl_m >= 1000); // first level at or above 1 km
console.log(h.time_local, w.speed_ms, w.direction_deg, km1 ? km1.wind_speed_ms : null);
}
# Python
import requests
d = requests.get('https://www.altimetercloud.com/api/weather/',
params={'lat': 52.64, 'lon': -1.50, 'date': '2026-09-18', 'ensemble': 'none'}).json()
for h in d['gfs']['hours']:
w = h['surface']['wind_10m']
print(h['time_local'], w['speed_ms'], w['direction_deg'], len(h['levels']), 'levels')
Units: heights in metres, wind in m/s with the direction the wind blows from in degrees true, temperatures in degrees Celsius, pressures in hPa, air density in kg/m3 (dry air). Standard deviations (sd) are across the members; spread_deg is the spread of the members' directions.
{
"success": true,
"date": "2026-09-18",
"location": { "lat": 52.64, "lon": -1.5, "elevation_m": 123.4, "elevation_ft": 404.9,
"terrain_has_data": true, "terrain_tier": "ultra", "terrain_cell_m": 31,
"timezone": "Europe/London", "utc_offset_seconds": 3600 },
"gfs": {
"available": true,
"hours": [
{ "time_local": "2026-09-18T00:00", "time_utc": "2026-09-17T23:00Z",
"surface": { "temperature_c": 11.2, "relative_humidity_pct": 80, "dew_point_c": 9.5,
"surface_pressure_hpa": 1000.1, "air_density_kg_m3": 1.2253,
"wind_10m": { "speed_ms": 4.2, "direction_deg": 245, "gust_ms": 9 }, ... },
"levels": [
{ "pressure_hpa": 975, "height_msl_m": 323.4, "height_agl_m": 200,
"wind_speed_ms": 8.74, "wind_direction_deg": 250.3,
"temperature_c": 12.9, "air_density_kg_m3": 1.18742 }, ... ] }, ... ] },
"gefs": {
"available": true, "region": "Europe",
"times": [
{ "time_utc": "2026-09-18T00:00Z", "source": "forecast", "run": "2026091612", "lead_hours": 36,
"summary": { "members": 31,
"levels": [ { "pressure_hpa": 975,
"wind_speed_ms": { "mean": 3.33, "sd": 1.19, "min": 1.33, "max": 5.33 },
"wind_direction": { "mean_deg": 255.7, "spread_deg": 14.9 }, ... } ] } }, ... ] },
"credits": [ ... ]
}
Errors
Errors come back as "success": false with a code and a message.
| Code | Meaning |
|---|---|
412 | A parameter is missing or not valid |
416 | The date is outside what the server holds; first_date and last_date give the range |
429 | Too many requests from your address, or one still being answered |
If the weather model service is unavailable, the answer still comes back with the ground height and the ensemble, and gfs.available is false with the reason.
Credits you must show
The data is free to use, including commercially, as long as it is credited. Wherever you show it, include:
- GFS: Weather data by Open-Meteo.com, licensed CC BY 4.0, noting that it has been interpolated to the place.
- GEFS: NOAA National Centers for Environmental Prediction, Global Ensemble Forecast System. Do not suggest that NOAA endorses your use.
- Ground height: the terrain data credits at the foot of this page.
These are model values, not observations. Check official forecasts and the conditions on the field before flying.
Try it
Latitude
Longitude
Date (YYYY-MM-DD)
Ensemble (members, summary or none)
Crediting AltimeterCloud
Free to use. If you use this API, or anything made from the answers, in a commercial product or service, credit AltimeterCloud with a link to www.altimetercloud.com at the point of use: on the screen, page or printout where the data appears, for example “Data from AltimeterCloud.com”. Any credits the data's own sources ask for, listed on this page, apply as well.
Terrain data credits
The ground heights come from the Terrain Tiles dataset (Mapzen / Tilezen, on AWS Open Data), reduced into resolution tiers by Altimeter Cloud. Wherever you show heights from this API, credit their sources. Each answer carries a short form of the list below in its credits field.
- ArcticDEM terrain data DEM(s) were created from DigitalGlobe, Inc., imagery and funded under National Science Foundation awards 1043681, 1559691, and 1542736
- Australia terrain data © Commonwealth of Australia (Geoscience Australia) 2017
- Austria terrain data © offene Daten Österreichs – Digitales Geländemodell (DGM) Österreich
- Canada terrain data contains information licensed under the Open Government Licence – Canada
- Europe terrain data produced using Copernicus data and information funded by the European Union - EU-DEM layers
- Global ETOPO1 terrain data U.S. National Oceanic and Atmospheric Administration
- Mexico terrain data source: INEGI, Continental relief, 2016
- New Zealand terrain data Copyright 2011 Crown copyright (c) Land Information New Zealand and the New Zealand Government (All rights reserved)
- Norway terrain data © Kartverket
- United Kingdom terrain data © Environment Agency copyright and/or database right 2015. All rights reserved
- United States 3DEP (formerly NED) and global GMTED2010 and SRTM terrain data courtesy of the U.S. Geological Survey
The licences behind each statement are on the terrain tiles attribution page.



















