Unofficial Python client for Weathercloud
Project description
weathercloud
Unofficial, fully-typed Python client for Weathercloud. Read live conditions, station metadata, history, and forecasts from any public station — no account, no API key.
⚠️ Reverse-engineered from the public web app. Not affiliated with or endorsed by Weathercloud, and the upstream endpoints may change without notice.
✨ Highlights
- 🌡️ Typed results —
get_current_conditions()returns aCurrentConditionsdataclass, not a bag of stringly-typed JSON. - 🧱 Raw access too — every endpoint also has a
dict-returning method when you need the full payload. - 🧯 One exception to catch — every failure (network, HTTP, bad JSON) raises
WeathercloudError. - 🧪 Tested & type-checked — ships
py.typed, runs on Python 3.10–3.13.
📦 Installation
pip install weathercloud
🚀 Quick start
from weathercloud import WeathercloudClient
with WeathercloudClient() as client:
cond = client.get_current_conditions("5726468552")
print(cond.temperature) # 22.8
print(cond.humidity) # 62
print(cond.wind_gust) # 1.4
The client owns a requests.Session, so use it as a context manager (or call
client.close()) to release connections. You can also tune the request timeout:
client = WeathercloudClient(timeout=30) # seconds; default is 10
📖 API
get_current_conditions(device_id) → CurrentConditions
Live sensor readings as a typed dataclass — the one you'll call most. Stations
only report the sensors they actually have, so every field is optional: a
reading the station doesn't provide comes back as None rather than raising.
| Field | Type | Unit | Field | Type | Unit |
|---|---|---|---|---|---|
temperature |
float | None |
°C | pressure |
float | None |
hPa |
dew_point |
float | None |
°C | wind_speed |
float | None |
m/s |
wind_chill |
float | None |
°C | wind_speed_avg |
float | None |
m/s |
heat_index |
float | None |
°C | wind_gust |
float | None |
m/s |
humidity |
int | None |
% | wind_direction |
int | None |
° |
rain |
float | None |
mm | rain_rate |
float | None |
mm/h |
solar_radiation |
float | None |
W/m² | uv_index |
int | None |
— |
epoch |
int | None |
unix ts |
get_station_info(device_id, scrape_name=True) → StationInfo
Station metadata. The name isn't exposed by any JSON endpoint, so it's scraped
from the page <title> (one extra request). Pass scrape_name=False to skip it
and use the device_id as the name instead.
info = client.get_station_info("5726468552")
info.name # "Ginometeo"
info.city # "Ingelmunster"
info.altitude # "18.0" (metres, as string)
info.status # "online" | "recently_online" | "offline" | "unknown"
info.seconds_since_update # int
info.account_type # 0 = free, >0 = premium
get_device_stats(device_id) → dict
Current readings plus day / month / year min–max. Each value is a
[unix_timestamp, value] pair, keyed as {sensor}_{period}_{type}.
stats = client.get_device_stats("5726468552")
stats["temp_day_max"] # [1748358122, 30.9]
stats["rain_month_total"] # [1748358122, 12.4]
get_evolution(device_id, variable, period="day") → dict
Hourly history for a single sensor. period is "day", "week", "month", or
"year".
from weathercloud import VariableCode
evo = client.get_evolution("5726468552", VariableCode.TEMPERATURE, "week")
Available codes: TEMPERATURE, HUMIDITY, DEW_POINT, PRESSURE, WIND_SPEED,
WIND_DIRECTION, WIND_GUST, RAIN, RAIN_RATE, SOLAR_RADIATION, UV_INDEX.
get_forecast(device_id) → dict
6-day WMO daily forecast for the station's location.
get_nearby_stations(lat, lon, distance_km=5) → dict
Stations within a radius of a coordinate. ⚠️ Sensor values inside each result are
×10 integers — divide by 10 (e.g. temp: 281 → 28.1 °C).
Other raw methods
client.get_device_values(device_id) # same data as get_current_conditions, raw
client.get_device_info(device_id) # metadata + current values as strings
client.get_wind_rose(device_id) # wind direction distribution
client.get_update_status(device_id) # seconds since last update
client.get_owner_profile(device_id) # observer name, hardware brand/model
client.get_station_name(device_id) # scrape the station name only
🧯 Error handling
Every method raises WeathercloudError on failure — network error, HTTP error,
non-JSON body, or an unexpected response shape. Catch the one type and you're
covered.
from weathercloud import WeathercloudClient, WeathercloudError
try:
cond = client.get_current_conditions(device_id)
except WeathercloudError as exc:
... # set unavailable, log it, retry — your call
🔎 Finding a device ID
It's the number at the end of the station URL:
app.weathercloud.net/d5726468552 → device_id = "5726468552"
METAR (airport) stations use ICAO codes (EBBR, EGLL, …) and work on most
device/* endpoints — just swap the prefix to metar/*.
💡 Notes
- 🔓 No authentication required for any endpoint.
- ⏱️ Poll at most every 10 minutes — that's how often free stations update.
- 🧭 Based on the reverse-engineered OpenAPI spec in this repo.
🛠️ Development
git clone https://github.com/MauroDruwel/Weathercloud-API
cd Weathercloud-API
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
ruff check . # lint
mypy # type-check
pytest # tests
python -m build # build sdist + wheel
CI runs the linter, type checker, and the test matrix (Python 3.10–3.13) on every push and pull request.
Local API explorer (Swagger UI)
A Swagger UI is hosted at weathercloud-api.maurodruwel.be, or run it locally against a small CORS proxy:
pip install flask
python docs/proxy.py # serves the proxy + Swagger UI on :8765
# then open docs/index.html
📄 License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file weathercloud-0.1.1.tar.gz.
File metadata
- Download URL: weathercloud-0.1.1.tar.gz
- Upload date:
- Size: 14.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
343d8ea4652be54d047c1cd128805c476c1c21c7feb538178c57a24d93e37da0
|
|
| MD5 |
b2a8f4fbd4b022f51664838a806988af
|
|
| BLAKE2b-256 |
a5abe2d94ad3de6ed2483c20864c93ebd67b319ec45bb2674ea3d652b0f4cbb6
|
Provenance
The following attestation bundles were made for weathercloud-0.1.1.tar.gz:
Publisher:
publish.yml on MauroDruwel/Weathercloud
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
weathercloud-0.1.1.tar.gz -
Subject digest:
343d8ea4652be54d047c1cd128805c476c1c21c7feb538178c57a24d93e37da0 - Sigstore transparency entry: 1672466240
- Sigstore integration time:
-
Permalink:
MauroDruwel/Weathercloud@c883eff2bc6e5b978fdaeb5e45aeceeb480bc46f -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/MauroDruwel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c883eff2bc6e5b978fdaeb5e45aeceeb480bc46f -
Trigger Event:
release
-
Statement type:
File details
Details for the file weathercloud-0.1.1-py3-none-any.whl.
File metadata
- Download URL: weathercloud-0.1.1-py3-none-any.whl
- Upload date:
- Size: 10.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19651e4c132d992935a647d331f0c5161dc2923170c25bf36ab09edc87a278fe
|
|
| MD5 |
d7af1e94c03d7a7cb736cfcef54c9a2d
|
|
| BLAKE2b-256 |
3f6a8643e1f7f68ddeda6de7b593031098f99543bb5ca09ec8ce277968bf5017
|
Provenance
The following attestation bundles were made for weathercloud-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on MauroDruwel/Weathercloud
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
weathercloud-0.1.1-py3-none-any.whl -
Subject digest:
19651e4c132d992935a647d331f0c5161dc2923170c25bf36ab09edc87a278fe - Sigstore transparency entry: 1672466254
- Sigstore integration time:
-
Permalink:
MauroDruwel/Weathercloud@c883eff2bc6e5b978fdaeb5e45aeceeb480bc46f -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/MauroDruwel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c883eff2bc6e5b978fdaeb5e45aeceeb480bc46f -
Trigger Event:
release
-
Statement type: