progrunners.comenergy & technology
progrunners / Nord Pool API

Nord Pool API, and the free route to the same prices

Most people searching for a Nord Pool API want one thing: the day-ahead price for a Nordic or Baltic zone, in code, every day. That number does not have to come from Nord Pool. Here is what the paid API gives you, what the free route gives you, and code that works.

Code tested on 26 September 2026 against Elering and elprisetjustnu.se — identical daily averages for 25 September 2026.
On this page
  1. Is there a free Nord Pool API?
  2. Python: all 15 zones from ENTSO-E
  3. Three traps a naive script falls into
  4. entsoe-py in pandas

Is there a free Nord Pool API?

Not from Nord Pool itself: automated access to Nord Pool data is a paid, licensed product. The public website shows current and recent prices for people to read, not for software to collect.

But the day-ahead auction Nord Pool runs is the single European day-ahead coupling (SDAC), and its results for every bidding zone are published by ENTSO-E on the Transparency Platform — free, with an API token you request by e-mail. For day-ahead prices in SE1–SE4, NO1–NO5, DK1–DK2, FI, EE, LV and LT the numbers are the same. We checked that on 25 September 2026 against two independent sources and all averages matched to the cent.

DataENTSO-ENord Pool
Day-ahead zone pricesfreepaid
In NOK, SEK, DKKEUR onlypaid
System price—paid
Intraday, order book—paid
Load, generationfreepartly
If you settle contracts against the system price or trade intraday, buy the Nord Pool data. For dashboards, research, forecasting inputs and apps that show today’s zone prices, ENTSO-E is enough.

Python: all 15 zones from ENTSO-E

Standard library only. Replace the token, change the dates, run. The start and end are in UTC: the Nordic delivery day 25 September 2026 runs from 22:00 UTC the day before.

import urllib.request
import xml.etree.ElementTree as ET

TOKEN = "your-entso-e-token"
ZONES = {"SE1": "10Y1001A1001A44P", "SE2": "10Y1001A1001A45N", "SE3": "10Y1001A1001A46L",
         "SE4": "10Y1001A1001A47J", "NO1": "10YNO-1--------2", "NO2": "10YNO-2--------T",
         "NO3": "10YNO-3--------J", "NO4": "10YNO-4--------9", "NO5": "10Y1001A1001A48H",
         "DK1": "10YDK-1--------W", "DK2": "10YDK-2--------M", "FI": "10YFI-1--------U",
         "EE": "10Y1001A1001A39I", "LV": "10YLV-1001A00074", "LT": "10YLT-1001A0008Q"}

def day_ahead(eic, start, end):            # start/end in UTC, e.g. "202609242200"
    url = ("https://web-api.tp.entsoe.eu/api?securityToken=" + TOKEN +
           "&documentType=A44&in_Domain=" + eic + "&out_Domain=" + eic +
           "&periodStart=" + start + "&periodEnd=" + end)
    root = ET.fromstring(urllib.request.urlopen(url).read())
    ns = {"n": root.tag.split("}")[0].strip("{")}
    series = root.find("n:TimeSeries", ns)   # first series only: some zones send a duplicate
    period = series.find("n:Period", ns)
    points = sorted((int(p.find("n:position", ns).text), float(p.find("n:price.amount", ns).text))
                    for p in period.findall("n:Point", ns))
    n = 96 if period.find("n:resolution", ns).text == "PT15M" else 24
    prices = []
    for i, (pos, price) in enumerate(points):   # curve A03: a repeated price is sent once
        nxt = points[i + 1][0] if i + 1 < len(points) else n + 1
        prices += [price] * (nxt - pos)
    return prices

for zone, eic in ZONES.items():
    p = day_ahead(eic, "202609242200", "202609252200")     # 25 Sep 2026, CEST
    print(zone, len(p), "quarter hours, average", round(sum(p) / len(p), 2), "EUR/MWh")

Output for 25 September 2026: SE3 121.62, FI 62.75, EE 112.56, LV and LT 172.07 EUR/MWh — the same as Elering and elprisetjustnu.se publish. A ready-made version is on GitHub as nordpool-day-ahead, and today’s prices are on our Nord Pool day-ahead prices page.

Three traps a naive script falls into

  1. Repeated prices are left out. ENTSO-E sends curve type A03: when several quarter hours in a row have the same price, only the first is sent. A script that averages the points it receives gets 95 values instead of 96 and the wrong average. The loop above fills them in.
  2. Some zones answer with two series. Norway and DK1 returned two identical time series for the same day, so a script that reads every point counts the day twice. Take the first series.
  3. The day has 96 prices, not 24. Since October 2025 the day-ahead auction clears in 15-minute periods. Anything that assumed hourly prices now reads a quarter of the day.

The token, request limits and empty responses are covered in our ENTSO-E API guide; every zone code is in the EIC code list.

entsoe-py in pandas

If you work in pandas anyway, the entsoe-py library does the same in three lines and handles the traps above. Zone names are short codes such as SE_3 or NO_1:

import pandas as pd
from entsoe import EntsoePandasClient     # pip install entsoe-py

client = EntsoePandasClient(api_key="your-entso-e-token")
start = pd.Timestamp("2026-09-25", tz="Europe/Stockholm")
end = pd.Timestamp("2026-09-26", tz="Europe/Stockholm")
se3 = client.query_day_ahead_prices("SE_3", start=start, end=end)

Frequently asked questions

Is there a free Nord Pool API?
Not from Nord Pool: its data access is a paid, licensed product. The same day-ahead zone prices are free from the ENTSO-E Transparency Platform API, which needs only a token requested by e-mail.
Are ENTSO-E prices the same as Nord Pool prices?
For day-ahead zone prices, yes: both publish the result of the same European day-ahead auction. We compared 25 September 2026 for SE3, FI, EE, LV and LT and the averages were identical. The Nord Pool system price, intraday trades and prices in local currencies are not on ENTSO-E.
How do I get Nord Pool prices in Python?
Request document type A44 from the ENTSO-E API for each zone’s EIC code, fill in the repeated prices the response leaves out, and take only the first time series. The code on this page does exactly that with the standard library.
Why do I get 95 prices instead of 96?
Because ENTSO-E omits a quarter hour whose price equals the previous one (curve type A03). The missing value is the same as the one before it.

Explore the rest of the site

Need Nordic data in production?

We build price and fundamentals pipelines on ENTSO-E and the Nordic TSOs — with the gaps filled, every version kept and alerts when a feed goes quiet.

Get in touch