Open meteo api
Claude Code skill for the free Open-Meteo API — weather forecasts, current conditions, historical weather, and air quality, no API key required
npx -y skills add NanookAI/open-meteo-api --skill open-meteo-apiAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Fetch weather forecasts, current conditions, historical weather, and air quality with the free Open-Meteo API (no API key). Use for any weather, temperature, rain, wind, UV, sunrise/sunset, air quality, or climate data task, even if Open-Meteo isn't mentioned.
SKILL.md
9.9 KB, as published. Nobody here has run it
Open-Meteo API
Open-Meteo is a free, open-source weather API. No API key, no signup for non-commercial use (fair-use limit ~10,000 requests/day). It blends national weather models (NOAA GFS, DWD ICON, ECMWF, Météo-France, JMA...) and auto-selects the best model per location.
Fastest path: bundled script
For the common case — current conditions and a daily forecast for a place — run the bundled zero-dependency script (Python 3.8+, stdlib only) instead of composing API calls by hand:
python3 scripts/get_weather.py "Taipei" # current + 3-day forecast
python3 scripts/get_weather.py "Paris" --country FR # disambiguate place name
python3 scripts/get_weather.py --lat 25.05 --lon 121.53 # skip geocoding
python3 scripts/get_weather.py "Tokyo" --days 7 --json # raw JSON for parsing
python3 scripts/get_weather.py "Denver" --fahrenheit
It geocodes, fetches, and decodes WMO weather codes into readable text. Exit codes: 0 success, 1 place not found, 2 API/network error.
Call the API directly (below) for anything the script doesn't cover: hourly data, specific variables (UV, soil, radiation...), historical weather, air quality, marine, or non-Python environments.
Typical workflow (direct API)
Most user questions name a place, but the API takes coordinates:
- Geocode the place name → latitude/longitude (Geocoding API below). Skip this step if coordinates are already known.
- Fetch weather from the forecast (or other) endpoint.
- Interpret
weather_codeusing the WMO table below.
Quick reference
| Task | Endpoint |
|---|---|
| Forecast / current weather | https://api.open-meteo.com/v1/forecast |
| Place name → coordinates | https://geocoding-api.open-meteo.com/v1/search |
| Historical weather (1940→now) | https://archive-api.open-meteo.com/v1/archive |
| Air quality (PM2.5, AQI, pollen) | https://air-quality-api.open-meteo.com/v1/air-quality |
| Marine (waves, sea temp) | https://marine-api.open-meteo.com/v1/marine |
| Elevation lookup | https://api.open-meteo.com/v1/elevation |
All endpoints: GET with query parameters, JSON responses, HTTPS, CORS enabled.
See references/other-apis.md for historical/air-quality/marine/elevation/flood/climate details.
Forecast API
GET https://api.open-meteo.com/v1/forecast
Key parameters:
| Parameter | Meaning |
|---|---|
latitude, longitude | Required. WGS84 decimal degrees. |
current | Comma-separated variables for current conditions |
hourly | Comma-separated hourly variables |
daily | Comma-separated daily aggregations (requires timezone) |
timezone | auto (recommended — resolves from coordinates) or IANA name like Asia/Taipei. Default is GMT. |
forecast_days | 0–16 (default 7) |
past_days | 0–92 — include recent past days in the same response |
start_date, end_date | YYYY-MM-DD, alternative to forecast_days/past_days |
temperature_unit | celsius (default) or fahrenheit |
wind_speed_unit | kmh (default), ms, mph, kn |
precipitation_unit | mm (default) or inch |
Most-used variables (full list in references/weather-variables.md):
- current:
temperature_2m,relative_humidity_2m,apparent_temperature,precipitation,weather_code,wind_speed_10m,wind_direction_10m,is_day - hourly:
temperature_2m,precipitation_probability,precipitation,weather_code,wind_speed_10m,relative_humidity_2m,cloud_cover,uv_index - daily:
weather_code,temperature_2m_max,temperature_2m_min,precipitation_sum,precipitation_probability_max,sunrise,sunset,uv_index_max,wind_speed_10m_max
Example: current weather
GET https://api.open-meteo.com/v1/forecast?latitude=25.05&longitude=121.53
¤t=temperature_2m,relative_humidity_2m,apparent_temperature,precipitation,weather_code,wind_speed_10m
&timezone=auto
{
"latitude": 25.06, "longitude": 121.52,
"timezone": "Asia/Taipei", "utc_offset_seconds": 28800, "elevation": 12.0,
"current_units": {"temperature_2m": "°C", "wind_speed_10m": "km/h", "weather_code": "wmo code"},
"current": {
"time": "2026-07-03T15:00", "interval": 900,
"temperature_2m": 31.8, "relative_humidity_2m": 63,
"apparent_temperature": 37.6, "precipitation": 0.0,
"weather_code": 1, "wind_speed_10m": 5.1
}
}
Example: 3-day daily forecast
GET https://api.open-meteo.com/v1/forecast?latitude=25.05&longitude=121.53
&daily=weather_code,temperature_2m_max,temperature_2m_min,precipitation_sum,precipitation_probability_max,sunrise,sunset
&timezone=auto&forecast_days=3
{
"daily_units": {"temperature_2m_max": "°C", "precipitation_sum": "mm"},
"daily": {
"time": ["2026-07-03", "2026-07-04", "2026-07-05"],
"weather_code": [95, 95, 96],
"temperature_2m_max": [33.6, 33.5, 33.2],
"temperature_2m_min": [26.0, 25.7, 26.1],
"precipitation_sum": [1.5, 4.3, 4.2],
"precipitation_probability_max": [100, 99, 82],
"sunrise": ["2026-07-03T05:08", "..."],
"sunset": ["2026-07-03T18:47", "..."]
}
}
Response shape: hourly/daily data comes as parallel arrays — time[i]
pairs with temperature_2m_max[i]. Units for every requested variable are
echoed in *_units. Timestamps are ISO 8601 in the requested timezone
(local time when timezone=auto), without a UTC offset suffix.
Geocoding API
GET https://geocoding-api.open-meteo.com/v1/search?name=Taipei&count=5&language=en&format=json
Parameters: name (place name, fuzzy for ≥3 chars), count (1–100, default 10),
language (lowercase code: en, zh, ja, de...).
{
"results": [
{
"id": 1668341, "name": "Taipei",
"latitude": 25.05306, "longitude": 121.52639,
"country": "Taiwan", "country_code": "TW",
"admin1": "Taiwan", "timezone": "Asia/Taipei", "population": 7871900
}
]
}
Pick the first result unless the user's context suggests otherwise (check
country/admin1 when names are ambiguous, e.g. Paris TX vs Paris FR; results
are ordered by relevance and population). No results key at all means no
match — retry with a simpler query (city name only, no district/street; the
geocoder matches localities, not addresses).
WMO weather codes
weather_code values (WMO 4677 subset) — condensed table:
| Code | Meaning |
|---|---|
| 0 | Clear sky |
| 1 / 2 / 3 | Mainly clear / partly cloudy / overcast |
| 45 / 48 | Fog / depositing rime fog |
| 51 / 53 / 55 | Drizzle: light / moderate / dense |
| 56 / 57 | Freezing drizzle: light / dense |
| 61 / 63 / 65 | Rain: slight / moderate / heavy |
| 66 / 67 | Freezing rain: light / heavy |
| 71 / 73 / 75 | Snowfall: slight / moderate / heavy |
| 77 | Snow grains |
| 80 / 81 / 82 | Rain showers: slight / moderate / violent |
| 85 / 86 | Snow showers: slight / heavy |
| 95 | Thunderstorm |
| 96 / 99 | Thunderstorm with slight / heavy hail |
Code examples
import requests
def get_weather(place: str) -> dict:
geo = requests.get(
"https://geocoding-api.open-meteo.com/v1/search",
params={"name": place, "count": 1}, timeout=10,
).json()
if "results" not in geo:
raise ValueError(f"Place not found: {place}")
loc = geo["results"][0]
r = requests.get(
"https://api.open-meteo.com/v1/forecast",
params={
"latitude": loc["latitude"], "longitude": loc["longitude"],
"current": "temperature_2m,weather_code,wind_speed_10m",
"daily": "temperature_2m_max,temperature_2m_min,precipitation_probability_max",
"timezone": "auto",
}, timeout=10,
)
r.raise_for_status()
return r.json()
const geo = await (await fetch(
`https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(place)}&count=1`
)).json();
const { latitude, longitude } = geo.results[0];
const weather = await (await fetch(
`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}` +
`¤t=temperature_2m,weather_code&timezone=auto`
)).json();
Errors
Errors return HTTP 400 with {"error": true, "reason": "<message>"} — e.g.
missing longitude, an unknown variable name, or an out-of-range date. Read
reason; it states exactly which parameter is wrong.
Practical tips
- Request only the variables you need — response size and quota cost scale with variable count and day range.
- Always pass
timezone=autowhen usingdaily(required) or showing times to a user; otherwise times are GMT and daily aggregation boundaries are wrong. - "Will it rain?" → prefer
precipitation_probability(hourly) orprecipitation_probability_max(daily) over rawprecipitationamounts. - Yesterday/last week → use
past_dayson the forecast endpoint. Older than ~3 months → use the archive endpoint (seereferences/other-apis.md). Archive data lags real time by ~5 days. - The returned
latitude/longitudeare the model grid cell center (~1–11 km grid), so they differ slightly from the request — that's normal. intervalincurrentis the data refresh interval in seconds; current conditions are model data, not station readings.- Batch multiple locations in one call:
latitude=25.05,24.14&longitude=121.53,120.68returns a JSON array of result objects. - Free tier is non-commercial use only; commercial use needs a paid API key
(
&apikey=oncustomer-prefixed endpoints). No key is needed otherwise.
For the complete variable catalog read references/weather-variables.md;
for historical, air-quality, marine, elevation, flood, climate, and ensemble
endpoints read references/other-apis.md.