1. Home
  2. Scripting
  3. Live electricity prices

Scripting

Live electricity prices

Heat, charge and switch when power is cheap, from a script on the device.

Updated August 2026

How it works

The device fetches the hourly price itself, over HTTP, and decides what to do with it. Nothing runs in the cloud, and nothing depends on a third-party service staying online — if the price fetch fails, the load simply keeps its last state.

Every setup has two halves:

  1. Fetch the price. This part is country-specific, because the number that matters is not the raw spot price.
  2. Act on the price. This part is identical everywhere, and it is the script below.

Prices differ by country

Each Nordic country therefore has its own guide, with its own data source and its own working fetch script:

Country Source Includes
Denmark stromligning.dk Spot price, grid operator tariffs, taxes — looked up from coordinates
Sweden National spot price by area Spot price by price area
Finland National spot price Spot price, with VAT handled separately

Start with your country’s guide for the fetch, then use the control logic below for what happens next.

What you need

  • A device that supports scripting — Gen2 or newer.
  • At least one metering device (PM or EM) if you want to see what the switching saved.
  • Shelly Smart Control, or control.shelly.cloud in a browser. A computer is easier for editing scripts than a phone.
  • A Gen3 device or newer if you want the price shown as a tile in the app — virtual components are not available before Gen3.

The control script

This is the half that is the same in every country. It takes a price, compares it against your threshold, and switches the output accordingly.

Paste your country guide’s fetch function into the marked place, then adjust the configuration block at the top.

// ===== CONFIGURATION =====
let CONFIG = {
  switch_id: 0,          // Which output to control
  price_limit: 1.50,     // Switch on below this price, per kWh, in local currency
  check_delay_seconds: 10, // Seconds after the hour before checking
  post_url: "",          // Optional: URL for pushing the price elsewhere. Leave empty if unused.
  vc_id: 200,            // Optional: virtual component id, to show the price in the app
};
// ===== END CONFIGURATION =====

let current_price = null;

// Decide what to do with a price once it has been fetched.
function actOnPrice(price) {
  current_price = price;
  let cheap = price < CONFIG.price_limit;

  print("Price " + price + " — limit " + CONFIG.price_limit + " — output " + (cheap ? "ON" : "OFF"));

  Shelly.call("Switch.Set", { id: CONFIG.switch_id, on: cheap });

  if (CONFIG.vc_id) {
    Shelly.call("Number.Set", { id: CONFIG.vc_id, value: price });
  }
}

// ===== PASTE YOUR COUNTRY'S FETCH FUNCTION HERE =====
// It must call actOnPrice(price) with the final price per kWh,
// including tariffs and taxes, and then call scheduleNextCheck().
function getCurrentPrice() {
  print("No fetch function installed — see your country guide.");
  scheduleNextCheck();
}
// ===== END FETCH FUNCTION =====

// Run again shortly after the next full hour.
function scheduleNextCheck() {
  let now = new Date();
  let msIntoHour = (now.getMinutes() * 60 + now.getSeconds()) * 1000;
  let delay = (3600 * 1000) - msIntoHour + (CONFIG.check_delay_seconds * 1000);

  print("Next check in " + Math.floor(delay / 1000) + " s");
  Timer.set(delay, false, getCurrentPrice);
}

getCurrentPrice();

Install it as described in how to add a script, and enable Run on startup so it survives a power cut.

Script list in the web interface with the script set to run automatically
Enable run-on-startup, or the script stops at the first power cut.

Show the price in the app

On Gen3 and newer devices, a virtual component turns the price into a tile in Shelly Smart Control, next to the switch it controls.

Create a Number component on the device, note its id, and put that id into vc_id in the configuration block. The script then updates it on every check.

Dashboard showing the electricity price as a virtual component tile
The price appears as its own tile, updated hourly by the script.

Tips & best practices

  • Pick the right load. Underfloor heating, hot water and EV charging are slow and tolerant — perfect. Lighting and sockets are not worth switching on price.
  • Combine with a schedule, not instead of one. Price control decides when within a window; the schedule decides that the window exists at all.
  • Give the customer a manual override. A cheap-hours rule that cannot be interrupted becomes a complaint the first time somebody wants a hot shower at 17:00.
  • Set the threshold from their actual bill, not from the spot price. See the country guide for what to include.
  • Watch it for a day before you leave. The console output shows each check and each decision, which is the fastest way to see that the threshold is set sensibly.