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

MQTT alerts feed

Live NWS hazards over MQTT-on-WebSocket, retained per hazard, tombstoned when they end, and filed by both issuing office and SAME code.


Every NWS hazard this system ingests is published to a public broker as it arrives, and stays there, retained, for as long as it is live. Subscribing replays everything currently in effect for your filter, so a client that has been offline comes back up knowing the current state of the world instead of waiting for the next statement.

This is the same broker that carries the lightning feed, on a separate topic tree. To look alerts up on demand instead of following them live, use the alerts REST API.

To write a first client, follow Subscribe to live alerts over MQTT. For what keeps one running, see Build a reliable MQTT client.

Connecting

URL wss://mqtt.wxalerts.org/mqtt
Host and port mqtt.wxalerts.org, 443
Transport MQTT over WebSocket, path /mqtt, TLS
Username wxalerts
Password wxalerts

The credentials are published on purpose. The account is subscribe-only and the broker’s ACL denies publishing on every topic, so there is nothing to protect. A publish from it is dropped without an error and without disconnecting you. There is no plain MQTT port open to the internet: 1883 and 8883 are closed, so the WebSocket on 443 is the only way in.

Your client ID must be unique. Two clients sharing one will kick each other off in a loop. Derive it from something stable and per-installation rather than hardcoding a constant.

The topic tree

Every hazard is announced twice: once under the office that issued it, and once per county it covers.

Topic Retained QoS What it carries
wxalerts/nws/v1/alert/{office}/{phen}/{sig}/{etn} yes 1 one live hazard, by issuing office
wxalerts/nws/v1/same/{same}/{etn} yes 1 the same hazard, by county
wxalerts/nws/v1/alert/{office}/Messages/{hash} 1 hour 0 raw text products

QoS is what the ingest publishes at. You receive the lower of that and the QoS you subscribe with, so subscribe at QoS 1 to get hazards at QoS 1.

The levels are:

  • {office}: the issuing office, like KMOB. Alerts that arrive without VTEC are given the four-letter office responsible for their zones. Only when that cannot be worked out does the sender’s name stand in, uppercased with non-alphanumerics replaced by underscores (NWS_MEDFORD_OR).
  • {phen}: the VTEC phenomenon, so TO tornado, SV severe thunderstorm, FF flash flood, and so on. Without VTEC, the slugged event name stands in.
  • {sig}: significance, so W warning, A watch, Y advisory, S statement. X when there is no VTEC to read it from.
  • {etn}: the VTEC event tracking number, zero-padded to four digits. Alerts without VTEC use id followed by the alert’s own id.

The ETN is in the topic because the message is retained and one office can have two tornado warnings live at once. Without it they would share alert/KMOB/TO/W and the second would erase the first.

Subscribing

Pick the tree that matches how you think about coverage. By county, the way a weather radio works:

wxalerts/nws/v1/same/012113/#        one county, every hazard

Or by office and phenomenon:

wxalerts/nws/v1/alert/KMOB/#         everything one office issues
wxalerts/nws/v1/alert/+/TO/W/+       every tornado warning in the country
wxalerts/nws/v1/alert/KMOB/TO/W/#    one office's tornado warnings

alert/# also matches text products, because messages are filed under the office that issued them. The two stay separable by shape: a hazard is the office plus three levels (alert/+/+/+/+), a message is the office plus two (alert/+/Messages/+). The shapes never collide.

Retention

A live hazard is retained, so subscribing delivers it immediately, and every resubscribe replays the whole retained set for that filter. A hazard ends with a tombstone, an empty payload retained on its topic. Both are explained in Retained alerts, and tombstones.

The payload

{
  "published_at": "2026-08-11T20:15:04.318204+00:00",   // when the ingest sent it
  "id": 1234,
  "vtec": "KMOB.TO.W.0012.2026",   // null for alerts without VTEC
  "event": "Tornado Warning",
  "office": "KMOB",
  "phenomena": "TO",                // null without VTEC
  "significance": "W",              // W warning, A watch, Y advisory, S statement
  "etn": 12,
  "action": "NEW",                  // NEW CON EXT EXA EXB CAN EXP UPG
  "status": "active",               // active | expired | cancelled
  "severity": "Extreme",            // Extreme | Severe | Moderate | Minor | Unknown
  "urgency": "Immediate",
  "certainty": "Observed",
  "issued_at": "2026-08-11T20:15:00+00:00",
  "onset":     "2026-08-11T20:15:00+00:00",
  "expires":   "2026-08-11T20:45:00+00:00",
  "ends":      "2026-08-11T20:45:00+00:00",
  "ugc":  ["FLC113", "ALC003"],
  "same": ["012113", "001003"],
  "headline": "TORNADO WARNING IN EFFECT UNTIL 345 PM CDT",
  "description": "At 315 PM CDT, a severe thunderstorm capable of…",
  "instruction": "TAKE COVER NOW! Move to a basement…",
  "geometry": { "type": "MultiPolygon", "coordinates": [] },   // GeoJSON, WGS84
  "geometry_source": "polygon",     // polygon | ugc | none
  "sources": ["api", "nwws", "emwin"]   // which feeds carried it
}

Timestamps are ISO 8601 with an offset. published_at is stamped as the message leaves the ingest, so it is the one field you can measure the broker hop against; issued_at is when NWS wrote the product. geometry is a GeoJSON Polygon or MultiPolygon in WGS84, or null for a hazard that has no shape.

Notes on individual fields:

  • expires is not the end of the hazard. It is CAP’s “expect an update by” deadline and routinely sits in the past on a live alert. ends is the end.
  • action is the latest VTEC action, not the state. A hazard that has been cancelled for some of its counties stays active, on its remaining counties, with action set to CAN. status is the state.
  • geometry_source tells you how precise the shape is. polygon is a tight storm-based warning polygon; ugc is a coarser union of county boundaries. Geometry is simplified for the wire.
  • One hazard arrives more than once. A warning covering three counties is published on three same/ topics plus its office topic, with an identical payload each time. id is the same on every copy.

Text products

Raw products are published under the office that issued them, keyed by a content hash so the same product arriving on two feeds lands on one topic instead of appearing twice:

wxalerts/nws/v1/alert/{office}/Messages/{hash}

They carry published_at, wmo_id, awips_id, office, issued_at, source, hash and the raw body. {hash} in the topic is the first 16 characters of hash. awips_id is null for products that have none, and source is the feed that delivered the product first, nwws or emwin. They are retained for about an hour and then tombstoned, so a subscriber joining mid-hour sees what an office has put out recently.

Surface observation collectives are not published here. At roughly 350 bulletins an hour they would swamp the tree with instrument data nobody subscribed to it for.

Broker limits

limit value
subscriptions per client 20. The 21st subscribe is refused with a failure code in the SUBACK while the connection stays up
new WebSocket connections at most 50 a second across all clients

View this page as Markdown

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.