When to use this skill
When the user asks what the weather was at a specific place on a specific date — temperature, precipitation, snowfall, wind — reach for NOAA NCEI. This is "what actually happened" data from the Global Historical Climatology Network, covering over 100,000 stations worldwide including remote cooperative observer posts in interior Alaska that most weather APIs do not know exist. Not for forecasts, current conditions, or climate normals — those are different NOAA services.
Your best first call
curl "https://www.ncei.noaa.gov/access/services/data/v1?dataset=daily-summaries&stations=USC00200230&startDate=2024-01-01&endDate=2024-01-07&dataTypes=TMAX,TMIN,PRCP&format=json"
No auth. No key. Replace USC00200230 with the GHCN station ID for your location, adjust the date range, and narrow dataTypes to only the variables you need. The response is a JSON array of daily observation objects with these fields:
DATE — observation date
STATION — GHCN station ID (USC prefix = cooperative observer, USW = airport/NWS station)
TMAX, TMIN — daily max/min temperature (tenths of degrees Celsius by default)
PRCP — precipitation (tenths of millimeters by default)
SNOW — snowfall (same units convention)
For human-scale units, add units=metric to the query string — temperatures come back in degrees C and precipitation in mm, no division needed.
Fallbacks (when the best call isn't enough)
- Need CSV output for spreadsheet import → add
format=csv&units=metric to get a compact tabular response in human-scale units.
- Need sub-daily or 15-minute precipitation → change
dataset from daily-summaries to precipitation-15min. Station coverage is much sparser for sub-daily data.
- Need climate normals (what's typical, not what happened) → change
dataset to normals-monthly or normals-daily. These are long-term averages, not actual observations.
Pitfalls
- Default values are in tenths of the unit.
TMIN: "-106" means -10.6°C (about 13°F), not minus 106 degrees. Always divide by 10 unless you pass units=metric. This is the single most common source of absurdly wrong answers from this API.
- JSON values are space-padded strings, not numbers.
" -106" must be trimmed and parsed as an integer before dividing. Raw string arithmetic will silently produce nonsense.
- The default format is CSV, not JSON. Omitting
format=json returns a tabular CSV regardless of Accept headers — an unusual default that catches agents expecting JSON.
dataset is a required parameter with no discoverable default. Omitting it returns an empty response with no error. Use daily-summaries unless you specifically need a different dataset.
One-line summary for the user
I can pull historical daily weather observations — temperature, precipitation, snowfall — from NOAA's GHCN station network by station ID and date range, but default values are in tenths of degrees and millimeters unless I request metric units.
SKILL.md source (frontmatter + body)
---
name: access-real
description: When the user asks about historical weather at a specific place and date — temperature, precipitation, snowfall, wind observations — reach for NOAA NCEI's GHCN station data. Actual observations from 100,000+ stations, no auth needed.
---
## When to use this skill
When the user asks what the weather was at a specific place on a specific date — temperature, precipitation, snowfall, wind — reach for NOAA NCEI. This is "what actually happened" data from the Global Historical Climatology Network, covering over 100,000 stations worldwide including remote cooperative observer posts in interior Alaska that most weather APIs do not know exist. Not for forecasts, current conditions, or climate normals — those are different NOAA services.
## Your best first call
```bash
curl "https://www.ncei.noaa.gov/access/services/data/v1?dataset=daily-summaries&stations=USC00200230&startDate=2024-01-01&endDate=2024-01-07&dataTypes=TMAX,TMIN,PRCP&format=json"
```
No auth. No key. Replace `USC00200230` with the GHCN station ID for your location, adjust the date range, and narrow `dataTypes` to only the variables you need. The response is a JSON array of daily observation objects with these fields:
- `DATE` — observation date
- `STATION` — GHCN station ID (`USC` prefix = cooperative observer, `USW` = airport/NWS station)
- `TMAX`, `TMIN` — daily max/min temperature (tenths of degrees Celsius by default)
- `PRCP` — precipitation (tenths of millimeters by default)
- `SNOW` — snowfall (same units convention)
For human-scale units, add `units=metric` to the query string — temperatures come back in degrees C and precipitation in mm, no division needed.
## Fallbacks (when the best call isn't enough)
- **Need CSV output for spreadsheet import** → add `format=csv&units=metric` to get a compact tabular response in human-scale units.
- **Need sub-daily or 15-minute precipitation** → change `dataset` from `daily-summaries` to `precipitation-15min`. Station coverage is much sparser for sub-daily data.
- **Need climate normals (what's typical, not what happened)** → change `dataset` to `normals-monthly` or `normals-daily`. These are long-term averages, not actual observations.
## Pitfalls
- **Default values are in tenths of the unit.** `TMIN: "-106"` means -10.6°C (about 13°F), not minus 106 degrees. Always divide by 10 unless you pass `units=metric`. This is the single most common source of absurdly wrong answers from this API.
- **JSON values are space-padded strings, not numbers.** `" -106"` must be trimmed and parsed as an integer before dividing. Raw string arithmetic will silently produce nonsense.
- **The default format is CSV, not JSON.** Omitting `format=json` returns a tabular CSV regardless of `Accept` headers — an unusual default that catches agents expecting JSON.
- **`dataset` is a required parameter with no discoverable default.** Omitting it returns an empty response with no error. Use `daily-summaries` unless you specifically need a different dataset.
## One-line summary for the user
I can pull historical daily weather observations — temperature, precipitation, snowfall — from NOAA's GHCN station network by station ID and date range, but default values are in tenths of degrees and millimeters unless I request metric units.