Community. Driven. Weather. Data. | Always Ad-Free | Developer FriendlyChecking statusDiscord
Become a supporter
Sign in
API

Statistics

Live counts of active alerts and GLM lightning, how fast each NWS alert feed delivers, and daily lightning totals in any time zone.


Base URL: https://api.wxalerts.org

The headline numbers on this site: how many alerts are in effect, how much lightning the GOES satellites are seeing, how quickly each alert feed delivers, and lightning per day.

GET /stats/summary
GET /stats/latency?hours=24
GET /v1/stats/lightning/daily?days=7&timezone=America/Chicago

summary and latency need no key. Browsers block calls from other websites (CORS allows only wxalerts.org), so call them from a server, script or app. They are limited per address as described under rate limits. lightning/daily needs an API key (alerts:read) and is served only under /v1; on the bare path it answers 401 with code api_key_required.

GET /stats/summary

Active alert counts and the GLM lightning window. No parameters. Cached for 15 seconds, which is about the data’s own cadence, so polling faster gets you the same answer.

{
  "server_time": "2026-11-09T19:07:18.638865Z",
  "alerts": { "active": 370, "with_geometry": 370 },
  "lightning": {
    "flashes": 1214878,
    "window_start": "2026-11-08T19:30:00.010682Z",
    "window_end": "2026-11-09T19:46:39.319450Z",
    "window_seconds": 87399,
    "rate_per_minute": 834.0,
    "retention_hours": 24.0,
    "covers_full_day": true
  }
}
field
alerts.active alerts in effect now, the same set every alerts route counts
alerts.with_geometry how many of those have a shape and can be drawn on a map
lightning.flashes GLM flashes between window_start and window_end
window_start, window_end the oldest and newest flash the live store holds
window_seconds the span between them
rate_per_minute flashes over that span, per minute
retention_hours how long the live store is set to keep flashes
covers_full_day whether the window spans at least 24 hours

The window is whatever the live store holds, measured, not assumed, so read its length from window_seconds rather than from retention_hours. Branch on covers_full_day before calling the count a day’s worth. Even when it is true, the window is rolling and never a calendar day: at 09:00 it reaches back into the day before. Do not label it “today”. For lightning per day, use lightning/daily.

GET /stats/latency

How fast each alert feed delivers, measured against the others. The ingest takes the same hazards from three feeds (nwws, NWWS-OI over XMPP; emwin, off the GOES broadcast; api, the api.weather.gov CAP feed) and records when each one first delivered each hazard.

parameter
hours window to report over, 1 to 168. Default 24. Arrival records are pruned on a rolling schedule, so asking for more than is kept gives a shorter answer, not an error
{
  "server_time": "2026-11-09T19:07:19.262194Z",
  "window_hours": 24,
  "issuance_resolution_seconds": 60,
  "sources": [
    {
      "source": "nwws",
      "arrivals": 241, "contested": 241, "wins": 236, "win_share": 0.9793, "exclusive": 0,
      "median_behind_seconds": 0.0, "p95_behind_seconds": 0.0, "max_behind_seconds": 9229.67,
      "median_issuance_lag_seconds": 58.6
    },
    {
      "source": "api",
      "arrivals": 242, "contested": 241, "wins": 5, "win_share": 0.0207, "exclusive": 1,
      "median_behind_seconds": 30.43, "p95_behind_seconds": 106.25, "max_behind_seconds": 169.78,
      "median_issuance_lag_seconds": 94.3
    },
    "..."
  ]
}

Sources come most wins first. Two different measurements are in each row, and they are not interchangeable.

Relative, exact to the millisecond, and the fair way to rank the feeds:

field
arrivals hazards this feed delivered in the window
contested of those, how many at least one other feed also delivered. Only these can be raced
wins contested hazards this feed delivered first
win_share wins / contested, 0.0 when nothing was contested
exclusive hazards no other feed carried. Coverage, not speed: the reason to keep a feed that never wins
median_behind_seconds, p95_behind_seconds, max_behind_seconds how far behind the fastest feed this one arrived, over contested hazards. null when none were contested

Absolute, indicative only:

field
median_issuance_lag_seconds median time from the NWS issuance stamp to arrival
issuance_resolution_seconds 60. The NWS stamps issuance to the minute, so every absolute lag can be off by up to this much. Treat it as an order of magnitude

max_behind_seconds catches outliers such as a feed that dropped and caught up later; the median and p95 are the figures to quote. Cached for 60 seconds.

GET /v1/stats/lightning/daily

GLM flash counts per day, with days cut in any time zone. Needs a key (alerts:read).

parameter
days how far back to look, in days from now, 1 to 400. Default 30
timezone IANA zone to cut days in, e.g. America/Chicago. Default UTC. An unknown zone is 422, never a silent fall back to UTC

Pick the zone your readers live in. A UTC day ends in the evening across the Americas, so in UTC an evening storm lands on the next day.

{
  "server_time": "2026-11-09T19:07:13.249615Z",
  "timezone": "America/Chicago",
  "days": [
    {
      "day": "2026-11-09",
      "flashes": 238705,
      "peak_hourly_flashes": 40928,
      "hours_observed": 11,
      "mean_energy_j": 2.0169939528190287E-13,
      "first_flash": "2026-11-09T06:00:00.096895Z",
      "last_flash": "2026-11-09T16:59:59.906157Z"
    },
    {
      "day": "2026-11-08",
      "flashes": 1557001,
      "peak_hourly_flashes": 166906,
      "hours_observed": 24,
      "mean_energy_j": 1.5397250051263375E-13,
      "first_flash": "2026-11-08T06:00:00.114443Z",
      "last_flash": "2026-11-09T05:59:59.953460Z"
    },
    "..."
  ]
}
field
day the local date in timezone
flashes flashes that day
peak_hourly_flashes the busiest single hour, a sign of how intense the day got that a total hides
hours_observed hours with at least one flash. Under 24 on a quiet day, but also on a day with a gap in the data: check it before reading a low count as fair weather
mean_energy_j mean optical energy per flash at cloud top, in joules. Not a measure of ground hazard
first_flash, last_flash the first and last flash of that day, UTC

Days come newest first: today and the days - 1 whole days before it, cut at midnight in timezone, so days=7 is at most seven rows (a day with no flashes at all has no row). Today’s row is still filling in. Use hours_observed to tell a partial day from a complete one. Finished days never change; the response is cached for an hour.

May we use Microsoft Clarity to see how pages are used (clicks, scrolling and replays of a visit, with anything you type hidden), plus a random ID linking that to crash reports? Only to find bugs and confusing screens. Never advertising, never sold.