๐ŸŽ‰ Premium Proxies ยท 24-Hour Free TrialClaim Now
Guides

How to Scrape Weather Data: Free APIs First (2026)

Learn how to scrape weather data the smart way: free official APIs (NWS, Open-Meteo, OpenWeatherMap) first, then Weather.com and AccuWeather when you must.

S SparkProxy 0 18 min read
Share
How to Scrape Weather Data: Free APIs First (2026)

Most guides that tell you how to scrape weather data point you straight at Weather.com with a headless browser. That is usually the slowest and most fragile way to get a temperature. Weather is one of the few domains with genuinely good free official APIs, so the right move is to try those first and only scrape a branded site when you actually need its specific numbers. This guide walks the whole ladder: the no-key government feed, two free global APIs, and the exact pattern for pulling data off Weather.com and AccuWeather when nothing else gives you what you need.

Free APIs first: a weather-data decision tree

Here is the insight that saves you a week of maintenance: Weather.com, AccuWeather, and every other consumer weather site are just front-ends over point-forecast models. The underlying numbers, temperature, precipitation probability, wind, humidity, come from a handful of global weather models (GFS, ECMWF, ICON and friends). Government agencies and open projects expose that same modeled data through clean JSON APIs. So before you write a single line of browser automation, ask what you truly need.

  • Do you only need US locations? Use the National Weather Service API. No key, no scraping, no proxy.
  • Do you need anywhere on Earth, plus history back to 1940? Use Open-Meteo.
  • Do you want a batteries-included commercial API with one key? Use OpenWeatherMap or a similar freemium provider.
  • Do you specifically need a branded site's own presentation (AccuWeather's RealFeel, The Weather Channel's narrative summaries, a competitor's displayed values)? Only then does scraping earn its place.

The table below is the short version of that decision.

SourceCoverageKey neededCostBest for
NWS `api.weather.gov`US and territoriesNo (User-Agent only)FreeUS forecasts, alerts, station observations
Open-MeteoGlobalNo (non-commercial)Free tier, paid for commercialForecast plus historical plus climate anywhere
OpenWeatherMapGlobalYes (`appid`)Free tier plus meteredCurrent and short forecast, quick setup
Weather.com (scrape)GlobalNoYour infra plus a proxyThe Weather Channel's specific values
AccuWeather (API or scrape)GlobalAPI: yesFree API 50/day, or scrapeRealFeel and AccuWeather indices

If your answer landed in one of the first three rows, you never touch a browser. Keep reading and you will have live data in a few minutes.

National Weather Service API (US, no key)

The US National Weather Service runs a public REST API at https://api.weather.gov. It needs no API key and no registration. The one hard requirement: send a descriptive User-Agent header that identifies your app and a contact, because the service rejects requests without one. A missing or generic User-Agent is the single most common reason a first NWS call fails.

The API is two steps. You look up a coordinate to get its grid cell, then you read the forecast for that cell.

import requests

UA = {"User-Agent": "(sparkproxy.io weather demo, you@sparkproxy.io)"}

# Step 1: resolve a lat/long to its NWS grid
point = requests.get(
    "https://api.weather.gov/points/30.2711,-97.7437", headers=UA
).json()

# Step 2: read the forecast URL the point handed back
forecast_url = point["properties"]["forecast"]
periods = requests.get(forecast_url, headers=UA).json()["properties"]["periods"]

for p in periods[:3]:
    print(p["name"], p["temperature"], p["temperatureUnit"], "-", p["shortForecast"])

That prints the next few named periods (Tonight, Tuesday, Tuesday Night) with temperatures and a plain-English summary. Swap forecast for forecastHourly in step two and you get hour-by-hour data instead.

For current conditions, the forecast grid is not enough. You want a real observation from a nearby station. The point response also gives you an observationStations URL:

stations = requests.get(
    point["properties"]["observationStations"], headers=UA
).json()["features"]

station_id = stations[0]["properties"]["stationIdentifier"]
latest = requests.get(
    f"https://api.weather.gov/stations/{station_id}/observations/latest", headers=UA
).json()["properties"]

print(latest["temperature"]["value"], "C at", latest["timestamp"])

Those observations are METAR reports from airports and official sensors, so they are the real measured value, not a model output. For severe weather alerts, hit the alerts endpoint directly by state:

curl -H "User-Agent: (sparkproxy.io weather demo, you@sparkproxy.io)" \
  "https://api.weather.gov/alerts/active?area=TX"

The catch is coverage. NWS only serves the United States and its territories. Point at a coordinate in Berlin or Tokyo and you get nothing useful. That is where the next tool comes in.

Free trial

Scraping at scale? Skip the blocks.

Fast, unblockable datacentre proxies with unlimited bandwidth.

Open-Meteo: free global forecast and historical

Open-Meteo is the most useful free weather API for scraping-adjacent work. No key for non-commercial use, roughly 10,000 calls per day on the free tier, global coverage, and a clean query-string interface. One GET request returns current conditions, an hourly forecast, and a daily forecast together.

curl "https://api.open-meteo.com/v1/forecast?latitude=30.27&longitude=-97.74\
&current=temperature_2m,relative_humidity_2m,weather_code,wind_speed_10m\
&hourly=temperature_2m,precipitation_probability\
&daily=temperature_2m_max,temperature_2m_min\
&timezone=auto&temperature_unit=fahrenheit"

You pick exactly which variables you want in each block, which keeps responses small. Do not have coordinates? Open-Meteo ships a free geocoding endpoint too, so a place name becomes lat/long without a second provider:

curl "https://geocoding-api.open-meteo.com/v1/search?name=Austin&count=1"

The part most tutorials miss is historical weather data. Open-Meteo has a separate archive endpoint backed by ERA5 reanalysis from the European Centre for Medium-Range Weather Forecasts, with hourly data going back to January 1940. Same query grammar, different host:

curl "https://archive-api.open-meteo.com/v1/archive?latitude=30.27&longitude=-97.74\
&start_date=2020-01-01&end_date=2020-12-31\
&daily=temperature_2m_max,temperature_2m_min,precipitation_sum&timezone=auto"

That single call returns a full year of daily highs, lows, and rainfall for any coordinate on the planet. Building a weather feature for a model, backtesting a strategy against past conditions, or filling gaps in a sensor log all become trivial. Two things to remember: the free tier is for non-commercial use (commercial projects need a paid API key), and the archive lags real time by about five days because reanalysis is not instant.

OpenWeatherMap and other freemium APIs

When you want a single commercial vendor with an SLA, OpenWeatherMap is the common default. You register for a free appid key and call a REST endpoint. The free tier covers current weather and a 5-day, 3-hour-interval forecast. Historical data and the richer One Call API 3.0 sit behind a paid or metered plan (One Call gives a free daily allotment once you attach a card).

curl "https://api.openweathermap.org/data/2.5/weather?lat=30.27&lon=-97.74\
&appid=YOUR_KEY&units=imperial"

The response is compact JSON with main.temp, weather[0].description, wind.speed, and so on. Other freemium options in the same shape include WeatherAPI.com, Tomorrow.io, and Visual Crossing, each with its own free quota. Pick on quota, variables, and historical depth. If your only worry is "will this key survive a launch," a metered commercial API is calmer than scraping a site that can change its markup any Tuesday.

At this point a lot of projects are done. You have current conditions, forecasts, and history from stable JSON. Scrape only if a branded site holds something these feeds do not.

Forecast, current, and historical: what to pull from where

Different sources are strong at different data types. Match the request to the source that serves it cleanly instead of forcing one API to do everything.

Data typeNWSOpen-MeteoOpenWeatherMapWeather.com / AccuWeather
Current conditionsStation observations (METAR)`current=` block`/data/2.5/weather`Embedded JSON
Hourly forecast`/forecast/hourly``hourly=` blockOne Call 3.0 (paid)Embedded JSON
Daily forecast`/forecast``daily=` block`/forecast`, One CallEmbedded JSON
HistoricalNot in main APIArchive (ERA5, 1940+)Time Machine (paid)Not exposed
Alerts`/alerts/active`LimitedOne Call alertsEmbedded

One nuance worth internalizing: a historical forecast and a historical observation are not the same thing. ERA5 reanalysis (Open-Meteo archive) is a modeled best estimate of what conditions actually were. Station observations (NWS, NOAA's NCEI archive) are measured readings. If you are training a model on "what the weather was," reanalysis is usually what you want. If you need certified measured values for a specific airport, go to the station record. Mixing the two silently corrupts a dataset, and most scraping tutorials never mention it.

When you actually need to scrape Weather.com

Say you specifically need The Weather Channel's own displayed values, maybe you are monitoring how a brand presents conditions, or you need their particular "feels like" narrative. Now scraping is justified. Here is the part that changes everything about how you do it.

Weather.com is a Next.js application. It does not render forecasts into static HTML on the server for you to parse with CSS selectors. Instead, it ships a big JSON blob in a script tag and hydrates the page from it in the browser. That blob lives in