Base URL: https://api.wxalerts.org
The National Weather Service’s local storm reports: what an office has confirmed happened, from spotters, emergency managers, the public and automated stations. Each report is a point, a time, the office’s own event wording and, where there is one, a measured or estimated magnitude.
GET /lsr/reports
GET /lsr/reports?hours=24&state=TX,OK
GET /lsr/reports?hours=72&categories=tornado,hail&bbox=-103,33,-94,37
GET /lsr/reports?office=KOUN
No key needed. Browsers block calls from other websites (CORS allows only
wxalerts.org), so call it from a server, script or app. Responses carry Cache-Control: public, max-age=60. Limits
are on the overview.
These are official NWS records, not the unofficial reports people file through wxalerts.org, which are a separate feed.
| parameter | |
|---|---|
hours |
how far back to look, 1 to 72. Default 6 |
bbox |
minLon,minLat,maxLon,maxLat. Only reports inside the box |
categories |
comma separated categories. Case does not matter. An unknown name is a 422, not an empty list |
state |
comma separated two letter states or territories, such as TX,OK or PR. Case does not matter |
office |
comma separated issuing offices, as the four letter ID the product carries: KOUN, PAJK, TJSJ. Case does not matter, but the three letter form (OUN) matches nothing |
Filters combine: a report has to pass every one given.
The window is on valid_at, when the weather happened, not when the report
arrived. Offices often issue a report hours after the event, sometimes the
next morning, so a late report can arrive already outside a short window.
That is deliberate: it describes weather that is over. Ask for a longer
hours to catch up on a day.
Reports come back newest first, as a plain JSON array. There is no paging: a response holds at most 1,000 reports, and past that the oldest in the window are the ones left out.
What a response holds
[
{
"id": 34564,
"valid_at": "2026-11-09T18:41:00Z",
"event": "Flood",
"category": "flood",
"office": "KEWX",
"lat": 29.83,
"lon": -100.4,
"city": "16 N Kickapoo Cavern St",
"county": "Edwards",
"state": "TX",
"source": "Emergency Manager",
"magnitude": null,
"magnitude_unit": null,
"magnitude_method": null,
"magnitude_trace": false,
"remarks": "EM report of water over area roadways in Edwards County including Highway 377 and RR 674 following prolonged steady rain. Some locations with 2.5 ft of water and extensive ponding along shoulders. Location is approximate."
},
{
"id": 34563,
"valid_at": "2026-11-09T18:05:00Z",
"event": "Non-Tstm Wnd Gst",
"category": "wind",
"office": "PAJK",
"lat": 57.05,
"lon": -135.36,
"city": "1 W Sitka",
"county": "Sitka",
"state": "AK",
"source": "ASOS/AWOS",
"magnitude": 54.0,
"magnitude_unit": "MPH",
"magnitude_method": "measured",
"magnitude_trace": false,
"remarks": null
},
"..."
]
| field | |
|---|---|
id |
stable for the report. A corrected or reissued report updates the same row, so a client can key on it |
valid_at |
when the event happened, UTC. The product states local time; it is converted once, when the report is read |
event |
the office’s own wording, verbatim and unnormalized: Tstm Wnd Gst and Non-Tstm Wnd Gst are different claims. Show this to a reader |
category |
a coarse grouping for colour and icon choice. See categories |
office |
the issuing office, four letters |
lat, lon |
where, as the office gave it |
city |
the office’s location wording, often a distance and bearing from a town ("3 W Midway"). May be cut short by the product’s column width |
county, state |
as the office gave them |
source |
who reported it: Trained Spotter, Emergency Manager, ASOS/AWOS, Public, CoCoRaHS and so on. Also subject to the column width ("Department of Hig") |
magnitude |
the number, if the report has one. Many flood and damage reports do not, and null there means no number was given, not zero |
magnitude_unit |
MPH for wind, INCH for hail, rain and snow, MI for the visibility in a fog report (offices write it bare; the API supplies the unit) |
magnitude_method |
measured, estimated or unknown, from the product’s M, E or U flag. Keep it with the number: a measured 67 mph gust is an instrument reading, an estimated one is a judgement |
magnitude_trace |
true for a trace (of rain or snow): more than nothing, less than the smallest amount the product can express. magnitude is then null |
remarks |
the office’s free text, or null |
Categories
category is assigned from the event wording, so it is a grouping, not the
office’s own classification. The event string is always there beside it.
| category | event wording it covers |
|---|---|
tornado |
tornado, waterspout |
funnel |
funnel cloud, wall cloud |
hail |
hail |
wind |
thunderstorm and non thunderstorm wind gusts and damage, downbursts, marine thunderstorm wind, high sustained winds |
flood |
flood, flash flood, coastal flood, storm surge |
rain |
heavy rain, rain |
winter |
snow, sleet, freezing rain, ice storm, blizzard |
lightning |
lightning |
fire |
wildfire |
landslide |
landslide, mudslide, debris flow |
other |
everything else, such as fog |
Errors
| status | |
|---|---|
422 |
hours outside 1 to 72, a bbox that is not four numbers, or an unknown category ("unknown category: hial") |

