How to Use the National Weather Service (NWS) API with Python Example Code

Posted by

The National Weather Service(NWS) API, provided by the U.S. National Weather Service, is a free public data API that offers a wide range of weather information. One of its key benefits is that it can be used without an API key, making it easy to access. In this post, we will explore how to use the NWS API with Python and examine the returned results.

Introduction to the National Weather Service(NWS) API

The NWS API has several endpoints that provide various weather data.

What is an Endpoint?

An API endpoint is a digital location where an API receives requests for a specific resource on a server. In the context of an API, an endpoint typically refers to a URL (Uniform Resource Locator) that specifies the resource location on a server.

Each endpoint is designed to access specific types of weather information:

  • /points: Location-based weather data
  • /gridpoints: Grid-based weather data
  • /alerts: Weather alerts and notifications
  • /stations: Weather observation station data

We will provide a more detailed explanation of the various endpoints at the end of this post.

API Key Issuance

The NWS API is free to use and does not require an API key, making it very easy to use.

API Request and Response Format

The NWS API provides data via HTTP requests, and responses are primarily returned in JSON format.


Basic Request Example

Fetching Current Weather Data Based on Location

/point NWS API operates based on location(latitude and longitude). Here, we will look at an example of fetching the current weather data for Dallas, Texas(latitude: 32.7767 N, longitude: -96.7970 W).

First, add the latitude and longitude to the endpoint URL and use requests.get to request and retrieve the data. The data is returned in JSON format, including metadata, identifiers, geographical coordinates, and weather information links. Next, parse the URL for the observation station and use that URL to request the current weather information. Parse and format the current weather information and print it.

import requests

# Latitude and longitude of Dallas
latitude = 32.7767
longitude = -96.7970

# NWS API endpoint
points_url = f"https://api.weather.gov/points/{latitude},{longitude}"

# Fetch location information
response = requests.get(points_url)
data = response.json()

# Extract observation station URL
observation_stations_url = data['properties']['observationStations']

# Fetch observation station data
stations_response = requests.get(observation_stations_url)
stations_data = stations_response.json()
stations = stations_data['observationStations']

# Fetch data from the first observation station
station_url = stations[0]

# Fetch current weather data
current_weather_url = f"{station_url}/observations/latest"
current_weather_response = requests.get(current_weather_url)
current_weather_data = current_weather_response.json()

# Print current weather information
current_observation = current_weather_data['properties']

print("Current Weather")
print(f"Temperature: {current_observation['temperature']['value']}°C")
print(f"Humidity: {current_observation['relativeHumidity']['value']}%")
print(f"Wind Speed: {current_observation['windSpeed']['value']} m/s")
print(f"Wind Direction: {current_observation['windDirection']['value']}°")
print(f"Weather Description: {current_observation['textDescription']}")

Output

Current Weather
Temperature: 30°C
Humidity: 77.340048483797%
Wind Speed: None m/s
Wind Direction: None°
Weather Description: Partly Cloudy

Fetching Weather Alerts and Notifications

In this example, we fetch alerts and notifications by first getting the alert URL via the /points endpoint and then fetching the alert data via the /alerts endpoint.

import requests

# Latitude and longitude of Oklahoma City
latitude = 35.4676
longitude = -97.5164

# NWS API endpoint
points_url = f"https://api.weather.gov/points/{latitude},{longitude}"

# Fetch location information
response = requests.get(points_url)
data = response.json()

# Extract alert URL
forecast_zone_url = data['properties']['forecastZone']

# Fetch alert data
alerts_url = f"https://api.weather.gov/alerts/active?zone={forecast_zone_url.split('/')[-1]}"
alerts_response = requests.get(alerts_url)
alerts_data = alerts_response.json()

# Print alert information
alerts = alerts_data['features']

if alerts:
    print("Current Weather Alerts and Notifications")
    for alert in alerts:
        properties = alert['properties']
        print(f"Title: {properties['headline']}")
        print(f"Event: {properties['event']}")
        print(f"Description: {properties['description']}")
        print(f"Instructions: {properties['instruction']}")
        print("-" * 40)
else:
    print("There are no active weather alerts and notifications.")

Output

Current Weather Alerts and Notifications
Title: Flood Watch issued June 4 at 9:58PM CDT until June 5 at 7:00AM CDT by NWS Norman OK
Event: Flood Watch
Description: * WHAT...Flooding caused by excessive rainfall continues to be
possible.

* WHERE...Portions of central, east central, southeast, and southern
Oklahoma, including the following counties, in central Oklahoma,
Cleveland, Grady, Lincoln, McClain, Oklahoma and Pottawatomie. In
east central Oklahoma, Pontotoc and Seminole. In southeast
Oklahoma, Atoka, Bryan, Coal, Hughes, Johnston and Marshall. In
southern Oklahoma, Garvin and Murray.

* WHEN...Until 7 AM CDT Wednesday.

* IMPACTS...Excessive runoff may result in flooding of rivers,
creeks, streams, and other low-lying and flood-prone locations.
Area creeks and streams are running high and could flood with more
heavy rain.

* ADDITIONAL DETAILS...
- A complex of storms is expected to bring heavy rain to areas
already saturated from previous rains.
- http://www.weather.gov/safety/flood
Instructions: You should monitor later forecasts and be alert for possible Flood
Warnings. Those living in areas prone to flooding should be prepared
to take action should flooding develop.
----------------------------------------

Detailed Description of Endpoints

/points

Provides weather information for a specific location(latitude and longitude).

  • Example: https://api.weather.gov/points/{latitude},{longitude}
  • Returns: Forecast and grid point URLs, observation station information, etc.

/gridpoints

Provides detailed weather information for a specific grid point.

  • Example: https://api.weather.gov/gridpoints/{wfo}/{x},{y}
  • Returns: Weather forecast data for a specific grid point.

/alerts

Provides weather alerts and notifications for a specific area.

  • Example: https://api.weather.gov/alerts/active?area={state}
  • Returns: Active weather alerts and notifications.

/stations

Provides data from weather observation stations.

  • Example: https://api.weather.gov/stations/{stationId}/observations/latest
  • Returns: Latest observation data from a specific station.

Advanced Example

Visualizing 7-Day Forecast Data

Here is an example of fetching and visualizing the 7-day forecast data for Dallas(latitude: 32.7767 N, longitude: -96.7970 W). Use the code below to create a more visually appealing forecast chart.

import requests
import pandas as pd
import matplotlib.pyplot as plt

# Latitude and longitude of Dallas
latitude = 32.7767
longitude = -96.7970

# NWS API endpoint
points_url = f"https://api.weather.gov/points/{latitude},{longitude}"
response = requests.get(points_url)
data = response.json()

# Extract forecast URL
forecast_url = data['properties']['forecast']

# Fetch forecast data
forecast_response = requests.get(forecast_url)
forecast_data = forecast_response.json()

# Extract high/low temperature data by date
periods = forecast_data['properties']['periods']
dates = [period['startTime'][:10] for period in periods if period['isDaytime']]
highs = [period['temperature'] for period in periods if period['isDaytime']]
lows = [period['temperature'] for period in periods if not period['isDaytime']]

# Create a DataFrame
df = pd.DataFrame({
    'Date': dates[:len(lows)],
    'High': highs[:len(lows)],
    'Low': lows
})

# Visualize the data
plt.figure(figsize=(10, 5))
plt.plot(df['Date'], df['High'], label='High Temp (F)', marker='o')
plt.plot(df['Date'], df['Low'], label='Low Temp (F)', marker='o')
plt.fill_between(df['Date'], df['High'], df['Low'], color='grey', alpha=0.2)
plt.xlabel('Date')
plt.ylabel('Temperature (°F)')
plt.title('7-Day Temperature Forecast for Dallas, TX')
plt.xticks(rotation=45)
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

Output

Error Handling and Exception Management

When using the NWS API, various errors can occur, so it is important to handle potential exceptions.

import requests
import json

# Latitude and longitude of Dallas
latitude = 32.7767
longitude = -96.7970

# NWS API endpoint
points_url = f"https://api.weather.gov/points/{latitude},{longitude}"

try:
    # Fetch location information
    response = requests.get(points_url)
    response.raise_for_status()
    data = response.json()
    
    # Extract forecast URL from location information
    forecast_url = data['properties']['forecast']
    
    # Fetch forecast data
    forecast_response = requests.get(forecast_url)
    forecast_response.raise_for_status()
    forecast_data = forecast_response.json()
    
    # Print current weather information
    forecast_data_string = json.dumps(forecast_data, indent=4, sort_keys=True)
    print(forecast_data_string)

except requests.exceptions.RequestException as e:
    print(f"HTTP Request Error: {e}")
except KeyError as e:
    print(f"Data Processing Error: {e}")
except Exception as e:
    print(f"Other Error: {e}")

Conclusion

Using the National Weather Service(NWS) API, you can fetch various real-time weather data across the United States for free, without the need for a separate API key, making it very convenient to use.

The NWS API provides location-based weather information, alerts, and observation station data through various endpoints. With simple HTTP requests, you can retrieve data in JSON format, making it easy to process and further analyze the data.

Leave a Reply

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다