NWS Weather API: Forecast, Observations and Alerts avatar

NWS Weather API: Forecast, Observations and Alerts

Pricing

from $2.80 / 1,000 location weathers

Go to Apify Store
NWS Weather API: Forecast, Observations and Alerts

NWS Weather API: Forecast, Observations and Alerts

Get the US National Weather Service forecast, latest valid station observation and active alerts for each coordinate or station ID, plus active alerts by state. One flat row per location. Public NWS data, $4.00 per 1,000 rows.

Pricing

from $2.80 / 1,000 location weathers

Rating

0.0

(0)

Developer

Don Mangu

Don Mangu

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

12 days ago

Last modified

Share

NWS weather API for the United States that returns one flat row per location with the National Weather Service forecast, the latest valid station observation and the active alerts, from the public weather.gov API. Add coordinates, station IDs or state codes and run. Each row costs $4.00 per 1,000 on the Free plan, and the prefill run of 3 rows costs about one cent. I built this Actor as an independent developer. It is not affiliated with or endorsed by the National Weather Service or NOAA.

Sample output

One row from a National Weather Service API run for downtown Los Angeles. Values were read from api.weather.gov on 2026-10-04 and change over time. Fields with no value (null) are left out here for space, and the alert text is shortened.

{
"recordType": "location",
"query": "34.0522,-118.2437",
"status": "ok",
"latitude": 34.0522,
"longitude": -118.2437,
"place": "Los Angeles",
"state": "CA",
"timeZone": "America/Los_Angeles",
"forecastOffice": "LOX",
"gridId": "LOX",
"gridX": 155,
"gridY": 45,
"forecastZone": "CAZ368",
"county": "CAC037",
"radarStation": "KSOX",
"forecastGeneratedAt": "2026-10-04T07:45:34+00:00",
"forecastUpdatedAt": "2026-10-04T06:26:38+00:00",
"forecastUnits": "us",
"forecastNowName": "Overnight",
"forecastNowSummary": "Mostly Clear",
"forecastNowTemperature": 77,
"forecastNowTemperatureUnit": "F",
"observationStationId": "KHHR",
"observationStationName": "Hawthorne, Hawthorne Municipal Airport",
"observationStationDistanceKm": 16.5,
"observationStationsTried": 2,
"observationTime": "2026-10-04T07:30:00+00:00",
"observationAgeMinutes": 16,
"observationDescription": "Clear",
"temperatureC": 27,
"temperatureF": 80.6,
"dewpointC": 17,
"relativeHumidityPercent": 54,
"windSpeedKmh": 0,
"windSpeedMph": 0,
"windDirectionDegrees": 0,
"stationPressureHpa": 1009.8,
"visibilityKm": 16.09,
"heatIndexC": 27.7,
"alertCount": 1,
"alertMaxSeverity": "Severe",
"alertsTruncated": false,
"fetchedAt": "2026-10-04T07:45:32.872Z",
"forecastPeriods": [
{
"number": 1,
"name": "Overnight",
"startTime": "2026-10-04T00:00:00-07:00",
"endTime": "2026-10-04T06:00:00-07:00",
"isDaytime": false,
"temperature": 77,
"temperatureUnit": "F",
"precipitationChancePercent": 1,
"windSpeed": "5 mph",
"windDirection": "ENE",
"shortForecast": "Mostly Clear",
"detailedForecast": "Mostly clear, with a low around 77. East northeast wind around 5 mph."
}
],
"alerts": [
{
"id": "urn:oid:2.49.0.1.840.0.469a5488af3dceb8f4d0e41c09f4dbf04bb51c75.002.1",
"event": "Extreme Heat Warning",
"severity": "Severe",
"urgency": "Expected",
"certainty": "Likely",
"status": "Actual",
"messageType": "Update",
"headline": "Extreme Heat Warning issued October 3 at 12:15PM PDT until October 8 at 8:00PM PDT by NWS Los Angeles/Oxnard CA",
"areaDescription": "Catalina and Santa Barbara Islands; Santa Clarita Valley; Ventura County Beaches; Ventura County Inl...",
"sentAt": "2026-10-03T12:15:00-07:00",
"onset": "2026-10-03T12:15:00-07:00",
"ends": "2026-10-08T20:00:00-07:00",
"expires": "2026-10-07T20:00:00-07:00",
"senderName": "NWS Los Angeles/Oxnard CA",
"response": "Execute",
"description": "* WHAT...Dangerously hot conditions with temperatures up to 90 at the\ncoast and 105 in the valleys.\n\n* WHERE...Coast and valleys of Los Angeles and Ve...",
"instruction": "Drink plenty of fluids, stay in an air-conditioned room, stay out of\nthe sun, an..."
}
]
}

How to use the National Weather Service API with this Actor

  1. Open the Actor and add Coordinates, one latitude and longitude pair per line, for example 47.6062,-122.3321. The prefill has two cities.
  2. Add Station IDs such as KSEA or KDEN when you want the observation of one named station. Each ID returns that station's latest report with the forecast and alerts for its location.
  3. Add State codes such as WA, TX or PR for one row of active alerts per state, territory or marine area.
  4. Open Advanced options to change the number of forecast periods (1 to 14), the units (US or SI), the parts of each row and the alert filters.
  5. Click Start. Rows appear in the dataset as they are saved. Use the Overview table, or export to JSON, CSV or Excel.

You can also call the Actor from code through the Apify API. The example below returns active Extreme and Severe alerts for three states.

curl -X POST "https://api.apify.com/v2/acts/conserving_celerytop~nws-weather-forecast-alerts-api/run-sync-get-dataset-items" \
-H "Authorization: Bearer <YOUR_APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"alertStates": ["TX", "LA", "FL"], "alertSeverities": ["Extreme", "Severe"]}'

What data you get from the weather.gov API

Every row has the same columns. A column that does not apply to a row is null, for example the forecast columns on a state row.

GroupFields
RowrecordType (location or state_alerts), query, status, statusMessage, sourceUrl, fetchedAt
Placelatitude, longitude, place, state, timeZone, forecastOffice, gridId, gridX, gridY, forecastZone, county, radarStation
ForecastforecastGeneratedAt, forecastUpdatedAt, forecastUnits, forecastNowName, forecastNowSummary, forecastNowTemperature, forecastNowTemperatureUnit, forecastPeriods (list of periods with name, start, end, temperature, precipitation chance, wind, short and detailed forecast)
Latest observationobservationStationId, observationStationName, observationStationDistanceKm, observationStationsTried, observationTime, observationAgeMinutes, observationDescription, temperatureC, temperatureF, dewpointC, relativeHumidityPercent, windSpeedKmh, windSpeedMph, windGustKmh, windDirectionDegrees, seaLevelPressureHpa, stationPressureHpa, visibilityKm, heatIndexC, windChillC, precipitationLastHourMm, precipitationLast3HoursMm, precipitationLast6HoursMm
Active alertsalertCount, alertMaxSeverity, alertCountsBySeverity, alertsTruncated, alerts (list with event, severity, urgency, certainty, headline, area, sent, onset, ends, expires, sender, response, description and instruction)

The latest observation comes from the nearest station that reports a valid temperature. The Actor reads the stations of the grid in distance order, skips a station whose report has no temperature or is older than 6 hours, and tries up to 5 stations. observationStationsTried shows how many it needed.

The status column says what happened for the row:

StatusMeaningCharged
okEvery part you switched on is in the rowyes
partialOne part is missing, and statusMessage says which and why, for example a marine grid without a forecastyes
outside_coverageThe NWS has no data for the point, for example a point in another country or in open oceanyes
station_not_foundThe NWS knows no station with that IDyes
area_not_acceptedThe NWS did not accept the area codeyes
source_unavailableThe NWS did not answer for this location after 3 attemptsyes

NWS weather API pricing

Pricing is pay per event. One event is one saved row (one location or one state), plus the standard Actor start event.

PlanPrice per rowPrice per 1,000 rows
Free$0.0040$4.00
Bronze$0.0036$3.60
Silver$0.0032$3.20
Gold$0.0028$2.80

Worked example: a weather check of 100 coordinates plus the alerts of 5 states is 105 rows. On the Free plan that is 105 x $0.004 = $0.42, plus $0.00005 for the Actor start, so about $0.42 in total. The same run on the Gold plan costs $0.29.

How charging works:

  • A row is charged only after it is saved to the dataset.
  • A row that carries a status such as outside_coverage or station_not_found is charged, because the NWS lookups for it were made.
  • A row with the status source_unavailable is saved and charged too, because the attempts were made. Three such rows in a row stop the run, so at most a few rows are affected. Run those locations again later.
  • Input the Actor rejects before any request (for example a text value that is not a coordinate pair) ends the run with a plain message and charges nothing.
  • Repeated entries in the input are removed before the run, so a location is charged once.
  • The run stops when the maximum charge you set for the run is reached.

Input example

{
"coordinates": ["47.6062,-122.3321", "34.0522,-118.2437"],
"stationIds": ["KSEA"],
"alertStates": ["WA"],
"forecastPeriods": 4,
"units": "us",
"alertSeverities": ["Extreme", "Severe"]
}

Output example for a state alert row

A state code returns one row with the active alerts of that state, most severe first. Values were read on 2026-10-04.

{
"recordType": "state_alerts",
"query": "TX",
"status": "ok",
"state": "TX",
"alertCount": 3,
"alertMaxSeverity": "Moderate",
"alertCountsBySeverity": {
"Extreme": 0,
"Severe": 0,
"Moderate": 2,
"Minor": 1,
"Unknown": 0
},
"alertsTruncated": false,
"alerts": [
{
"event": "Rip Current Statement",
"severity": "Moderate",
"urgency": "Expected",
"certainty": "Likely",
"headline": "Rip Current Statement issued October 3 at 9:32AM CDT until October 4 at 9:00AM CDT by NWS Houston/Galveston TX",
"onset": "2026-10-03T09:32:00-05:00",
"ends": "2026-10-04T09:00:00-05:00",
"expires": "2026-10-04T09:00:00-05:00",
"senderName": "NWS Houston/Galveston TX"
}
],
"fetchedAt": "2026-10-04T07:45:37.167Z"
}

Use cases for a weather.gov forecast and alerts feed

  • Check the forecast, the current conditions and any warning for a list of job sites, stores, venues or fields in one run.
  • Watch active Extreme and Severe alerts for the states where you operate, on an hourly schedule.
  • Add current temperature, wind and visibility from the nearest working station to a logistics or insurance sheet.
  • Give an AI agent one row per place with the forecast, the latest observation and the alerts, so it needs no extra calls.
  • Pull the same forecast the NWS publishes for a grid cell and compare it with the observed value later.

Run it every day

Switch on Only new since the last run and the Actor saves a row only for a place that has an alert it has not delivered to you before.

  1. Fill the input with your coordinates, station IDs and state codes. Keep Active alerts on. Pick the severities you want in Alert severities.
  2. Switch on Only new since the last run and enter a Monitor name, for example job-sites. Use one name per saved task.
  3. Click Save as task and run it once. The first run saves a row for every place with an active alert and becomes the baseline.
  4. In the Apify Console, open Schedules, click Create new, pick your Task, and enter a cron expression for once a day, for example 0 6 * * *. An alert can come and go within a day, so use a shorter schedule, for example every hour, if you need to see short alerts.
{
"coordinates": ["47.6062,-122.3321", "34.0522,-118.2437"],
"alertStates": ["WA"],
"alertSeverities": ["Extreme", "Severe"],
"onlyNew": true,
"monitorName": "job-sites"
}

How a row looks in this mode: the row has the same fields as before, with the forecast and the latest observation, and alerts lists only the new alerts. alertCount and alertCountsBySeverity count the new alerts only. A place with no new alert gets no row, the Actor does not read its forecast and observation, and it costs nothing. Alerts that were skipped as already delivered are not charged. If a row has more new alerts than Maximum alerts per row, the alerts beyond that number are not remembered and come with the next run if they are still active.

The Actor remembers each alert per place, so an alert that covers two of your places is delivered once in each place. An alert whose NWS alert id the monitor has not seen is delivered as new. A place outside the NWS coverage, or an unknown station ID or state code, returns its status row once and is then skipped. If the NWS cannot give the alerts of a place, that place gets no row and no charge, and the run message says how many places could not be checked. STATS has the counts: locationsWithNewAlerts, locationsWithoutNewAlerts and locationsNotChecked.

The memory lives in your own key-value store, named nws-monitor-<monitor name>. It holds ids only: the place and the NWS alert id. Alerts expire, and the oldest ids are dropped first when the memory grows past 150,000 ids. If you change the alert severities, the Actor starts a separate memory, and its first run saves the active alerts again. You can add and remove places without losing the memory.

Worked cost example on the Free plan, with the prices in the pricing table above ($0.004 per row, $0.00005 for the start). Say you watch 100 coordinates and on a day 4 places get a new alert. That day costs 4 x $0.004 = $0.016 plus $0.00005, so $0.01605. Thirty such days cost 30 x $0.01605 = $0.4815. A day with no new alert costs only the start fee of $0.00005. The same 100 coordinates run daily without Only new return 100 rows every day: 100 x $0.004 = $0.40 plus $0.00005, so $0.40005 a day and 30 x $0.40005 = $12.0015 in 30 days. The 4 places per day is an example, not a measured value.

  • RSS Feed Reader reads news and agency feeds into a table.
  • More Actors by the same author are on the author's Apify profile.

FAQ

The Actor reads the public weather.gov API without a login, a key or a proxy, and it returns weather data only, with no personal data. The NWS says: "All of the information presented via the API is intended to be open data, free to use for any purpose." and "A User Agent is required to identify your application." The Actor sends a User-Agent that names itself. The NWS disclaimer says its information "[is] in the public domain, unless specifically noted otherwise, and may be used without charge for any lawful purpose" so long as you do not claim it as your own, imply an endorsement or affiliation with NOAA or the NWS, or modify it and present it as official government material. This Actor reformats NWS data into rows, shortens long alert text, and is not official. For decisions that affect safety, read the original warnings at weather.gov. This is not legal advice.

Which NWS endpoints does it use?

Only api.weather.gov: the points lookup (coordinate to grid), the gridpoint forecast, the stations of a grid, the latest observation of a station, the station record, and active alerts by point or by area. Grid lookups are cached for the run, and a forecast, a station list and an observation are shared by locations in the same grid cell.

How fast does it run and how does it treat the NWS rate limit?

The NWS does not publish its rate limit and says it allows "a generous amount for typical use". The Actor keeps to 4 requests per second at most, waits for the time in a Retry-After header when the NWS asks for it, and stops with the rows saved so far when the NWS refuses requests (status 403). A run needs about 5 requests per location. A run of 500 locations took about 10 minutes in the test.

What are the limits?

  • Up to 500 locations (coordinates, station IDs and state codes together) per run. Split larger lists across runs.
  • Coverage is the United States, its territories and nearby waters. The NWS has no data for points in other countries.
  • The NWS API takes coordinates, not addresses, ZIP codes or place names. Convert them to latitude and longitude first, then add them as coordinates.
  • Forecasts for marine grids are not supported by the NWS, so a point on open water can have an observation and alerts with no forecast.
  • The forecast has up to 14 periods (7 days). Alert descriptions are cut at 1,500 characters and instructions at 600.
  • A row lists up to 200 alerts (50 by default, set by Maximum alerts per row), most severe first. alertCount always shows the full total.
  • The observation is the latest report of the nearest working station, not a reading at the exact coordinates. observationStationDistanceKm shows the distance.

Why did my run stop early or return fewer rows?

Open the STATS record in the key-value store. The status field says why: succeeded, succeeded_with_gaps, invalid_input, rate_limited, blocked, source_unavailable, charge_limit_reached or unexpected_error. The status message on the run page repeats it in a sentence. After source_unavailable, rate_limited or blocked, the rows saved so far are kept, and a new run a few minutes later continues the work.

Why does a row have the status partial?

One part of the row was missing from the NWS at that moment. Read statusMessage. A marine grid has no forecast, and a remote area can have no station with a valid temperature in the last 6 hours.

A coordinate returned outside_coverage. What now?

Check that latitude comes first and longitude second, and that western longitudes are negative, for example 47.6062,-122.3321. A point in Canada, Mexico or another country returns this status too.

Can I schedule it?

Yes. Use an Apify schedule with the same input. Each run reads the current forecast, observation and alerts.

If this saved you time, a rating helps others find it.