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

Lightning

Recent GOES-19 GLM lightning flashes in a box, for filling in what a live MQTT client missed before it connected.


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

Lightning flashes seen from orbit by the Geostationary Lightning Mapper (GLM) on GOES-19, the GOES-East satellite. GLM is an optical sensor: it watches for the flicker of lightning lighting up cloud tops, day and night, across the Americas and the Atlantic, at about 8 km resolution. It sees in-cloud and cloud-to-ground lightning alike and does not tell them apart.

GET /lightning/flashes?bbox=-98.5,32.0,-96.0,33.5
GET /lightning/flashes?bbox=-104,30,-90,40&minutes=30
GET /lightning/flashes?bbox=-104,30,-90,40&minutes=60&until=2026-11-09T18:00:00Z&limit=5000

No key needed. It shares the per address limit. Browsers block calls from other websites (CORS allows only wxalerts.org), so call it from a server, script or app.

Flashes arrive live over the MQTT lightning feed, and that is the way to follow lightning as it happens. The broker keeps nothing, so a client that has just connected has no flashes from before it did. This route fills that gap: it reads the same flashes back from the database, so a radar loop or a newly opened page can draw the last hour and then carry on from MQTT. For daily counts rather than individual flashes, see /v1/stats/lightning/daily.

parameter
bbox required. minLon,minLat,maxLon,maxLat in degrees, west, south, east, north. Each must be inside -180 to 180 and -90 to 90, with min below max. A box crossing the antimeridian is not supported
minutes how far back from until to reach, 1 to 180. Default 70 (a radar loop’s hour, plus the ten minutes its oldest frame draws behind it)
until ISO 8601 end of the window. Default now. A time without a zone is read as UTC. Up to 5 minutes in the future is accepted for clock skew, and anything later is pulled back to now plus 5 minutes
limit at most this many flashes, 1 to 60000. Default 30000

The window is since < t <= until. The database keeps about a day, so a window that ends further back than that comes back empty, not as an error.

What a response holds

{
  "since": "2026-11-09T18:58:26.935870Z",
  "until": "2026-11-09T19:08:26.935870Z",
  "truncated": false,
  "flashes": [
    [1794250713936, 24.4613, -95.9038, 6.42848946817709e-14],
    [1794250715534, 39.6719, -67.0973, 9.428477557070838e-14],
    "...",
    [1794251248570, 39.214, -68.1464, 1.3128461805091834e-13]
  ]
}
  • flashes are rows, oldest first, not GeoJSON: an hour over a busy view is tens of thousands of flashes, and four key names on each would triple the payload. Each row is [t_ms, lat, lon, energy_j].
  • t_ms is the observation time in epoch milliseconds (truncated, not rounded). This is when GLM saw the flash, not when it reached us; flashes run about 20 seconds behind.
  • lat, lon are rounded to four decimals, exactly as the MQTT feed publishes them. Note the order: latitude first, unlike bbox and GeoJSON.
  • energy_j is the flash’s total optical energy as GLM measured it, in joules, or null. The numbers are tiny (around 1e-14 to 1e-12) because it is the light reaching the sensor; use it to compare flashes, for size or brightness, not as the energy of the discharge.
  • since, until echo the window actually served, after defaults and the clamp on until.
  • truncated is true when there were more flashes than limit. The newest are kept and the oldest dropped, so the gap is at the start of the window. Narrow the box or shorten minutes rather than raising limit to the ceiling as a habit.

Merging with the live feed

The time to the millisecond and the position to four decimals are the identity the MQTT feed uses, so a flash heard live and the same flash read here match exactly. Key a set on t_ms,lat,lon, load the history, and drop live messages already in it. Fade flashes on t_ms, not on when you received them.

Responses are cached for 20 seconds (Cache-Control: public, max-age=20): the newest minute changes with every GLM granule, so poll no faster than that, and prefer MQTT for anything live.

Errors

status when
422 bbox missing, not four numbers, out of range or inverted, or minutes or limit out of range

The shared error shapes are on the REST overview.

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.