canwxdb-py
Python client for the wxdb.ca API — historical Canadian weather observations from Environment and Climate Change Canada, queryable by geography and time range.
wxdb.ca is a community project and not affiliated with or endorsed by Environment and Climate Change Canada.
Installation
pip install canwxdb
Optional extras for richer output formats and progress bars:
pip install canwxdb[pandas] # DataFrame support
pip install canwxdb[geo] # GeoDataFrame support (includes pandas)
pip install canwxdb[progress] # tqdm progress bars
pip install canwxdb[all] # everything above
Quick start
from canwxdb import Client
client = Client()
Look up a station
station = client.station(52)
# {'type': 'Feature', 'geometry': ..., 'properties': {'name': 'ESQUIMALT HARBOUR', ...}}
Find stations near a location
# By lat/lon + radius
stations = client.stations(lat=48.43, lon=-123.37, radius_km=50)
# By Canadian postal code
stations = client.stations(postal_code="V8W1A1", radius_km=25)
# By bounding box (min_lon, min_lat, max_lon, max_lat)
stations = client.stations(bbox=(-124.5, 48.3, -123.0, 49.0))
Fetch observations
# Daily observations for a single station
obs = client.daily(station_id=52, start="2024-01-01", end="2024-12-31")
# Hourly observations
obs = client.hourly(station_id=52, start="2024-07-01", end="2024-07-31")
# Monthly observations
obs = client.monthly(station_id=52, start="1990-01-01", end="2024-12-31")
All three methods accept the same geographic filters as stations().
Date arguments accept ISO 8601 strings, datetime.date, or datetime.datetime objects.
Get a pandas DataFrame
df = client.daily(
station_id=52,
start="2024-01-01",
end="2024-12-31",
format="dataframe",
)
df.head()
# date station_id mean_temp_c ... latitude longitude
# 0 2024-01-01 52 -1.2 ... 48.43 -123.43
# 1 2024-01-02 52 0.5 ... 48.43 -123.43
Get a GeoDataFrame (GeoPandas)
gdf = client.daily(
postal_code="V8W1A1",
radius_km=100,
start="2023-01-01",
end="2023-12-31",
format="geodataframe",
)
# Plot mean temperature across stations
gdf.plot(column="mean_temp_c", legend=True, figsize=(10, 6))
The GeoDataFrame uses WGS-84 (EPSG:4326) and has a Point geometry column built from each station's coordinates.
Progress bars (recommended for large queries)
For multi-page queries — especially in Jupyter notebooks — pass show_progress=True to see live row counts. The library automatically uses tqdm.notebook inside Jupyter and plain tqdm elsewhere.
# In a Jupyter notebook this renders a rich notebook-style progress bar.
df = client.daily(
bbox=(-124.5, 48.3, -123.0, 49.0),
start="2015-01-01",
end="2024-12-31",
format="dataframe",
show_progress=True,
)
# Fetching: 45000 rows [00:18, 2490 rows/s]
Limit pages for exploratory queries
When exploring a new dataset, use max_pages to avoid accidentally fetching millions of rows:
# Just peek at the first page
df = client.hourly(
bbox=(-80, 43, -76, 44),
start="2020-01-01",
end="2023-12-31",
format="dataframe",
max_pages=1,
)
Using as a context manager
with Client() as client:
df = client.daily(station_id=52, start="2024-01-01", end="2024-12-31",
format="dataframe")
Connecting to a custom endpoint
client = Client(base_url="https://my-private-instance.example.com")
Output formats
format= |
Return type | Requires |
|---|---|---|
"geojson" (default) |
dict (GeoJSON FeatureCollection) |
— |
"dataframe" |
pandas.DataFrame |
pandas |
"geodataframe" |
geopandas.GeoDataFrame |
geopandas, shapely |
Error handling
from canwxdb import Client, WxDBNotFoundError, WxDBRateLimitError
client = Client()
try:
station = client.station(99999)
except WxDBNotFoundError:
print("Station not found")
# The client automatically retries 429 responses with exponential back-off.
# WxDBRateLimitError is raised only if all retries are exhausted.
| Exception | Raised when |
|---|---|
WxDBNotFoundError |
HTTP 404 |
WxDBRateLimitError |
HTTP 429 after all retries |
WxDBHTTPError |
Any other non-2xx response |
WxDBError |
Base class for all of the above |
Data source
Weather data is sourced from Environment and Climate Change Canada's open data under the Government of Canada Open Government Licence.
Metadata
Release files for canwxdb 1.0.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 | Provenance | Actions |
|---|---|---|---|---|
| canwxdb-1.0.0.tar.gz | 183.8 kB | Without provenance | Details for canwxdb-1.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| canwxdb-1.0.0-py3-none-any.whl | Python 3 | none | any | Details for canwxdb-1.0.0-py3-none-any.whl |
Total release size: 194.4 kB
Release files / canwxdb-1.0.0.tar.gz
| Download URL | canwxdb-1.0.0.tar.gz |
|---|---|
| Size | 183.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b7d13b6d8a0b54c0a437a5a54f96df6d066676bb90141d62fcd097fe1438da8f
|
|
BLAKE2b-256 checksum How to use checksums |
5fb1553dc689dcde0df3ca849bed9f46bcd030593b8f75d5666ecc254b3536b6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.12
|
Release files / canwxdb-1.0.0-py3-none-any.whl
| Download URL | canwxdb-1.0.0-py3-none-any.whl |
|---|---|
| Size | 10.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c28d43ed167680ada8003ee346ae7f50c85319bff122cae10747562924a27ee6
|
|
BLAKE2b-256 checksum How to use checksums |
aab9914de997c3739814f8a5b5d941173187d897763d4db634c7397551bcf7cc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.12
|
Security for canwxdb 1.0.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.