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.
- 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
# 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 openelectricity0.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.
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/v4You can test the client and authentication with the following:
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())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)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.
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# 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)
)# 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 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
This project is licensed under the MIT License - see the LICENSE file for details.
