API
The app's server function returns NOAA GHCN-Daily records for one station and one date range as CSV, in metric units. It is free and needs a SkillSafe app token for this app.
1. Get a token
The quickest way: sign in and copy your token. Or, in a script, exchange your SkillSafe API key for an app token (valid 30 days). Requests with a guest token are refused.
curl -s -X POST https://api.skillsafe.ai/v1/app-api/authorize \
-H "Authorization: Bearer YOUR_SKILLSAFE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"slug":"weather-history"}'
# -> {"ok":true,"data":{"token":"aut_...","expires_at":"..."}}
import requests
r = requests.post("https://api.skillsafe.ai/v1/app-api/authorize",
headers={"Authorization": "Bearer YOUR_SKILLSAFE_API_KEY"},
json={"slug": "weather-history"})
token = r.json()["data"]["token"]
const r = await fetch("https://api.skillsafe.ai/v1/app-api/authorize", {
method: "POST",
headers: { Authorization: "Bearer YOUR_SKILLSAFE_API_KEY", "Content-Type": "application/json" },
body: JSON.stringify({ slug: "weather-history" }),
});
const token = (await r.json()).data.token;
2. Fetch daily data
GET https://weather-history.skillsafe.ai/api/daily?station=ID&start=YYYY-MM-DD&end=YYYY-MM-DD
station: an 11-character GHCN-Daily id, for exampleUSW00024233(Seattle-Tacoma airport). The app's station list is at stations.json.start,end: dates; at most 40 calendar years per request.- Response:
text/csvwith columnsSTATION, DATEand whichever ofAWND(m/s),PRCP(mm),SNOW(mm),TAVG,TMAX,TMIN(°C) the station reports.
curl -s "https://weather-history.skillsafe.ai/api/daily?station=USW00024233&start=2025-01-01&end=2025-12-31" \ -H "Authorization: Bearer YOUR_APP_TOKEN"
import csv, io, requests
r = requests.get("https://weather-history.skillsafe.ai/api/daily",
params={"station": "USW00024233", "start": "2025-01-01", "end": "2025-12-31"},
headers={"Authorization": "Bearer " + token})
rows = list(csv.DictReader(io.StringIO(r.text)))
const res = await fetch("https://weather-history.skillsafe.ai/api/daily?station=USW00024233&start=2025-01-01&end=2025-12-31",
{ headers: { Authorization: "Bearer " + token } });
const csvText = await res.text();
Errors
| Status | Meaning |
|---|---|
| 400 | bad_station or bad_range: check the id and the dates (40 years at most) |
| 401 | No token, a guest token, or an expired token |
| 429 | NOAA is rate-limiting; wait and retry |
| 502 | NOAA did not answer or answered with an error |
Data: NOAA NCEI GHCN-Daily, Version 3 (Menne et al. 2012, doi:10.7289/V5D21VHZ). Errors come back as {"error":{"code","message"}}.