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 /v1/visibility?bbox=-123.2,37.4,-121.8,38.2
GET /v1/visibility?bbox=-123.2,37.4,-121.8,38.2&min_category=3
GET /v1/visibility/point?lat=37.62&lon=-122.38
GET /v1/visibility/point?q=mobile+al
Needs an API key (weather:read). Both endpoints are
served only under /v1; the unprefixed paths answer 401. Browsers block
calls from other websites (CORS allows only wxalerts.org), so call it from a
server, script or app. Both send Cache-Control: private, max-age=120; a new
analysis lands every 15 minutes, so polling faster than that learns nothing.
The key’s rate limit applies.
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 anonymized driver reports from partner apps. No single driver is trusted: ten or more independent reporters within 2 km and 30 minutes create an area, marked reported: true. Individual reports are never served by this API |
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.
Areas are grouped, not one per fog bank: each feature is every area sharing one category, confidence, set of sources and cause, as a single MultiPolygon. The same category can appear several times in one response with different confidence or sources.
GET /v1/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 |
required. west,south,east,north in degrees, west less than east and south less than north. At most 30 degrees a side |
min_category |
1 (default) to 4: only areas this bad or worse |
{
"type": "FeatureCollection",
"server_time": "2026-11-09T19:12:04Z",
"analysis_time": "2026-11-09T18:45:00Z",
"published_at": "2026-11-09T19:08:21Z",
"bbox": [-123.2, 37.4, -121.8, 38.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": 4,
"category_name": "near_zero",
"cause": "marine_fog",
"confidence": "high",
"sources": ["analysis", "station", "advisory"],
"reported": false,
"vis_m_min": 180.0,
"analysis_time": "2026-11-09T18:45:00Z"
}
},
"..."
]
}
vis_m_min is the lowest analysed visibility inside the area, in metres. It
can sit above the category’s range: where an advisory set the category (at
least very_low), the analysis underneath may still read several miles.
legend repeats the category table with its edges in metres (min_m
inclusive, max_m exclusive, null for no floor). Coordinates are to 5
decimal places, about a metre. An empty features list is a clear analysis. A
bbox that is missing, malformed or too large is a 422. Before the first
analysis has been published the endpoint answers 503; retry.
GET /v1/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. None of them is a 422; a name or id that matches nothing is a 404 |
{
"server_time": "2026-11-09T19:12:05Z",
"location": { "name": null, "display_name": null, "state": null, "lat": 37.62, "lon": -122.38 },
"analysis_time": "2026-11-09T18:45:00Z",
"published_at": "2026-11-09T19:08:21Z",
"message": null,
"current": {
"category": 3, "category_name": "very_low", "cause": "fog", "confidence": "medium",
"sources": ["analysis", "station"], "reported": false, "vis_m_min": 424.0
},
"station": {
"station_id": "metar:KSFO", "source": "metar", "distance_km": 1.3,
"visibility_m": 1207.0, "observed_at": "2026-11-09T18:56:00Z"
},
"advisories": [],
"outlook": {
"model": "hrrr", "cycle": "2026-11-09T18:00:00Z", "cell_id": 267091, "resolution_km": 6.0,
"hours": [
{ "valid_time": "2026-11-09T19:00:00Z", "visibility_m": 13500.0, "category": 0, "category_name": "normal" },
{ "valid_time": "2026-11-09T20:00:00Z", "visibility_m": 17200.0, "category": 0, "category_name": "normal" },
"..."
]
},
"legend": ["..."]
}
currentis the worst area covering the point: the highest category, then the highest confidence, then areportedarea. Outside every area it is category0,normal, withcause,confidenceandvis_m_minnullandsourcesempty. Before the first analysis it isnullandmessagesays so; the other blocks still answer.locationis named only when you asked byqorlocation_id.stationis the nearest airport (source: metar) or buoy (ndbc) within 25 km that reported a visibility in the last 90 minutes, ornull.station_idcarries the source as a prefix (metar:KSFO,ndbc:PTOA1). A station can disagree withcurrent: it is a single measurement at one spot, and the area is the fused picture.advisoriesare the NWS fog and smoke advisories in force at the point, soonest to expire first:event(for exampleDense Fog Advisory),phenomena(FGdense fog,MFmarine dense fog,ZFfreezing fog,SMdense smoke), the issuingoffice,expiresandends. Empty when none.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).

