Skip to main content

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

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.5.tar.gz (18.3 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.5-py3-none-any.whl (13.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: weathercloud-0.1.5.tar.gz
  • Upload date:
  • Size: 18.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for weathercloud-0.1.5.tar.gz
Algorithm Hash digest
SHA256 9ba4f954935b9d889541fb50e4ac5847f4f5be0f764784eb9e5c00a6c6cd5e5a
MD5 ad9056ead908ba9848ebfceabd9f7106
BLAKE2b-256 d84aeaa2fe2186cbe7d5e23273ee6d792cc28a8f0aa08d07b1ebd244332d794d

See more details on using hashes here.

Provenance

The following attestation bundles were made for weathercloud-0.1.5.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.5-py3-none-any.whl.

File metadata

  • Download URL: weathercloud-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 13.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for weathercloud-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 e6779a44e1342b05779b65cbc51599c699b10f798cba4fd220932aba0e6bbddd
MD5 f01fe06cbff20e37f4b0a29d89d2dff8
BLAKE2b-256 d2fbb37cdc243bd7cb8b510824e697cd49856ece814e8c57ccfef06e74dd6f82

See more details on using hashes here.

Provenance

The following attestation bundles were made for weathercloud-0.1.5-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.

Release history Release notifications | RSS feed

This release

0.1.5 This release

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page