OpenElectricity Python Client
A Python client for the OpenElectricity API, providing access to electricity and energy network data and metrics for Australia.
To obtain an API key visit platform.openelectricity.org.au
For documentation visit docs.openelectricity.org.au.
See CHANGELOG.md for release notes.
Features
- Synchronous and asynchronous API clients
- Fully typed with comprehensive type annotations
- Automatic request retries and error handling
- Context manager support
- Modern Python (3.10+) with full type annotations
- Direct conversion to Pandas and Polars DataFrames
Installation
# or with uv (recommended)
uv add openelectricity
# Install with data analysis support (Polars/Pandas)
uv add "openelectricity[analysis]"
# Install base package with pip
pip install openelectricity
Upgrading to 0.12
0.12.0 fixes the data frame output, which changes it. See the changelog.
to_records()/to_pandas()/to_polars()reportintervalin network time. 0.11.x reported it 10 hours late for the NEM; remove any -10h compensation you added.- Records gain the
region,statusandunit_codegrouping columns that 0.11.x dropped. to_polars()keeps every metric. 0.11.x dropped metrics whose rows started after the first 100.
Quick Start
First, set your API key in the environment:
# Set your API key
export OPENELECTRICITY_API_KEY=your-api-key
# Optional: Override API server (defaults to production)
export OPENELECTRICITY_API_URL=http://localhost:8000/v4
Quick Test
You can test the client and authentication with the following:
Data Examples
Examples of using the client are in the examples directory. Here are some basic examples:
from datetime import datetime, timedelta
from openelectricity import OEClient
from openelectricity.types import DataMetric, UnitFueltechType, UnitStatusType
# Calculate date range
end_date = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
start_date = end_date - timedelta(days=7)
# Using context manager (recommended)
with OEClient() as client:
# Get operating solar and wind facilities
facilities = client.get_facilities(
network_id=["NEM"],
status_id=[UnitStatusType.OPERATING],
fueltech_id=[UnitFueltechType.SOLAR_UTILITY, UnitFueltechType.WIND],
)
# Get network data for NEM
response = client.get_network_data(
network_code="NEM",
metrics=[DataMetric.POWER, DataMetric.ENERGY],
interval="1d",
date_start=start_date,
date_end=end_date,
secondary_grouping="fueltech_group",
)
# Print results
for series in response.data:
print(f"\nMetric: {series.metric}")
print(f"Unit: {series.unit}")
for result in series.results:
print(f"\n {result.name}:")
print(f" Fuel Tech Group: {result.columns.fueltech_group}")
for point in result.data:
print(f" {point.timestamp}: {point.value:.2f} {series.unit}")
For async usage:
from openelectricity import AsyncOEClient
import asyncio
async def main():
async with AsyncOEClient() as client:
# Get operating solar and wind facilities
facilities = await client.get_facilities(
network_id=["NEM"],
status_id=[UnitStatusType.OPERATING],
fueltech_id=[UnitFueltechType.SOLAR_UTILITY, UnitFueltechType.WIND],
)
# Get network data
response = await client.get_network_data(
network_code="NEM",
metrics=[DataMetric.POWER],
interval="1d",
secondary_grouping="fueltech_group",
)
# Process response...
asyncio.run(main())
Rooftop solar forecast
MarketMetric.SOLAR_ROOFTOP_FORECAST (MW, NEM only) accepts a date_end in the future, up to the latest forecast interval. Each forecast series carries forecast_run_time, the issue time of the newest AEMO run used. examples/rooftop_forecast.py splices it onto rooftop actuals; see the forecast guide.
from openelectricity.types import MarketMetric
with OEClient() as client:
response = client.get_market(
network_code="NEM",
metrics=[MarketMetric.SOLAR_ROOFTOP_FORECAST],
interval="30m",
date_start=datetime(2026, 10, 6, 10, 30),
date_end=datetime(2026, 10, 8, 10, 30),
primary_grouping="network_region",
)
print(response.data[0].forecast_run_time)
Response fields
Each series in response.data carries date_start and date_end for its data range, and each result carries its grouping values in result.columns (region, fueltech, fueltech_group, renewable, status or unit_code). Timestamps are network-local with an offset (e.g. 2026-10-05T00:00:00+10:00). series.start / series.end and columns.network_region are deprecated aliases of date_start / date_end and region; they still work and emit a DeprecationWarning.
Data Analysis
The client provides built-in support for converting API responses to popular data analysis formats. to_records(), to_pandas() and to_polars() return one row per value by default, with interval (network-local time as a naive datetime), the grouping columns (region, fueltech_group, unit_code, ...) and the value under its metric name. Pass merge_metrics=True for one row per interval and grouping with a column per metric:
df = response.to_pandas(merge_metrics=True) # interval, region, price, demand
Using with Polars
# Make sure you've installed with analysis extras
# uv add "openelectricity[analysis]"
from openelectricity import OEClient
from openelectricity.types import DataMetric
with OEClient() as client:
response = client.get_network_data(
network_code="NEM",
metrics=[DataMetric.POWER, DataMetric.ENERGY],
interval="1d",
secondary_grouping="fueltech_group",
)
# Convert to Polars DataFrame
df = response.to_polars()
# Get metric units
units = response.get_metric_units()
# Analyze data
energy_by_fueltech = (
df.group_by("fueltech_group")
.agg(
pl.col("energy").sum().alias("total_energy_mwh"),
pl.col("power").mean().alias("avg_power_mw"),
)
.sort("total_energy_mwh", descending=True)
)
Using with Pandas
# Make sure you've installed with analysis extras
# uv add "openelectricity[analysis]"
from openelectricity import OEClient
from openelectricity.types import DataMetric
with OEClient() as client:
response = client.get_network_data(
network_code="NEM",
metrics=[DataMetric.POWER, DataMetric.ENERGY],
interval="1d",
secondary_grouping="fueltech_group",
)
# Convert to Pandas DataFrame
df = response.to_pandas()
# Get metric units
units = response.get_metric_units()
# Analyze data
energy_by_fueltech = (
df.groupby("fueltech_group")
.agg({
"energy": "sum",
"power": "mean",
})
.sort_values("energy", ascending=False)
)
Development
Development is preferred with uv and there are targets in the Makefile for common tasks and managing releases. There are optional dependency groups for development, analysis and testing. You can install all of them with make install (which runs uv sync --all-extras).
-
Clone the repository
-
Install development dependencies:
make install -
Run tests:
make test
-
Format code:
make format -
Run linters:
make lint
License
This project is licensed under the MIT License - see the LICENSE file for details.
Metadata
Release files for openelectricity 0.12.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 | |
|---|---|---|---|
| openelectricity-0.12.0.tar.gz | 258.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| openelectricity-0.12.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 283.3 kB
Release files / openelectricity-0.12.0.tar.gz
| Download URL | openelectricity-0.12.0.tar.gz |
|---|---|
| Size | 258.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
75b0577018390957b71e1b78d85fce97425001425a2aabb113371c4d64949d29
|
|
BLAKE2b-256 checksum How to use checksums |
9fd0710930a08d8540f9f39ec31b52e6a2b520df28a465ee7898e2adb15b2796
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.0
|
Release files / openelectricity-0.12.0-py3-none-any.whl
| Download URL | openelectricity-0.12.0-py3-none-any.whl |
|---|---|
| Size | 24.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2ad92f49718a41fb2f02ca9180db18179809e6da24aef53ecdc18670e58cb29d
|
|
BLAKE2b-256 checksum How to use checksums |
9182d1be7757c78df69398f816335c30fdcc82a798323c00ae2eea1228b1e50f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.0
|