Here is what I have learned so far about working with this new NWS API. The input I use is the locations lat and lng. The output I want is weather data (temp, preceip, cloud cover, etc…) for that location in a grid, hour by hour. I have included links to run or download a one page PHP working example, you will find those below the code snippets.
National Weather Service API Streaming Setup
To stream anything from https://api.weather.gov you must first set the stream header to include the Accept, Version and User-Agent. If you do not set the header the stream will return empty. NWS asks that you include your website and email address in the User-Agent so the they can contact you if need be.
$UserAgent = "YOURWEBSITE (your@emailaddress.com)"; // HTTP stream options: $opts = array( 'http'=>array( 'method'=>"GET", 'header'=>"Accept: application/geo+json;version=1\r\n" . "User-agent: $UserAgent\r\n" ) ); $context = stream_context_create($opts);
After the header is set you can stream the /points/lat,lng endpoint into a json object and pull forecastGridData, which is the /gridpoints/office/x/y endpoint. If you do not need a detailed gridded forecast take a look at the /points/lat,lng/forecast/ or /points/lat,lng/forecast/hourly in the documentation.
$lat = 43.0204; $lng = -71.6002; $pointMetaUrl = "https://api.weather.gov/points/$lat,$lng"; $pointMetaFile = file_get_contents($pointMetaUrl, false, $context); $pointMetaArray = json_decode($pointMetaFile, true); $forecastGridData = $pointMetaArray["properties"]["forecastGridData"];
Now stream the detailed gridded forecast using the forecastGridData /gridpoints/office/x/y endpoint. Then start pulling the data you want.
$gridDataFile = file_get_contents($forecastGridData, false, $context); $gridDataArray = json_decode($gridDataFile, true); $temp = $gridDataArray["properties"]["temperature"]["values"];
Here is the code above in one file you can run or download:
Run Code Example Download Code Example (raw)
Each weather element is returned as an array of arrays, including a time and value (e.g. temperature). The value may span more than one hour. validTime is formatted as ISO 8601, with a PHP DateInterval suffix, like: “PT2H”. “PT2H” is a 2 hour interval, “PT3H” is 3 hours, “PT4H” is 4 hours, and so on. So the temperature (-6.111 C) in the example below “…T08:00:00+00:00/PT2H” covers 2 hours (8AM, 9AM GMT).
"values": [
{
"validTime": "2017-02-17T08:00:00+00:00/PT2H",
"value": -6.1111111111111
},
I am trying to decode the “validTime” field in the NOAA forecast file for my zone. It currently shows: “validTimes”: “2021-03-09T06:00:00+00:00/P7DT19H”. What is the meaning of “P7DT19H”? I was expecting something like “PT8H”. Thanks!
Thank you for sharing this. It wasn’t exactly what I needed, but put me on the right track. The js fiddle on post 13 is another great share. This url is what nailed it for me —
https://graphical.weather.gov/xml/SOAP_server/ndfdXML.htm
Not sure if this is helpful to anyone or not: https://jsfiddle.net/bravofoxtrotyankee/rzpLqm27/18/
Fantastic! Have been looking for an “open” weather api and it looks like this is the one I want. WU is closed and the others don’t give me a clear “forecast” like this does. My goal is a Raspberry Pi kitchen weather station and this makes it possible (but parsing the return with JS in Node Red will be an uphill slog for me). Thanks for putting this out there.
How would you display only the current conditions: Temp, City, and weather image to display in a div as they do on the forecast page – https://forecast.weather.gov ?
1) I would get the lat,lng for the location I wanted with Google Maps or some other service or API.
2) Then look up that location in the weather API, using the lat,lon: https://api.weather.gov/points/39.7456,-97.0892
3) In the response above you will see an “hourly” forecast URI to access the current weather forecast which includes the icon/image. “hourly” URI example:
https://api.weather.gov/gridpoints/TOP/31,80/forecast/hourly
The hourly forecast current icons/images look like this:
https://api.weather.gov/icons/land/day/bkn?size=small
Thank you so much! That helped clear things up! I have it working now. This post might become very popular now that WU has made big changes to their API Keys.
Great information. Thank you! I must be missing something, and I hope you can point me in the right direction. When I’m pulling latest observation data, the temps come up in Celsius. Is there a way to pull temp data in Fahrenheit?
Joe, As far as I know you have to convert the temp on your own: $F = ($C * 1.8) + 32;
Thanks so much for this! It really helped point me in the right direction! Figured I would leave a friendly comment for those that use cURL.
$lat_long = $lat . ‘,’ . $long;
$noaa_url = ‘https://api.weather.gov/points/ . $lat_long;
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
‘Accept: application/geo+json;version=1’,
‘User-agent: YOURWEBSITE (you@yourdomain.com)’
]);
curl_setopt($ch, CURLOPT_URL, $noaa_url);
$result = curl_exec($ch);
curl_close($ch);
$result = json_decode($result, true);
Thanks again! This really was a huge time saver!
I have a silly question. What language are you using? It looks like JS but I have never seen that many $ sine basic in the early 1980’s. I am not a JS expert. I generally write a few lines and then spend a few hours looking up errors. Tremors are not helping much either 🙂
The code samples are in PHP. If you know JS syntax picking up PHP is not that bad.
I’m looking for the definition of the terms used by the NWS API to help understand the context for terms like: map, grid, current, forecast etc. related to data returned from requests.
For example, what is the definition for a grid? How is a grid define by the NWS? What is the size of a grid? Is the grid dynamic? There are many grid systems used by maps, such as: USNG, UTC, MGRS etc.
Is there a link to a NWS page that contains term definitions and examples of API requests? I understand the NWS is using JSON-LD, but still, there should be more documentation, yes?
Thanks you,
Mark
In the past I could get a forecast by zip code by using “http://forecast.weather.gov/zipcity.php?inputstring=10000”
Is there still a way to get the forecast by zip code with the new api? I have tried something like this but it has not worked.
https://api.weather.gov/zip_code/10000“
Can you help with trying to get the observations for a specific station with a start and end date?
When the following is tried there is no observations returned.
https://api.weather.gov/stations/KFAR/observations?start=2018-03-06T17:12:26Z&end=2018-03-07T17:12:26Z
Thanks for this. When trying to retrieve the forecast for a given lat, lon pair, I am getting this error message:
Any idea of what’s going on?
Thanks
Hi Vincent,
I have not seen that error. Send the the location (lat,lng) and I’ll try it.
I’m seeing this error as well. https://api.weather.gov/gridpoints/BMX/65,88/forecast
I am currently getting that error for the following url:
https://api.weather.gov/gridpoints/HGX/61,101
Can you explain Noaa’s point in adding php DateInterval to validTime?
Could it mean for example PT2H – for this hour and next the value is the same?
Yes, exactly. Below is a sample of temperatures pulled from https://api.weather.gov/gridpoints/GYX/36,21
In the sample you will see:
[validTime] => 2017-10-25T07:00:00+00:00/PT2H covers 2 hours (7AM, 8AM)
[validTime] => 2017-10-25T09:00:00+00:00/PT3H covers 3 hours (9AM, 10AM, 11AM)
[validTime] => 2017-10-25T12:00:00+00:00/PT1H covers 1 hour (12PM)
"temperature": {
"sourceUnit": "F",
"uom": "unit:degC",
"values": [
{
"validTime": "2017-10-25T07:00:00+00:00/PT2H",
"value": 16.666666666667
},
{
"validTime": "2017-10-25T09:00:00+00:00/PT3H",
"value": 16.111111111111
},
{
"validTime": "2017-10-25T12:00:00+00:00/PT1H",
"value": 17.222222222222
},
Appreciate your confirmation.
Thanks
I’m trying to do this same thing in VBA, but all I’m getting is “Method Not Allowed” responses when I try to POST or PUT:
Dim xmlhttp As Object
‘Set xmlhttp = CreateObject(“WinHttp.WinHttpRequest.5.1”)
Set xmlhttp = CreateObject(“MSXML2.serverXMLHTTP”)
xmlhttp.Open “GET”, “https://api.weather.gov/alerts/active/zone/PZZ530”
‘xmlhttp.Open “PUT”, “https://api.weather.gov/products/types/CWF/locations/MTR”, False
xmlhttp.setRequestHeader “Accept”, “application/vnd.noaa.dwml+xml;version=1”
xmlhttp.setRequestHeader “User-Agent”, “OCSCSailing chris@ocsc.com”
xmlhttp.Send
‘xmlhttp.Open “GET”, “https://api.weather.gov/products/types/CWF/locations/MTR”
‘ Send Request.
‘xmlhttp.Send
‘And we get this response
MsgBox xmlhttp.responseText
Not sure but perhaps the issue is you are calling for a format the endpoint does not support. application/vnd.noaa.dwml is only available at /points/{point}/forecast.
The available formats are listed on the API Reference tab.
Great stuff. Thanks!