thameswaterapi
pip install thameswaterapi
A Python client for retrieving meter data from Thames Water.
This is a fork of thameswaterclient by Ayrton Bourn.
Python API
from thameswaterapi import ThamesWater
email = "myname@provider.com"
password = "**********"
thames_water = ThamesWater(email=email, password=password)
If you have multiple accounts, you can specify which one to use:
thames_water = ThamesWater(email=email, password=password, account_number=123456789)
Sessions
The first data call establishes a session, by trying the refresh token the
client holds, then a silent authorize against a live sign-in session, then the
password. Only the password step raises AuthenticationError, and it means the
password is wrong — a spent refresh token or a dead session simply falls
through to the next step. A session is always established before a call, never
in response to one failing.
authenticate() does the same thing at a moment of your choosing, replacing
whatever session is there. A long-running client wants that: it can establish
the session where it belongs in its cycle, and store the rotated refresh token
before making any data call.
The refresh token lasts 24 hours and the grant rotates it, so a caller that persists it and polls more often than that submits the password only on the first run and after a gap longer than a day:
thames_water = ThamesWater(
email=email,
password=password,
refresh_token=stored_refresh_token, # from a previous client, optional
cookies=stored_cookies, # likewise, optional
)
thames_water.authenticate()
store(thames_water.refresh_token) # rotated, so store it after every cycle
store(thames_water.cookies)
thames_water.logout() # ends the session server-side
Listing accounts and meters
thames_water.get_account_numbers() # [123456789011, 123456789012]
thames_water.get_meter_numbers() # ['123456789']
Daily usage
from thameswaterapi import lines_to_timeseries
meters = thames_water.get_meters()
readings = lines_to_timeseries(meters.Lines)
for r in readings:
print(r.start, r.usage, r.total)
Hourly usage
import datetime
from thameswaterapi import meter_usage_lines_to_timeseries
meter = thames_water.get_meter_numbers()[0]
start = datetime.date(2024, 10, 1)
end = datetime.date(2024, 10, 31)
meter_usage = thames_water.get_meter_usage(meter, start, end)
readings = meter_usage_lines_to_timeseries(start, meter_usage.Lines)
for r in readings:
print(r.hour_start, r.usage, r.total)
A window of any width works. Hourly labels are clock times that repeat every
day, so meter_usage_lines_to_timeseries takes the hour from the label and the
day from a cursor that advances at every 0:00. A window ending today is
truncated at a whole-day boundary rather than padded, so the days that have not
been published yet are simply absent from the result.
Tariff
Thames Water has no tariff API — metered charges are a fixed annual "Scheme of Charges" published per region (identical for every customer), so the figures are scraped from Thames Water's public metered-customers help page and need no authentication:
from thameswaterapi import get_tariff
tariff = get_tariff()
tariff.clean_water_rate_per_m3 # 2.7346
tariff.wastewater_rate_per_m3 # 1.4721
tariff.water_fixed_per_year # 66.87
tariff.wastewater_fixed_per_year # 128.13 (standard rate, not the rebate)
tariff.effective_date # datetime.date(2026, 4, 1)
tariff.volumetric_rate_per_m3 # combined GBP/m3
tariff.unit_rate_per_litre # combined GBP/L
tariff.standing_charge_per_day # combined fixed charge GBP/day
ThamesWater.get_tariff() is also available on an authenticated client (it
reuses the session).
Command line
python -m thameswaterapi EMAIL PASSWORD [options]
Options:
--account-number N— use a specific contract account number (defaults to the account default)--list-accounts— list available contract account numbers and exit--list-meters— list meter serial numbers and exit--meter M— query a specific meter (defaults to first meter)
Examples:
# Show daily and hourly readings for the default account and first meter
python -m thameswaterapi myname@provider.com mypassword
# List available account numbers
python -m thameswaterapi myname@provider.com mypassword --list-accounts
# List meters on a specific account
python -m thameswaterapi myname@provider.com mypassword --account-number 123456789012 --list-meters
# Query a specific meter
python -m thameswaterapi myname@provider.com mypassword --meter 123456789
Release files for thameswaterapi 0.6.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 | |
|---|---|---|---|
| thameswaterapi-0.6.0.tar.gz | 18.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| thameswaterapi-0.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 36.3 kB
Release files / thameswaterapi-0.6.0.tar.gz
| Download URL | thameswaterapi-0.6.0.tar.gz |
|---|---|
| Size | 18.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e50838c099202b35899f2df6b9ebfafb80c5ba65fe9dcea0c297d711b0de51a4
|
|
BLAKE2b-256 checksum How to use checksums |
753d8b17478ac87121c49312046404f5c96c17738b21663233fcfa1fa27f422a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 5, 2026.
Transparency logRelease files / thameswaterapi-0.6.0-py3-none-any.whl
| Download URL | thameswaterapi-0.6.0-py3-none-any.whl |
|---|---|
| Size | 17.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
eed94530b0b2ddf79ab2b164d68b4596cd84a81d28fe22c6e7fd6529f93caa78
|
|
BLAKE2b-256 checksum How to use checksums |
1bef5fccc55571facfafbf39f396a9b9e5e3c849613532232bacfb9eaf22da2a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 5, 2026.
Transparency log