Pythonic, typed, modern client for the Hubeau water data APIs.
Project description
hubeau-data
Typed, modern Python client for the Hub'Eau water data APIs.
Hub'Eau exposes 15+ REST APIs for French national water data — but no official typed Python client exists. This library fills that gap: Pydantic v2 models, strict typing, and a clean interface ready for data science workflows.
Quickstart
from hubeau_data.client import HubeauClient
from hubeau_data.models.hydrometrie import ObservationTrParams
from hubeau_data.models.qualite_rivieres import StationPcParams
client = HubeauClient()
# Hydrométrie — real-time observations
params = ObservationTrParams(code_station=["Y120201001"], size=3)
observations = client.hydrometrie.get_observations_tr(params=params)
print(observations[0].date_obs, observations[0].resultat_obs)
# Qualité Rivières — water quality stations
stations = client.qualite_rivieres.get_stations(
params=StationPcParams(code_departement=["75"], size=3)
)
print(stations[0].code_station, stations[0].libelle_station)
# Eau potable — drinking water analyses for a commune
from hubeau_data.models.eau_potable import ResultatEauPotableParams
resultats = client.eau_potable.get_resultats_dis(
params=ResultatEauPotableParams(code_commune=["75056"], size=5)
)
print(resultats[0].libelle_parametre, resultats[0].resultat_numerique)
# Phytopharmaceutiques — national pesticide sales
from hubeau_data.models.phytopharmaceutiques import VenteSubstanceParams
ventes = client.phytopharmaceutiques.get_ventes_substances(
params=VenteSubstanceParams(type_territoire="National", size=5)
)
print(ventes[0].libelle_substance, ventes[0].quantite, ventes[0].annee)
# API health check — works on every API
report = client.hydrometrie.check_health(n_requests=3)
print(report.summary())
# Data coverage — spot-check stations
cov = client.hydrometrie.data_coverage(code_station="Y120201001")
print(cov.summary())
Async client
For bulk data collection — e.g. fetching many stations before inserting into a database —
AsyncHubeauClient mirrors the sync client and supports asyncio.gather() for parallel requests:
import asyncio
from hubeau_data.async_client import AsyncHubeauClient
from hubeau_data.models.hydrometrie import ObservationTrParams
async def main():
async with AsyncHubeauClient() as client:
codes = ["Y120201001", "K418001001", "A1234567"]
tasks = [
client.hydrometrie.get_observations_tr(
params=ObservationTrParams(code_station=[c], size=10)
)
for c in codes
]
results = await asyncio.gather(*tasks)
for code, obs in zip(codes, results):
print(code, len(obs), "observations")
asyncio.run(main())
All 11 APIs are available on AsyncHubeauClient with the same method names as the sync client
(get_sites, get_stations, etc.) — just await them. Retry logic (tenacity) applies to async
requests too. check_health and data_coverage are sync-only (diagnostic tools, not bulk operations).
API Coverage
| API | Status | Notes |
|---|---|---|
| Hydrométrie | ✅ Supported | Sites, stations, real-time and elaborated observations |
| Qualité des cours d'eau | ⚠️ Partial | Stations and analyses. Upstream API has known stability issues |
| Piézométrie | ✅ Supported | Stations, chroniques, chroniques temps réel |
| Qualité des nappes | ⚠️ Partial | Stations and analyses. Known 503/timeout issues |
| Écoulement | ✅ Supported | Stations, observations, campaigns |
| Température | ✅ Supported | Stations and chroniques |
| Prélèvements en eau | ✅ Supported | Ouvrages, points de prélèvement, chroniques |
| Hydrobiologie | ✅ Supported | Stations, indices (IBGN/IBMR/IBD/IPR), taxons |
| Poisson | ✅ Supported | Stations, indicateurs IPR/IPR+, observations, operations |
| Qualité eau potable | ✅ Supported | Communes/UDI links, analysis results |
| Phytopharmaceutiques | ✅ Supported | Purchases and sales by substance and product |
| Surveillance Littoral | 🚫 Skipped | API being decommissioned by Hub'Eau |
| Indicateurs Services | 🚧 Maintenance | API under maintenance — see services.eaufrance.fr |
All supported APIs expose check_health(n_requests) and data_coverage(...), and are available
on both HubeauClient (sync) and AsyncHubeauClient (async, except health/coverage).
Features
- Pydantic v2 models for all responses — strict runtime validation, IDE autocomplete
- Typed query
Paramsmodels for every endpoint — no more**kwargs - Sync (
HubeauClient) and async (AsyncHubeauClient) clients, same method names - Automatic retry with exponential backoff (tenacity) on transient errors — Hub'Eau APIs have known stability issues
check_health(n_requests)— latency stats per endpoint, healthy ratiodata_coverage(...)— data availability windows per station or territory- Optional extras:
[dataframe],[geo],[viz]— install only what you need
Stack
- Python 3.13+,
mypy --strict,ruff,uv,hatchling, src-layout httpx+tenacityfor resilient sync/async HTTPpytest-httpxmocked test suite — CI runs without network dependency
Installation & Development
git clone https://github.com/pfei/hubeau-data.git
cd hubeau-data
uv sync # core only
uv sync --all-extras # with pandas, geopandas, matplotlib
uv run ruff check . # lint
uv run mypy . # type check
uv run pytest -m "not live" # fast mocked tests (CI)
uv run pytest -m "live" -s # real network integration tests
Examples & Scripts
uv run python examples/demo.py
uv run jupyter lab # open examples/demo.ipynb
Health check scripts for every API under scripts/<api>/check_health.py:
uv run python scripts/hydrometrie/check_health.py --n-requests 3 --random
uv run python scripts/qualite_rivieres/check_health.py --n-requests 2
uv run python scripts/eau_potable/check_health.py --commune 75056
uv run python scripts/phytopharmaceutiques/check_health.py
Exploration scripts under scripts/qualite_rivieres/ and scripts/hydrometrie/.
Roadmap
- Full Hub'Eau API coverage (11 APIs implemented)
-
check_healthanddata_coverageon all APIs - Typed
Paramsmodels for every endpoint - Automatic retry with exponential backoff (tenacity)
- Async client (
AsyncHubeauClient, all 11 APIs) - Optional dependency groups —
pandas,geopandas,matplotlibas extras -
CHANGELOG.md+CONTRIBUTING.md - PyPI release
License
MIT © Pierre Feilles
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
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 hubeau_data-0.0.1.tar.gz.
File metadata
- Download URL: hubeau_data-0.0.1.tar.gz
- Upload date:
- Size: 165.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
31ec1943c29fcd8598375a454cef343afa7f0650e4e95e97a3bba93d6a463b05
|
|
| MD5 |
dd9a91264518b712d2c3b5b455f7b36d
|
|
| BLAKE2b-256 |
80f10f3f39e0170994bb35f28bd9e7633d5deea9a8801259874dac51c62218e0
|
File details
Details for the file hubeau_data-0.0.1-py3-none-any.whl.
File metadata
- Download URL: hubeau_data-0.0.1-py3-none-any.whl
- Upload date:
- Size: 50.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
83a186690a3ea0e281132ce4f36b9e5916b932862c1bcc736c003d3ffe453055
|
|
| MD5 |
fb8f39ab6a979d416458e430080148d8
|
|
| BLAKE2b-256 |
387c0529fc6adb6de67bcbe7859cae0c72cab6350b39bfeb1f24249e33380aa0
|