Base URL: https://api.wxalerts.org
Where visibility is down right now, and why: fog, marine fog and smoke, as polygons by category, refreshed every 15 minutes. Each area says how sure the product is and what it is based on. No polygon means normal visibility.
GET /visibility?bbox=-88.6,30.1,-86.4,31.2
GET /visibility?bbox=-88.6,30.1,-86.4,31.2&min_category=2
GET /visibility/point?lat=30.69&lon=-88.04
GET /visibility/point?q=mobile+al
No authentication. CORS is open. Design against
60 requests a minute. Both endpoints send
Cache-Control: public, max-age=120; a new analysis lands every 15 minutes,
so polling faster than that learns nothing.
WxAlerts sets no thresholds
This product describes; it does not decide. It never says “dangerous”, never
issues an alert, and never hides a category as too minor to show. Every area
carries its category, confidence, cause and sources, and what is worth drawing
or alerting on is your call. A traffic app might alert only on very_low and
worse at medium confidence or higher; a marine app might care about any
marine_fog. Filter on the fields.
Categories
Prevailing visibility, from aviation and NWS practice.
category |
category_name |
visibility |
|---|---|---|
| 1 | reduced |
3 to 5 mi (4828 to 8047 m) |
| 2 | low |
1 to 3 mi (1609 to 4828 m) |
| 3 | very_low |
1/4 to 1 mi (402 to 1609 m) |
| 4 | near_zero |
under 1/4 mi (under 402 m) |
| 0 | normal |
5 mi or more. Never a polygon; used only by /visibility/point |
Each lower edge is inclusive: 1609 m is low, 1608 m is very_low, 8047 m is
normal.
Where it comes from
Four independent sources, fused on a 2.5 km grid:
| source | what it adds |
|---|---|
analysis |
NOAA’s RTMA Rapid Update visibility analysis, every 15 minutes, the base layer everywhere |
station |
airport (METAR) and buoy (NDBC) visibility, which pulls the analysis toward the measurement within 15 km |
advisory |
NWS Dense Fog, Marine Dense Fog, Freezing Fog and Dense Smoke Advisories. Inside one, the category is at least very_low and the cause is the advisory’s |
reports |
clusters of driver reports from integrations. No single driver is trusted: ten or more independent reporters within 2 km and 30 minutes create an area, marked reported: true |
sources on each area lists the ones that agree with it.
Confidence follows from how many independent sources agree: one is low,
two medium, three or more high. A reported area is always high.
Cause is fog, marine_fog or smoke. Freezing fog is reported as fog.
GET /visibility
The current areas that intersect a bounding box, clipped to it, as a GeoJSON FeatureCollection, least severe first so drawing in order puts the worst on top.
| parameter | |
|---|---|
bbox |
west,south,east,north in degrees. At most 30 degrees a side |
min_category |
1 (default) to 4: only areas this bad or worse |
{
"type": "FeatureCollection",
"analysis_time": "2026-11-09T11:45:00Z",
"published_at": "2026-11-09T11:52:10Z",
"bbox": [-88.6, 30.1, -86.4, 31.2],
"min_category": 1,
"legend": [
{ "category": 1, "category_name": "reduced", "range_mi": "3 to 5 mi", "min_m": 4828.0, "max_m": 8047.0 },
"..."
],
"features": [
{
"type": "Feature",
"geometry": { "type": "MultiPolygon", "coordinates": ["..."] },
"properties": {
"category": 3,
"category_name": "very_low",
"cause": "fog",
"confidence": "high",
"sources": ["analysis", "station", "advisory"],
"reported": false,
"vis_m_min": 420.0,
"analysis_time": "2026-11-09T11:45:00Z"
}
}
]
}
vis_m_min is the lowest analysed visibility inside the area, in metres.
Coordinates are to 5 decimal places, about a metre. An empty features list
is a clear analysis. A bbox that is malformed or too large is a 422. Before
the first analysis has been published the endpoint answers 503; retry.
GET /visibility/point
Everything known at one place: the analysis, the nearest measurement, any advisory, and the model’s next six hours.
| parameter | |
|---|---|
lat, lon |
the point. Or q (a place name) or location_id, as on /forecast |
{
"location": { "name": "Mobile", "display_name": "Mobile, AL", "state": "AL", "lat": 30.69, "lon": -88.04 },
"analysis_time": "2026-11-09T11:45:00Z",
"published_at": "2026-11-09T11:52:10Z",
"message": null,
"current": {
"category": 3, "category_name": "very_low", "cause": "fog", "confidence": "high",
"sources": ["analysis", "station", "advisory"], "reported": false, "vis_m_min": 420.0
},
"station": {
"station_id": "KMOB", "source": "metar", "distance_km": 18.4,
"visibility_m": 402.0, "observed_at": "2026-11-09T11:53:00Z"
},
"advisories": [
{ "event": "Dense Fog Advisory", "phenomena": "FG", "office": "MOB",
"expires": "2026-11-09T15:00:00Z", "ends": "2026-11-09T15:00:00Z" }
],
"outlook": {
"model": "hrrr", "cycle": "2026-11-09T11:00:00Z", "cell_id": 812345, "resolution_km": 6.0,
"hours": [
{ "valid_time": "2026-11-09T12:00:00Z", "visibility_m": 300, "category": 4, "category_name": "near_zero" },
{ "valid_time": "2026-11-09T13:00:00Z", "visibility_m": 1200, "category": 3, "category_name": "very_low" },
"..."
]
},
"legend": ["..."]
}
currentis the worst area covering the point: the highest category, then the highest confidence. Outside every area it is{"category": 0, "category_name": "normal"}. Before the first analysis it isnullandmessagesays so.stationis the nearest airport or buoy within 25 km that reported a visibility in the last 90 minutes, ornull.advisoriesare the NWS fog and smoke advisories in force at the point.outlookis HRRR surface visibility for the next six hours, from the hour in progress, each mapped to the same categories. It is the lowest value in a 6 km block, so it leans pessimistic.nulloutside the HRRR grid (the contiguous United States and its surroundings).
Report intake
POST /visibility/reports accepts anonymized driver fog reports from
integrations by arrangement, authenticated with a shared token. It is not open
to the public. Reports are never served back by this API; they only shape the
product, and only in clusters. Get in touch if you run an app
whose users could report fog.

