uw-api
Async Python client for the Utility Warehouse customer portal API.
Endpoints are hardcoded (discovered from myaccount.uw.co.uk/) and require no
configuration — just provide credentials.
Installation
pip install uw-api
Usage
import asyncio
from uw_api import UWClient
async def main():
async with UWClient(email="user@example.com", password="secret") as client:
await client.login()
account = await client.gql.get_account()
print(f"Account: {account.account_number}")
bills = await client.gql.get_bills()
for bill in bills:
print(f"Bill {bill.bill_id}: £{bill.total_amount_gbp}")
consumption = await client.gql.get_consumption()
print(f"Electricity: {consumption.electricity_kwh} kWh")
print(f"Gas: {consumption.gas_kwh} kWh")
meters = await client.gql.get_meters()
for meter in meters:
print(f"{meter.meter_type}: {meter.meter_number} (smart={meter.is_smart})")
tariff = await client.gql.get_tariff()
if tariff:
print(f"Tariff: {tariff.tariff_name}")
asyncio.run(main())
API Reference
Auth
client = UWClient(email="...", password="...")
await client.login()
Authenticates via OAuth2 PKCE at account.uw.co.uk/v2/login. Session cookies are
managed automatically. The library re-authenticates on 401 responses.
Account
account = await client.gql.get_account()
Returns UWAccount with account_id and account_number.
Energy
consumption = await client.gql.get_consumption()
services = await client.gql.get_energy_services()
usage = await client.gql.get_energy_usage()
get_consumption()→EnergyConsumption(latest electricity/gas kWh)get_energy_services()→ raw list of energy service dictsget_energy_usage()→ list ofEnergyUsagewith per-meter readings
Meters
meters = await client.gql.get_meters()
readings = await client.gql.get_meter_readings()
get_meters()→ list ofMeter(type, serial, smart status, last reading date)get_meter_readings()→ list ofMeterReading(value, type, date, source)
Bills
bills = await client.gql.get_bills()
pdf_url = await client.gql.get_pdf_url(month=1, year=2026)
get_bills()→ list ofBill(ID, date, amount, status, PDF URL)get_pdf_url(month, year)→ str URL for the bill PDF
Financial
balance = await client.gql.get_balance()
services = await client.gql.get_live_services()
tariff = await client.gql.get_tariff()
get_balance()→{"due": float, "overdue": float}get_live_services()→ dict of service statusesget_tariff()→EnergyTariff(name, code, rates)
Hardcoded Endpoints
| Purpose | URL |
|---|---|
| Login page | https://account.uw.co.uk/v2/login |
| GraphQL API | https://myaccount.uw.co.uk/server/graphql |
11 GraphQL operations are embedded in uw_api/graphql/queries.py.
Discovery Script (optional)
A HAR-based discovery script is included for verifying or re-discovering endpoints:
python scripts/discover_api.py parse-har capture.har
This is not required for normal use — the library ships with hardcoded
endpoints discovered from myaccount.uw.co.uk/ in July 2026.
Architecture
UWClient → UWAuth (OAuth2 PKCE)
→ UWGraphQL → /server/graphql (POST)
→ Pydantic v2 models
- Auth: CSRF token extraction from login page HTML, form-encoded POST with Castle.io device token
- GraphQL: All data via
POST /server/graphqlwith operation-oriented queries - Retry: 3 attempts with exponential backoff on 429/5xx, re-auth on 401
- Models:
UWAccount,EnergyUsage,EnergyConsumption,EnergyTariff,Meter,MeterReading,Bill,BillPDFMetadata
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 uw_api-0.2.0.tar.gz.
File metadata
- Download URL: uw_api-0.2.0.tar.gz
- Upload date:
- Size: 19.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6acbbfc8f3579b72c7c97b82e38749b4f5bfaf9e996603eb57d2f592b84cabc2
|
|
| MD5 |
306ceeea8c9ffb0dcaf855c5bba038b1
|
|
| BLAKE2b-256 |
ee101104f19c01a7a0d9383607e8a9cf9ce1ee332dcc8b1ae7e2923b450a331f
|
Provenance
The following attestation bundles were made for uw_api-0.2.0.tar.gz:
Publisher:
release-please.yml on KRoperUK/uw-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
uw_api-0.2.0.tar.gz -
Subject digest:
6acbbfc8f3579b72c7c97b82e38749b4f5bfaf9e996603eb57d2f592b84cabc2 - Sigstore transparency entry: 2229309424
- Sigstore integration time:
-
Permalink:
KRoperUK/uw-py@2ef7b4e4ca0239872a37bf758c89dfcb452ec561 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/KRoperUK
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-please.yml@2ef7b4e4ca0239872a37bf758c89dfcb452ec561 -
Trigger Event:
push
-
Statement type:
File details
Details for the file uw_api-0.2.0-py3-none-any.whl.
File metadata
- Download URL: uw_api-0.2.0-py3-none-any.whl
- Upload date:
- Size: 14.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6b934f2dafdce8c5710275c296df4dce3bd7f52b71d9ad870c96bfba5eabde5d
|
|
| MD5 |
dd605c1ce1a405c3d3fdccec5ada0ac5
|
|
| BLAKE2b-256 |
477b324253ef87c6fdacdb007cf266308e17fc103008d99899e5ada92490414a
|
Provenance
The following attestation bundles were made for uw_api-0.2.0-py3-none-any.whl:
Publisher:
release-please.yml on KRoperUK/uw-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
uw_api-0.2.0-py3-none-any.whl -
Subject digest:
6b934f2dafdce8c5710275c296df4dce3bd7f52b71d9ad870c96bfba5eabde5d - Sigstore transparency entry: 2229310074
- Sigstore integration time:
-
Permalink:
KRoperUK/uw-py@2ef7b4e4ca0239872a37bf758c89dfcb452ec561 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/KRoperUK
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-please.yml@2ef7b4e4ca0239872a37bf758c89dfcb452ec561 -
Trigger Event:
push
-
Statement type: