Skip to main content

Unofficial Python client for Weathercloud

Project description

weathercloud

PyPI Python CI License: MIT

Unofficial, fully-typed Python client for Weathercloud. Read live conditions, station metadata, history, and forecasts from any public station — no account, no API key (recommended). Authentication is optional and only required if you want to access private indoor sensors (like inside temperature, humidity, and heat index) of a station you own.

⚠️ Reverse-engineered from the public web app. Not affiliated with or endorsed by Weathercloud, and the upstream endpoints may change without notice.

✨ Highlights

  • 🌡️ Typed resultsget_current_conditions() returns a CurrentConditions dataclass, 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

# Public data requires no login:
with WeathercloudClient() as client:
    cond = client.get_current_conditions("5726468552")

print(cond.temperature)   # 22.8
print(cond.humidity)      # 62

# Pass your credentials to fetch private indoor sensors:
with WeathercloudClient(username="my_user", password="my_password") as client:
    cond = client.get_current_conditions("5726468552")

print(cond.inside_temperature)  # 21.5 (None if not logged in)
print(cond.inside_humidity)     # 55

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
# or with both credentials and timeout:
client = WeathercloudClient(username="user", password="pass", timeout=15)

📖 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
inside_temperature float | None °C inside_humidity int | None %
inside_heat_index float | None °C 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 public endpoints (recommended). Supply credentials only if you need to fetch private inside sensors of a station you own.
  • ⏱️ 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
cd Weathercloud
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

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

weathercloud-0.1.3.tar.gz (16.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

weathercloud-0.1.3-py3-none-any.whl (12.2 kB view details)

Uploaded Python 3

File details

Details for the file weathercloud-0.1.3.tar.gz.

File metadata

  • Download URL: weathercloud-0.1.3.tar.gz
  • Upload date:
  • Size: 16.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for weathercloud-0.1.3.tar.gz
Algorithm Hash digest
SHA256 2c9188b3bf69a4dcda376f87fec89812eb9fa8e6a96219fdcd49e8980ad8180e
MD5 6054fb137b02c58477fd0c21653eea7e
BLAKE2b-256 0e1af27318143125ead3f8602842a87899b0d8379eead804993f7862ab553f96

See more details on using hashes here.

Provenance

The following attestation bundles were made for weathercloud-0.1.3.tar.gz:

Publisher: publish.yml on MauroDruwel/Weathercloud

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file weathercloud-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: weathercloud-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 12.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for weathercloud-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 c8c8b2613882ed6fe6f85419800fa6548c27076093e071ae457acc23b055d7ef
MD5 989d80bcd3e975c42855c36cb7637689
BLAKE2b-256 f46fe91521d4bc9908329e774b9c0912ea7400df9620a097fcc68914fd863e5f

See more details on using hashes here.

Provenance

The following attestation bundles were made for weathercloud-0.1.3-py3-none-any.whl:

Publisher: publish.yml on MauroDruwel/Weathercloud

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page