Skip to content

NWS API

The National Weather Service (US) provides an API that can be used to get all sorts of data related to the weather. Best of all, no account or authentication is needed.

We'll be using the following API endpoints for this exercise:

  • Stations (list)
  • Station (detailed information about a single station)
  • Active Alerts
  • Observations

Documentation for the API can be found here: https://www.weather.gov/documentation/services-web-api. You can also try out all the API endpoints there, to see what data you can supply, and what the returned data looks like.

Stations and station API

Stations (list)

The Stations endpoint allows us to retrieve a list of weather observation stations. In our case, we will be querying by state.

Here's an example query for Oklahoma and Texas:

https://api.weather.gov/stations?state=OK,TX

Here's the response to that query (note: this has been truncated):

{
  "@context": [
    "https://raw.githubusercontent.com/geojson/geojson-ld/master/contexts/geojson-base.jsonld",
    {
      "wx": "https://api.weather.gov/ontology#",
      "s": "https://schema.org/",
      "geo": "http://www.opengis.net/ont/geosparql#",
      "unit": "http://codes.wmo.int/common/unit/",
      "@vocab": "https://api.weather.gov/ontology#",
      "geometry": {
        "@id": "s:GeoCoordinates",
        "@type": "geo:wktLiteral"
      },
      "city": "s:addressLocality",
      "state": "s:addressRegion",
      "distance": {
        "@id": "s:Distance",
        "@type": "s:QuantitativeValue"
      },
      "bearing": {
        "@type": "s:QuantitativeValue"
      },
      "value": {
        "@id": "s:value"
      },
      "unitCode": {
        "@id": "s:unitCode",
        "@type": "@id"
      },
      "forecastOffice": {
        "@type": "@id"
      },
      "forecastGridData": {
        "@type": "@id"
      },
      "publicZone": {
        "@type": "@id"
      },
      "county": {
        "@type": "@id"
      },
      "observationStations": {
        "@container": "@list",
        "@type": "@id"
      }
    }
  ],
  "type": "FeatureCollection",
  "features": [
    {
      "id": "https://api.weather.gov/stations/KLBB",
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [
          -101.8213899,
          33.6674999
        ]
      },
      "properties": {
        "@id": "https://api.weather.gov/stations/KLBB",
        "@type": "wx:ObservationStation",
        "elevation": {
          "value": 1000.0488,
          "unitCode": "unit:m"
        },
        "stationIdentifier": "KLBB",
        "name": "Lubbock, Lubbock International Airport",
        "timeZone": "America/Chicago"
      }
    },
...

The key things to note about this response are that the information we care about is in the features object; that contains the list of stations, and each station has a set of properties.

Station (detailed information)

The Station endpoint provides detailed information about each observation station, including county and NWS forecast and fire zones.

Here's an example query for Tulsa International Airport:

https://api.weather.gov/stations/KTUL

And here's the result of that query:

{
  "@context": [
    "https://raw.githubusercontent.com/geojson/geojson-ld/master/contexts/geojson-base.jsonld",
    {
      "wx": "https://api.weather.gov/ontology#",
      "s": "https://schema.org/",
      "geo": "http://www.opengis.net/ont/geosparql#",
      "unit": "http://codes.wmo.int/common/unit/",
      "@vocab": "https://api.weather.gov/ontology#",
      "geometry": {
        "@id": "s:GeoCoordinates",
        "@type": "geo:wktLiteral"
      },
      "city": "s:addressLocality",
      "state": "s:addressRegion",
      "distance": {
        "@id": "s:Distance",
        "@type": "s:QuantitativeValue"
      },
      "bearing": {
        "@type": "s:QuantitativeValue"
      },
      "value": {
        "@id": "s:value"
      },
      "unitCode": {
        "@id": "s:unitCode",
        "@type": "@id"
      },
      "forecastOffice": {
        "@type": "@id"
      },
      "forecastGridData": {
        "@type": "@id"
      },
      "publicZone": {
        "@type": "@id"
      },
      "county": {
        "@type": "@id"
      }
    }
  ],
  "id": "https://api.weather.gov/stations/KTUL",
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [
      -95.88639,
      36.1975
    ]
  },
  "properties": {
    "@id": "https://api.weather.gov/stations/KTUL",
    "@type": "wx:ObservationStation",
    "elevation": {
      "value": 206.0448,
      "unitCode": "unit:m"
    },
    "stationIdentifier": "KTUL",
    "name": "Tulsa, Tulsa International Airport",
    "timeZone": "America/Chicago",
    "forecast": "https://api.weather.gov/zones/forecast/OKZ060",
    "county": "https://api.weather.gov/zones/county/OKC143",
    "fireWeatherZone": "https://api.weather.gov/zones/fire/OKZ060"
  }
}

Note again that we aren't interested in the context object. In this case, since we're just getting one station, instead of a features object with a list, we just have a set of attributes. In general, the attributes we care about will always be under the properties object.

Active alerts API

The Active Alerts endpoint provides information about severe weather alerts such as tornado warnings, flood warnings and other special weather statements. We’ll be collecting these alerts to create corresponding Zenoss events. This way operators can know when severe weather may be impacting areas of concern. We'll be using the county of the weather station to collect alerts that might impact each station, since the alerts aren't directly issued by the observation station.

Here's an example of a query for alerts affecting the station at Tulsa International Airport:

https://api.weather.gov/alerts/active?zone=OKC143

And here's the response to that query:

{
  "@context": [
    "https://raw.githubusercontent.com/geojson/geojson-ld/master/contexts/geojson-base.jsonld",
    {
      "wx": "https://api.weather.gov/ontology#",
      "@vocab": "https://api.weather.gov/ontology#"
    }
  ],
  "type": "FeatureCollection",
  "features": [
    {
      "id": "https://api.weather.gov/alerts/NWS-IDP-PROD-3574196",
      "type": "Feature",
      "geometry": null,
      "properties": {
        "@id": "https://api.weather.gov/alerts/NWS-IDP-PROD-3574196",
        "@type": "wx:Alert",
        "id": "NWS-IDP-PROD-3574196",
        "areaDesc": "Tulsa, OK",
        "geocode": {
          "UGC": [
            "OKC143"
          ],
          "SAME": [
            "040143"
          ]
        },
        "affectedZones": [
          "https://api.weather.gov/zones/county/OKC143"
        ],
        "references": [],
        "sent": "2019-05-23T12:44:00-05:00",
        "effective": "2019-05-23T12:44:00-05:00",
        "onset": "2019-05-23T12:44:00-05:00",
        "expires": "2019-05-23T21:45:00-05:00",
        "ends": null,
        "status": "Actual",
        "messageType": "Alert",
        "category": "Met",
        "severity": "Unknown",
        "certainty": "Unknown",
        "urgency": "Unknown",
        "event": "Civil Emergency Message",
        "sender": "[email protected]",
        "senderName": "NWS Tulsa OK",
        "headline": "Civil Emergency Message issued May 23 at 12:44PM CDT by NWS Tulsa OK",
        "description": "THE FOLLOWING MESSAGE IS TRANSMITTED AT THE REQUEST OF THE CITY\nOF TULSA.\n\nTHE KEYSTONE DAM IS INCREASING THE RELEASE OF WATER TO 250,000\nCUBIC FEET PER SECOND.\n\nBEGINNING AT 3 PM, THE CITY OF TULSA WILL SOUND THE FLOOD SIRENS\nINCREMENTALLY EVERY 30 MINUTES FOR 6 HOURS.\n\nTHE FLOOD SIRENS WILL BE LOCALIZED ALONG THE ARKANSAS RIVER AND\nWILL BE A WARNING TO RESIDENTS IN AFFECTED AREAS TO PLAN TO MOVE\nTO HIGHER GROUND.\n\nTHIS IS A DANGEROUS SITUATION. PLEASE FOLLOW THE INSTRUCTIONS OF\nYOUR LOCAL FIRST RESPONDERS FOR EVACUATION ROUTES AND SHELTERS FOR\nYOUR AFFECTED AREA.",
        "instruction": "",
        "response": "Monitor",
        "parameters": {
          "EAS-ORG": [
            "WXR"
          ],
          "PIL": [
            "TSACEMTSA"
          ],
          "BLOCKCHANNEL": [
            "CMAS",
            "EAS",
            "NWEM"
          ]
        }
      }
    },

This was done during a time of severe weather, so we'd have something to look at. Note that the response has been truncated. It’s easy to imagine turning this alert into a Zenoss event. We’ll see how to do this a bit later.

Observations API

The Observations API endpoint provides information about current weather conditions for a given weather station. The Observations API endpoint is accepts a station ID to specify the weather station. There’s a lot of numeric data that would be useful to graph and threshold as Zenoss datapoints.

Here’s an example query for the observations for the weather station at Dallas/Fort Worth International Airport:

https://api.weather.gov/stations/KDFW/observations/latest

And here’s the result of that query:

{
  "@context": [
    "https://raw.githubusercontent.com/geojson/geojson-ld/master/contexts/geojson-base.jsonld",
    {
      "wx": "https://api.weather.gov/ontology#",
      "s": "https://schema.org/",
      "geo": "http://www.opengis.net/ont/geosparql#",
      "unit": "http://codes.wmo.int/common/unit/",
      "@vocab": "https://api.weather.gov/ontology#",
      "geometry": {
        "@id": "s:GeoCoordinates",
        "@type": "geo:wktLiteral"
      },
      "city": "s:addressLocality",
      "state": "s:addressRegion",
      "distance": {
        "@id": "s:Distance",
        "@type": "s:QuantitativeValue"
      },
      "bearing": {
        "@type": "s:QuantitativeValue"
      },
      "value": {
        "@id": "s:value"
      },
      "unitCode": {
        "@id": "s:unitCode",
        "@type": "@id"
      },
      "forecastOffice": {
        "@type": "@id"
      },
      "forecastGridData": {
        "@type": "@id"
      },
      "publicZone": {
        "@type": "@id"
      },
      "county": {
        "@type": "@id"
      }
    }
  ],
  "id": "https://api.weather.gov/stations/KDFW/observations/2019-05-28T17:53:00+00:00",
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [
      -97.03,
      32.9
    ]
  },
  "properties": {
    "@id": "https://api.weather.gov/stations/KDFW/observations/2019-05-28T17:53:00+00:00",
    "@type": "wx:ObservationStation",
    "elevation": {
      "value": 182,
      "unitCode": "unit:m"
    },
    "station": "https://api.weather.gov/stations/KDFW",
    "timestamp": "2019-05-28T17:53:00+00:00",
    "rawMessage": "KDFW 281753Z 18020KT 10SM BKN034 BKN042 OVC250 28/20 A2974 RMK AO2 PK WND 19030/1737 SLP062 T02830200 10294 20228 56010",
    "textDescription": "Cloudy",
    "icon": "https://api.weather.gov/icons/land/day/ovc?size=medium",
    "presentWeather": [],
    "temperature": {
      "value": 28.30000000000001,
      "unitCode": "unit:degC",
      "qualityControl": "qc:V"
    },
    "dewpoint": {
      "value": 20,
      "unitCode": "unit:degC",
      "qualityControl": "qc:V"
    },
    "windDirection": {
      "value": null,
      "unitCode": "unit:degree_(angle)",
      "qualityControl": "qc:Z"
    },
    "windSpeed": {
      "value": null,
      "unitCode": "unit:m_s-1",
      "qualityControl": "qc:Z"
    },
    "windGust": {
      "value": null,
      "unitCode": "unit:m_s-1",
      "qualityControl": "qc:Z"
    },
    "barometricPressure": {
      "value": 100710,
      "unitCode": "unit:Pa",
      "qualityControl": "qc:V"
    },
    "seaLevelPressure": {
      "value": 100620,
      "unitCode": "unit:Pa",
      "qualityControl": "qc:V"
    },
    "visibility": {
      "value": 16090,
      "unitCode": "unit:m",
      "qualityControl": "qc:C"
    },
    "maxTemperatureLast24Hours": {
      "value": null,
      "unitCode": "unit:degC",
      "qualityControl": null
    },
    "minTemperatureLast24Hours": {
      "value": null,
      "unitCode": "unit:degC",
      "qualityControl": null
    },
    "precipitationLastHour": {
      "value": null,
      "unitCode": "unit:m",
      "qualityControl": "qc:Z"
    },
    "precipitationLast3Hours": {
      "value": null,
      "unitCode": "unit:m",
      "qualityControl": "qc:Z"
    },
    "precipitationLast6Hours": {
      "value": null,
      "unitCode": "unit:m",
      "qualityControl": "qc:Z"
    },
    "relativeHumidity": {
      "value": 60.766129124366735,
      "unitCode": "unit:percent",
      "qualityControl": "qc:C"
    },
    "windChill": {
      "value": null,
      "unitCode": "unit:degC",
      "qualityControl": "qc:V"
    },
    "heatIndex": {
      "value": 29.99744621839261,
      "unitCode": "unit:degC",
      "qualityControl": "qc:V"
    },
    "cloudLayers": [
      {
        "base": {
          "value": 1040,
          "unitCode": "unit:m"
        },
        "amount": "BKN"
      },
      {
        "base": {
          "value": 1280,
          "unitCode": "unit:m"
        },
        "amount": "BKN"
      },
      {
        "base": {
          "value": 7620,
          "unitCode": "unit:m"
        },
        "amount": "OVC"
      }
    ]
  }
}