python-entsoe: Descarga datos energéticos europeos en 3 líneas de Python
Librería Python para descargar precios de electricidad, generación y flujos transfronterizos de ENTSO-E. Instala con pip y analiza mercados energéticos europeos.
If you’ve ever worked with the ENTSO-E Transparency Platform API directly, you know the pain: XML responses, manual pagination, cryptic area codes, and rate limiting you have to handle yourself.
We built python-entsoe to solve this. Three lines of code to go from zero to a pandas DataFrame with European energy data.
from entsoe import Client
client = Client() # reads ENTSOE_API_KEY from environment
df = client.prices.day_ahead("2024-06-01", "2024-06-08", country="FR") In this article, we’ll walk through the library’s main features with executable examples and Plotly visualizations. If you want to see how we built the library from scratch, watch the live coding stream.
Installation
pip install python-entsoe You’ll also need a free API key from the ENTSO-E Transparency Platform. Register, then request a token via email. Set it as an environment variable:
export ENTSOE_API_KEY=your-token-here Before vs after: the “aha” moment
If you’ve followed our ENTSO-E API tutorial, you’ve seen code like this to download day-ahead prices for multiple countries:
# Before: using entsoe-py (the old library)
from entsoe import EntsoePandasClient
client = EntsoePandasClient(api_key=API_TOKEN)
start = pd.Timestamp('20240201', tz='Europe/Rome')
end = pd.Timestamp('20240229T2359', tz='Europe/Rome')
ls = []
for area in areas:
s = client.query_day_ahead_prices(
country_code=area, start=start, end=end
)
s.name = area
ls.append(s)
df = pd.concat(ls, axis=1) With python-entsoe, the same task becomes:
# After: using python-entsoe
from entsoe import Client
client = Client()
df = client.prices.day_ahead("2024-06-01", "2024-06-08", country=["FR", "DE_LU", "ES", "NL"]) Key differences:
- No manual timestamps — just pass date strings, the library handles timezone conversion
- Namespace-organized API —
client.prices.day_ahead()instead ofclient.query_day_ahead_prices() - Consistent DataFrames — every method returns the same column structure with
timestampandvalue - Multi-value parameters — pass a list of countries or fuel types to get all results in one call
- Automatic retry — rate-limited requests are retried with exponential backoff
Use case 1: Day-ahead electricity prices
Let’s start with the most common use case — downloading and visualizing day-ahead spot prices.
Single country
start = "2024-06-01"
end = "2024-06-08"
df_prices = client.prices.day_ahead(start, end, country="ES")
df_prices.head()

One line to download, one line to plot. The DataFrame includes timestamp, value, currency, and price_unit columns.
Multi-country comparison
df_multi = client.prices.day_ahead(start, end, country=["FR", "DE_LU", "ES", "NL"]) 
Price distribution

Notice how Spain consistently shows lower prices — this correlates with its high solar penetration, which pushes midday prices down.
Use case 2: Generation by technology
Understanding the energy mix is essential for price analysis. Let’s look at France’s generation breakdown.
df_gen = client.generation.actual(start, end, country="FR")
df_gen.head()

Nuclear dominates France’s generation mix, while solar and wind follow their natural daily patterns.
Solar vs wind — daily patterns
You can filter by fuel type using the psr_type parameter:
start_day = "2024-06-03"
end_day = "2024-06-06"
df_ren = client.generation.actual(start_day, end_day, country="FR", psr_type=["solar", "wind_onshore"]) 
Solar follows a predictable bell curve while wind is more volatile — exactly what drives price patterns in European markets.
Use case 3: Cross-border flows
One of ENTSO-E’s most valuable datasets: physical electricity flows between countries.
df_flows = client.transmission.crossborder_flows(
start, end, country_from="FR", country_to="ES"
)
df_flows.head()

France is a net exporter to Spain — driven largely by its nuclear fleet providing baseload power.
Multi-border comparison

Use case 4: Load forecasting accuracy
How accurate are the TSO’s load forecasts? Let’s compare actual vs forecasted demand.
df_load = client.load.actual(start, end, country="FR")
df_forecast = client.load.forecast(start, end, country="FR") 

Forecast errors typically stay within ±5%, demonstrating the high accuracy of European TSO forecasting.
Advanced configuration
Error handling
The library provides typed exceptions for common error cases:
from entsoe import Client, NoDataError, InvalidParameterError
client = Client()
try:
df = client.prices.day_ahead(start, end, country="FR")
except NoDataError:
print("No data available for this period")
except InvalidParameterError as e:
print(f"Bad parameters: {e}") Automatic year-splitting
Requests spanning more than 1 year are split into annual chunks transparently:
# This works — the library splits it into 3 requests internally
df = client.load.actual("2022-01-01", "2024-12-31", country="FR") Rate limiting and retry
HTTP 429 responses are retried automatically with exponential backoff. You don’t need to implement any rate limiting logic.
Conclusions
python-entsoe simplifies access to European energy data:
- Simple API — namespace-organized methods (
client.prices,client.generation,client.transmission,client.load,client.balancing) instead of cryptic function names - Consistent output — every method returns a pandas DataFrame with
timestampandvaluecolumns - Production-ready — automatic retry, year-splitting, ZIP handling, and typed exceptions
- 60+ bidding zones — from
ES(Spain) toNO_5(Norway) with human-readable names viacountry_name()
Resources
- PyPI: python-entsoe
- GitHub: datons/python-entsoe
- Deep dive: If you want to understand the raw API before using the library, read our ENTSO-E API in Python tutorial
- US energy data? Check out python-eia — our sister library for the EIA API