# Nordic Electricity Prices (Nord Pool spot, Norway and Denmark) (`nightwave-owner/nordic-electricity-prices`) Actor

Returns Nord Pool day-ahead electricity spot prices for Norway (NO1-NO5) and Denmark (DK1-DK2) in NOK, DKK and EUR per kWh, hourly or per 15 minutes, with optional daily summaries. Supports onlyNew for scheduled runs.

- **URL**: https://apify.com/nightwave-owner/nordic-electricity-prices.md
- **Developed by:** [Viktor Wiberg](https://apify.com/nightwave-owner) (community)
- **Categories:** Developer tools, Automation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 price rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Nordic Electricity Prices (Nord Pool spot, Norway and Denmark)

Day-ahead electricity spot prices (Nord Pool) for the five Norwegian bidding zones NO1-NO5 and the two Danish zones DK1-DK2, in local currency (NOK or DKK) and EUR per kWh. You get one row per hour, or per 15 minutes for Denmark, and optionally one summary row per zone and day with the lowest, highest and average price and the cheapest and most expensive hour.

Every row has the same fields whatever the country: `country`, `area`, `currency` and `source` tell you where the price comes from, so you can mix Norwegian and Danish zones in one dataset. For the Swedish zones SE1-SE4 use [Sweden Electricity Prices](https://apify.com/nightwave-owner/sweden-electricity-prices), which has the same output format.

### Bidding zones

| Zone | Country | Area | Largest city | Source |
|---|---|---|---|---|
| NO1 | Norway | Eastern Norway | Oslo | hvakosterstrommen.no |
| NO2 | Norway | Southern Norway | Kristiansand | hvakosterstrommen.no |
| NO3 | Norway | Central Norway | Trondheim | hvakosterstrommen.no |
| NO4 | Norway | Northern Norway | Tromsø | hvakosterstrommen.no |
| NO5 | Norway | Western Norway | Bergen | hvakosterstrommen.no |
| DK1 | Denmark | Western Denmark (Jutland, Funen) | Aarhus | Energi Data Service |
| DK2 | Denmark | Eastern Denmark (Zealand) | Copenhagen | Energi Data Service |

Finland (FI) is not included. We did not find an open source for Finnish day-ahead prices that needs no API key and has terms that clearly allow commercial reuse. The ENTSO-E Transparency Platform has the data but requires a personal API key.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `areas` | array | all seven zones | `NO1`, `NO2`, `NO3`, `NO4`, `NO5`, `DK1`, `DK2`. |
| `dateFrom` | string | today | First day, `YYYY-MM-DD` in local time (CET/CEST). Data is available from 2021-12-01. |
| `dateTo` | string | from date or today | Last day (inclusive). Can be tomorrow. At most 366 days per run. |
| `resolution` | string | `hour` | `hour` gives hourly prices. `quarter` gives 15 minute prices for Denmark from 2025-10-01. Norwegian zones are always hourly. |
| `includeDailySummary` | boolean | `true` | Adds one summary row per zone and day. |
| `currency` | string | `both` | `local` (NOK or DKK), `EUR` or `both`. Controls which price fields are included. |
| `onlyNew` | boolean | `false` | Return only rows that earlier runs with the same input did not deliver. See "Monitoring and scheduling". |
| `maxResults` | integer | `50` | Maximum number of rows, summary rows included. 1 to 100 000. |

One zone for one day at hourly resolution with a summary is 25 rows, so all seven zones for one day are 175 rows. A run with empty input returns today's prices for the first zones in the list (NO1 and NO2) until it reaches 50 rows. Pick the zones you need or raise `maxResults` to get more.

This input was used for the test run in the Apify cloud that the output examples below come from:

```json
{
  "dateFrom": "2026-10-03",
  "dateTo": "2026-10-03",
  "maxResults": 200
}
```

It returned 175 rows: 24 hourly prices and one summary for each of the seven zones.

### Output

#### Price rows

| Field | Description |
|---|---|
| `country` | `NO` or `DK` |
| `area` | Bidding zone, for example `NO1` or `DK2` |
| `date` | Delivery day, `YYYY-MM-DD` in local time |
| `timeStart`, `timeEnd` | ISO 8601 with the local UTC offset, for example `2026-10-03T00:00:00+02:00` |
| `resolution` | `quarter` or `hour` |
| `currency` | Local currency of the zone: `NOK` or `DKK` |
| `priceLocalPerKwh` | Price in local currency per kWh (left out if `currency` is `EUR`) |
| `priceEurPerKwh` | Price in EUR per kWh (left out if `currency` is `local`) |
| `exchangeRateEurLocal` | EUR to local currency rate used for the day |
| `source` | `hvakosterstrommen.no` or `energidataservice.dk` |

Excerpt from the cloud run (Norway and Denmark):

```json
{
  "country": "NO",
  "area": "NO1",
  "date": "2026-10-03",
  "timeStart": "2026-10-03T00:00:00+02:00",
  "timeEnd": "2026-10-03T01:00:00+02:00",
  "resolution": "hour",
  "currency": "NOK",
  "priceLocalPerKwh": 1.51913,
  "priceEurPerKwh": 0.13969,
  "exchangeRateEurLocal": 10.875,
  "source": "hvakosterstrommen.no"
}
```

```json
{
  "country": "DK",
  "area": "DK1",
  "date": "2026-10-03",
  "timeStart": "2026-10-03T00:00:00+02:00",
  "timeEnd": "2026-10-03T01:00:00+02:00",
  "resolution": "hour",
  "currency": "DKK",
  "priceLocalPerKwh": 1.43088,
  "priceEurPerKwh": 0.19146,
  "exchangeRateEurLocal": 7.4736,
  "source": "energidataservice.dk"
}
```

#### Daily summary rows

Added when `includeDailySummary` is `true`. `min`, `max`, `cheapestHourStart` and `mostExpensiveHourStart` are based on hourly prices, so a single cheap 15 minute period does not decide the cheapest hour. `average` is the mean of all prices for the day. `hours` is the number of hours in the day (23 or 25 on daylight saving days).

```json
{
  "type": "dailySummary",
  "country": "DK",
  "area": "DK1",
  "date": "2026-10-03",
  "currency": "DKK",
  "min": { "localPerKwh": 0.40907, "eurPerKwh": 0.05474 },
  "max": { "localPerKwh": 1.77205, "eurPerKwh": 0.23711 },
  "average": { "localPerKwh": 1.25491, "eurPerKwh": 0.16791 },
  "cheapestHourStart": "2026-10-03T13:00:00+02:00",
  "mostExpensiveHourStart": "2026-10-03T19:00:00+02:00",
  "hours": 24,
  "exchangeRateEurLocal": 7.4736,
  "source": "energidataservice.dk"
}
```

Price rows have no `type` field, so you can filter summaries with `type = "dailySummary"`.

### Example from a real run

Input:

```json
{
  "areas": [
    "NO1"
  ],
  "maxResults": 5
}
```

Output (first 3 of 5 rows, values unchanged):

```json
[
  {
    "country": "NO",
    "area": "NO1",
    "date": "2026-10-04",
    "timeStart": "2026-10-04T00:00:00+02:00",
    "timeEnd": "2026-10-04T01:00:00+02:00",
    "resolution": "hour",
    "currency": "NOK",
    "priceLocalPerKwh": 1.50179,
    "priceEurPerKwh": 0.13865,
    "exchangeRateEurLocal": 10.8315,
    "source": "hvakosterstrommen.no"
  },
  {
    "country": "NO",
    "area": "NO1",
    "date": "2026-10-04",
    "timeStart": "2026-10-04T01:00:00+02:00",
    "timeEnd": "2026-10-04T02:00:00+02:00",
    "resolution": "hour",
    "currency": "NOK",
    "priceLocalPerKwh": 1.51164,
    "priceEurPerKwh": 0.13956,
    "exchangeRateEurLocal": 10.8315,
    "source": "hvakosterstrommen.no"
  },
  {
    "country": "NO",
    "area": "NO1",
    "date": "2026-10-04",
    "timeStart": "2026-10-04T02:00:00+02:00",
    "timeEnd": "2026-10-04T03:00:00+02:00",
    "resolution": "hour",
    "currency": "NOK",
    "priceLocalPerKwh": 1.51403,
    "priceEurPerKwh": 0.13978,
    "exchangeRateEurLocal": 10.8315,
    "source": "hvakosterstrommen.no"
  }
]
```

Run Evwkak0DBnIcnKdlI on 2026-10-04, 5 rows, 3 seconds.

### Use cases

- Compare spot prices across Norwegian and Danish zones, or add them to Swedish prices from the sister actor for a full Nordic view.
- Plan flexible consumption such as EV charging, heat pumps or batteries around the cheapest hours.
- Feed a dashboard, spreadsheet or BI tool with daily prices through a schedule and an integration.
- Give an AI agent a small, well described tool for "what does electricity cost in Oslo tomorrow".

### Monitoring and scheduling

Set `onlyNew` to `true` to use the actor for recurring monitoring. The actor then remembers which rows it has delivered for the same input, in a named key-value store in your Apify account (`nightwave-state-nordic-electricity-prices`, one record per input). Each run returns and charges only rows that earlier runs did not deliver. The first run returns everything in the selection. A run without news finishes successfully with 0 rows.

A row is identified by zone and start time, and a summary row by zone and day. The input below has no dates, so each run covers the current day in local time. If your client builds the input, set `dateTo` to tomorrow's date and schedule a run after 13:00 CET to get tomorrow's prices as soon as they are published: with `onlyNew` the next run skips the hours you already have.

`onlyNew` and `maxResults` are not part of the remembered input, so you can change them without starting over. Changing any other field starts a fresh state. To start over with the same input, delete the record in the key-value store.

Example: a daily run at 00:30 local time that returns the new day's hourly prices for all seven zones. In Apify Console, open **Schedules**, create a schedule with the cron expression `30 0 * * *` and add this actor with the input below.

```json
{
  "areas": ["NO1", "NO2", "NO3", "NO4", "NO5", "DK1", "DK2"],
  "resolution": "hour",
  "includeDailySummary": true,
  "onlyNew": true,
  "maxResults": 200
}
```

The same schedule through the Apify API:

```sh
curl -X POST "https://api.apify.com/v2/schedules?token=<YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"name": "daily-nordic-electricity-prices", "cronExpression": "30 0 * * *", "timezone": "Europe/Oslo", "isEnabled": true, "isExclusive": true,
       "actions": [{"type": "RUN_ACTOR", "actorId": "nightwave-owner~nordic-electricity-prices",
                    "runInput": {"contentType": "application/json; charset=utf-8", "body": "<the input above as a JSON string>"}}]}'
```

Connect a webhook or an integration (Slack, e-mail, Google Sheets) to the actor in Apify Console if you want the new rows sent somewhere when the run finishes.

### Good to know

- **Prices exclude VAT, taxes, grid fees and supplier mark-ups.** They are the wholesale spot price only. Norwegian prices do not include the Norwegian electricity support (strømstøtte).
- **Tomorrow's prices are published after about 13:00 CET.** If you ask for tomorrow before that, the day is skipped with a log message and the run still succeeds.
- **Norway is hourly only.** hvakosterstrommen.no publishes one price per hour, so Norwegian rows have `resolution: "hour"` also when you ask for `quarter`.
- **Denmark** has 15 minute prices from 2025-10-01 (Energi Data Service dataset `DayAheadPrices`) and hourly prices before that (dataset `Elspotprices`). The source publishes prices per MWh; the actor converts them to per kWh and rounds to 5 decimals. The DKK/EUR rate for the day is taken from the source's own DKK and EUR prices.
- Daylight saving days have 23 or 25 hours. On the autumn day the repeated hour 02:00 appears twice, once with `+02:00` and once with `+01:00`.
- Failed requests are retried three times. If a source returns data in an unexpected format the run fails with a clear message instead of storing broken rows.

### Data sources and licenses

- **Norway:** [Hva koster strømmen.no](https://www.hvakosterstrommen.no/strompris-api). According to the API page the data is freely available to anyone for any purpose. The source asks for attribution when the data is shown publicly: "Strømpriser levert av Hva koster strømmen.no" with a link.
- **Denmark:** [Energi Data Service](https://www.energidataservice.dk) by Energinet, under [Creative Commons CC BY 4.0](https://www.energidataservice.dk/terms-and-conditions), which allows commercial use. Credit: "Source: Energinet (www.energidataservice.dk)". The actor converts the prices from MWh to kWh.

The datasets contain no personal data. This actor is not affiliated with Hva koster strømmen.no, Energinet, Nord Pool or ENTSO-E, and Energinet does not endorse it.

### Pricing

Pay per event: each dataset row (event `price-row`, summary rows included) costs USD 0.002, the same as Sweden Electricity Prices. All seven zones for one day at hourly resolution with summaries are 175 rows. With `onlyNew` you only pay for rows you have not received before. Platform usage is included in the price.

Rows are delivered only after they have been charged. If you set a maximum cost per run (maxTotalChargeUsd), the run stops there and its status message says how many rows were delivered.

### Contact

Built and maintained by Nightwave AB. Questions, bugs and feature requests: kontakt@nightwave.se

### På svenska

Actorn hämtar dagen-före-priser på el (Nord Pool) för Norges elområden NO1-NO5 och Danmarks DK1-DK2, i lokal valuta (NOK eller DKK) och euro per kWh, per timme eller per kvart (Danmark från 2025-10-01), med en valfri dygnssammanställning.

Exempel från en verklig körning: input och de första raderna i outputen finns i avsnittet Example from a real run ovan (körning Evwkak0DBnIcnKdlI, 2026-10-04, 5 rader, 3 sekunder).

- Varje rad har fälten `country`, `area`, `currency` och `source`, så att norska och danska områden går att blanda i samma dataset. Formatet är detsamma som i Sweden Electricity Prices för SE1-SE4.
- Finland ingår inte: vi hittade ingen öppen källa utan API-nyckel med villkor som tydligt tillåter kommersiell vidareanvändning.
- Priserna är spotpriser **exklusive moms, skatter, nätavgift och elhandlarens påslag**.
- Norge publiceras bara per timme av källan. Danmark har kvartspriser från 1 oktober 2025.
- Morgondagens priser publiceras efter cirka 13:00. Före det hoppas dagen över med en loggrad.
- Källor: [Hva koster strømmen.no](https://www.hvakosterstrommen.no/strompris-api) (fri att använda för alla ändamål, hänvisning önskas) och [Energi Data Service](https://www.energidataservice.dk) från Energinet (CC BY 4.0).
- Med `onlyNew: true` levereras och debiteras bara rader som tidigare körningar med samma input inte har levererat (se "Monitoring and scheduling").
- Pris: 0,002 USD per rad i datasetet. Alla sju områden för ett dygn per timme med sammanställning är 175 rader.
- Kontakt: kontakt@nightwave.se

# Actor input Schema

## `areas` (type: `array`):

Bidding zones to fetch, for example \["NO1", "DK2"]. NO1 Oslo, NO2 Kristiansand, NO3 Trondheim, NO4 Tromsø, NO5 Bergen, DK1 Western Denmark, DK2 Eastern Denmark (Copenhagen). Defaults to all seven zones.

## `dateFrom` (type: `string`):

First day to fetch, YYYY-MM-DD in local time (CET/CEST), for example "2026-10-03". Defaults to today. Data is available from 2021-12-01.

## `dateTo` (type: `string`):

Last day to fetch (inclusive), YYYY-MM-DD, for example "2026-10-04". Defaults to the from date or today. Can be tomorrow: tomorrow's prices are published after about 13:00 CET, and an unpublished day is skipped with a log message. At most 366 days per run.

## `resolution` (type: `string`):

"hour" returns hourly prices (24 rows per zone and day). "quarter" returns 15 minute prices for Denmark from 2025-10-01 (96 rows per zone and day). The Norwegian source only publishes hourly prices, so Norwegian zones are always hourly. Defaults to hour.

## `includeDailySummary` (type: `boolean`):

Adds one row per zone and day with min, max and average price and the cheapest and most expensive hour, for example true. Defaults to true.

## `currency` (type: `string`):

Which price fields to include: "local" (NOK for Norway, DKK for Denmark), "EUR" or "both", for example "EUR". The exchange rate and the local currency code are always included. Defaults to both.

## `onlyNew` (type: `boolean`):

For scheduled runs. When true, rows that an earlier run with the same input already delivered are skipped and not charged, so each run returns only new prices. The first run returns everything. Defaults to false.

## `maxResults` (type: `integer`):

Maximum number of rows to return, including summary rows, for example 50. One zone for one day at hourly resolution with a summary is 25 rows, all seven zones are 175 rows. Each row is one billable result. Defaults to 50.

## Actor input object example

```json
{
  "areas": [
    "NO1",
    "DK2"
  ],
  "dateFrom": "2026-10-03",
  "dateTo": "2026-10-04",
  "resolution": "hour",
  "includeDailySummary": true,
  "currency": "EUR",
  "onlyNew": true,
  "maxResults": 175
}
```

# Actor output Schema

## `results` (type: `string`):

All rows produced by the run, as JSON. Open in Apify Console or download via the dataset API.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "areas": [
        "NO1",
        "NO2",
        "NO3",
        "NO4",
        "NO5",
        "DK1",
        "DK2"
    ],
    "resolution": "hour",
    "includeDailySummary": true,
    "currency": "both",
    "onlyNew": false,
    "maxResults": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("nightwave-owner/nordic-electricity-prices").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "areas": [
        "NO1",
        "NO2",
        "NO3",
        "NO4",
        "NO5",
        "DK1",
        "DK2",
    ],
    "resolution": "hour",
    "includeDailySummary": True,
    "currency": "both",
    "onlyNew": False,
    "maxResults": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("nightwave-owner/nordic-electricity-prices").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "areas": [
    "NO1",
    "NO2",
    "NO3",
    "NO4",
    "NO5",
    "DK1",
    "DK2"
  ],
  "resolution": "hour",
  "includeDailySummary": true,
  "currency": "both",
  "onlyNew": false,
  "maxResults": 50
}' |
apify call nightwave-owner/nordic-electricity-prices --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nightwave-owner/nordic-electricity-prices"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/CZGGLY9LpDygbLvwC/builds/4xRaOKAGDdJZZeJaU/openapi.json
