truewire-weather-gov
A typed, validated, async Python client for the US National Weather Service API: forecasts, hourly forecasts, the raw gridded data behind both, station observations, and every watch, warning and advisory in effect.
Generated by Truewire from a spec of what the API puts on the wire, and checked against recordings of real responses.
Into a fresh virtual environment:
python -m venv .venv
. .venv/bin/activate # on Windows: .venv\Scripts\activate
pip install truewire-weather-gov
The fresh environment matters: PyPI has an unrelated weather-gov package that also
imports as weather_gov, and the two cannot share an environment.
No account, no key, no quota. The service asks one thing: a User-Agent that identifies
the application, with a way to reach you if you have one. That is the contact argument,
and it is required — a default would be a lie about who is calling. Nothing checks the value: for a first try, the placeholder you@example.com in the examples
below works as it is. Before you ship, replace it with something that names you, such as an
email address you read or your project's URL.
Use
Almost everything here is addressed by grid cell rather than by coordinates, so a caller
starts at points.get_point:
import asyncio
from weather_gov import Weather
async def main() -> None:
async with Weather.new(contact='you@example.com') as client:
point = await client.points.get_point(latitude=47.6062, longitude=-122.3321)
forecast = await client.forecast.get_forecast(
office=point['gridId'], grid_x=point['gridX'], grid_y=point['gridY']
)
for period in forecast['periods'][:3]:
print(
f'{period["name"]:<16} {period["temperature"]:.0f}°{period["temperatureUnit"]} {period["shortForecast"]}'
)
asyncio.run(main())
Tonight 56°F Mostly Clear
Wednesday 74°F Sunny
Wednesday Night 57°F Partly Cloudy
Every measurement carries its unit
This API never sends a bare number. A temperature is
{'unitCode': 'wmoUnit:degC', 'value': 13, 'qualityControl': 'V'}, and value is None
wherever the measurement is missing rather than zero — an airport station's windGust
has a value only when there were gusts. The types say so, so the null is hard to forget.
Walking a span of observations
stations.get_observations is paged by time, and the walk knows something hand-written
code usually does not: the service caps a response at 500 observations, keeps the newest,
and says nothing about the ones it withheld. A full page is evidence the span held more, so
stations.get_observations_paged moves end back to the oldest observation it held and
asks again, until the span is done. Await it for every observation in the span, newest
first, or iterate it for one page at a time:
from datetime import datetime, timedelta, timezone
from weather_gov import Weather
async def last_week(client: Weather) -> None:
end = datetime.now(timezone.utc)
# A week is more than 500 observations, so this is several requests -- by design.
observations = await client.stations.get_observations_paged(
'KSEA', start=end - timedelta(days=7), end=end
)
print(len(observations), 'observations')
Everything else
Fifty-eight endpoints across eleven groups, three response vocabularies (GeoJSON, schema.org, JSON-LD) described as they actually arrive, and TypeScript and Rust clients from the same spec.
Full documentation, the spec, and the recordings: https://github.com/truewire-dev/weather-gov
MIT. NWS data is a work of the US government and is in the public domain.
Metadata
Release files for truewire-weather-gov 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| truewire_weather_gov-0.2.0.tar.gz | 70.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| truewire_weather_gov-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 166.5 kB
Release files / truewire_weather_gov-0.2.0.tar.gz
| Download URL | truewire_weather_gov-0.2.0.tar.gz |
|---|---|
| Size | 70.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
768dbafcbcd19bd65c5c6786c1b9d351841a107196fa078dd949a5f03aac68ec
|
|
BLAKE2b-256 checksum How to use checksums |
fcc8d6e80d96e7aba66d18425f5071ee56186c276f1ec4c39c686b3de102db50
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 15, 2026.
Transparency logRelease files / truewire_weather_gov-0.2.0-py3-none-any.whl
| Download URL | truewire_weather_gov-0.2.0-py3-none-any.whl |
|---|---|
| Size | 95.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
10db76141670b7c891e71bf6dcaeb6ebc2ad450da39406a23f66a4f09ca8b555
|
|
BLAKE2b-256 checksum How to use checksums |
8ecdeda26b2add90dea2e33579e99ebd1ffb67feab9508ed641ad626614f3d97
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 15, 2026.
Transparency log