# PSE Electricity Price API – Poland RCE & Kompas (`enterprising_hamster/polish-electricity-market-pse`) Actor

PSE electricity price and power-grid data from the official PSE API (api.raporty.pse.pl): rynkowa cena energii RCE, day-ahead and imbalance prices, Kompas Energetyczny, load and generation mix as clean 15-minute, hourly or daily rows. Export CSV, JSON or Excel.

- **URL**: https://apify.com/enterprising_hamster/polish-electricity-market-pse.md
- **Developed by:** [Kamil Kaczmarek](https://apify.com/enterprising_hamster) (community)
- **Categories:** Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.24 / 1,000 market data rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Poland Power Grid API – Official PSE RCE & Kompas

**Poland power grid API**: official Polish **power-system / electricity market data** from PSE ([api.raporty.pse.pl](https://api.raporty.pse.pl)) as clean, typed rows — **rynkowa cena energii (RCE)** for prosumer net-billing, the day-ahead price, imbalance prices, **Kompas Energetyczny** (PDGSZ), system load, and the generation mix. Choose 15-minute, hourly, or daily rows, schedule the Actor, and receive only new or revised values; export CSV, JSON or Excel. Polski opis: **dane PSE** — rynkowa cena energii RCE, Kompas Energetyczny, zapotrzebowanie KSE i generacja źródeł z oficjalnego API raportów PSE (sieć elektroenergetyczna / power grid).

Keywords: Poland power grid API, PSE electricity API, ceny energii PSE, rynkowa cena energii RCE, RCE PLN, Kompas Energetyczny, PDGSZ, ceny rozliczeniowe, zapotrzebowanie KSE, generacja źródeł, net-billing prosumenci.

### What data can you get

| `datasets` value | PSE report | Native resolution | Output fields |
| --- | --- | --- | --- |
| `rce` | `rce-pln` | 15 min | `rcePlnPerMwh` |
| `day-ahead-price` | `csdac-pln` | 15 min | `csdacPlnPerMwh` (single day-ahead coupling price) |
| `imbalance-price` | `price-cost` | 15 min | `cenPlnPerMwh`, `ckoebPlnPerMwh`, `cebAvgPlnPerMwh`, `corPlnPerMwh`, `imbalanceEnergyMwh`, `systemContracting` |
| `kompas` | `pdgsz` (active forecast only) | 1 hour | `usageLevel` 0–3 and `usageLevelLabel`: recommended usage, normal usage, recommended saving, required reduction |
| `load` | `kse-load` | 15 min | `loadActualMw`, `loadForecastMw` |
| `generation-mix` | `his-gen-pal` | 15 min | one MW column per ENTSO-E production type (`solarMw`, `windOnshoreMw`, `hardCoalMw`, …), `unmappedTypesMw`, `totalGenerationMw` |

Every row also has `dataset`, `granularity`, `businessDate` (doba handlowa), interval start and end in UTC and Europe/Warsaw, `intervalsCount`, `isComplete`, `publishedAtUtc`, `sourceUrl`, and the attribution fields `source`, `retrievedAt`, and `processingNote`.

History starts at business date 2024-06-14. Day-ahead reports for tomorrow appear after about 14:00 Europe/Warsaw.

### How to use

```json
{
  "datasets": ["rce", "kompas"],
  "lastDays": 0,
  "granularity": "hour",
  "onlyNew": true,
  "stateKey": "prosumer",
  "maxItems": 200
}
```

This input returns today's and tomorrow's hourly RCE and Kompas rows (48 rows per day). Schedule it every afternoon; `onlyNew` skips rows you already have and delivers a row again if PSE revises its value. The `examples` directory has four more inputs.

### Input

Today's and tomorrow's hourly RCE + Kompas (prosumer net-billing schedule):

```json
{
  "datasets": ["rce", "kompas"],
  "lastDays": 0,
  "granularity": "hour",
  "onlyNew": true,
  "stateKey": "prosumer",
  "maxItems": 200
}
```

Generation mix for one business day (15-min native):

```json
{
  "datasets": ["generation-mix"],
  "dateFrom": "2026-10-19",
  "dateTo": "2026-10-19",
  "maxItems": 100
}
```

| Field | Default | Meaning |
| --- | --- | --- |
| `datasets` | `["rce"]` | Reports to download, in this order. |
| `lastDays` | `7` | Business days before `dateTo` (or today), 0–3650. Used when `dateFrom` is empty. |
| `dateFrom`, `dateTo` | empty | Inclusive business dates `YYYY-MM-DD`. Empty `dateTo` means tomorrow. |
| `granularity` | `native` | `native`, `hour`, or `day`. Aggregation: arithmetic mean of prices and power, sum of energy, maximum Kompas level. |
| `maxItems` | `1000` | Row cap for the whole run, 1–500000, shared by all datasets in order. |
| `onlyNew` | `false` | Skip rows whose values were delivered before under the same `stateKey`. |
| `stateKey` | `default` | Separate keys for independent schedules. |
| `maxRequestsPerSecond` | `2` | Request rate to PSE, 0.2–5, one request at a time. |

### Output

```json
{
  "dataset": "rce",
  "granularity": "native",
  "businessDate": "2026-10-19",
  "intervalStartUtc": "2026-10-18T22:00:00Z",
  "intervalEndUtc": "2026-10-18T22:15:00Z",
  "intervalStartLocal": "2026-10-19T00:00:00+02:00",
  "intervalEndLocal": "2026-10-19T00:15:00+02:00",
  "rcePlnPerMwh": 755.01,
  "intervalsCount": 1,
  "isComplete": true,
  "publishedAtUtc": "2026-10-18T11:59:15.031000Z",
  "sourceUrl": "https://api.raporty.pse.pl/api/rce-pln",
  "source": "Polskie Sieci Elektroenergetyczne S.A. (PSE), Raporty OSP / Market Data API (api.raporty.pse.pl). Informacja pozyskana ze strony www.pse.pl.",
  "retrievedAt": "2026-10-20T14:12:48Z",
  "processingNote": "Informacja pozyskana ze strony www.pse.pl według stanu na dzień 2026-10-20. Informacja została przetworzona w całości lub w części. Processing: fields renamed to English; timestamps converted to ISO 8601 in UTC and Europe/Warsaw; numbers parsed."
}
```

Aggregated rows report how many source intervals they contain. `isComplete` is false when a bucket has fewer intervals than expected, for example a day that PSE has not finished publishing. Daily buckets follow local midnight, so DST days contain 92 or 100 quarter-hours.

### Source and attribution

PSE allows reuse of the information it publishes "zarówno w celach komercyjnych, jak i niekomercyjnych" ([PSE: ponowne wykorzystanie informacji publicznej](https://www.pse.pl/bip/ponowne-wykorzystanie-informacji-publicznej)). Its conditions are to name the source, give the retrieval date, remove the PSE logo, and tell recipients when and how information was processed. Every row carries this in `source`, `retrievedAt`, and `processingNote`; the Actor publishes no PSE logo. When you republish the data, keep these fields or an equivalent notice.

### Pricing (pay per event)

| Event | USD | When charged |
| --- | --- | --- |
| `data-row` | $0.0003 | Each delivered dataset row: one 15-minute interval, one hour, or one day. |

Coarser granularity costs less: a day of RCE is 96 native rows ($0.029), 24 hourly rows ($0.007), or one daily row. Rows skipped by `onlyNew` and rows refused by your spending limit are not charged; the Actor stops cleanly when the limit is reached. `.actor/pay_per_event.json` documents the event for the Apify Console; it does not activate pricing.

### Use cases

- **Prosumers and energy apps:** show today's and tomorrow's RCE and Kompas Energetyczny hours to shift consumption or battery charging (net-billing).
- **Traders and analysts:** build price, imbalance and load histories at 15-minute, hourly or daily resolution.
- **Researchers and journalists:** study the generation mix, solar and wind shares, and price spikes.
- **AI agents and RAG:** give an assistant current, sourced Polish power prices on request.

### FAQ

**Is there an API for Polish electricity / power-grid data (PSE)?** Yes. PSE publishes a public market-data API at `api.raporty.pse.pl`. This Actor turns those live reports into clean **RCE, day-ahead, imbalance, Kompas Energetyczny, load and generation-mix** rows callable from the Apify API, with CSV/JSON/Excel export.

**How do I export PSE RCE / Kompas prices to CSV or Excel?** Pick `datasets` (e.g. `rce`, `kompas`), set `lastDays` or `dateFrom`/`dateTo`, choose `granularity`, run the Actor, then download the dataset as CSV or Excel from the run page or via the Apify API.

**May I reuse PSE data commercially?** Yes. PSE allows reuse "zarówno w celach komercyjnych, jak i niekomercyjnych" if you name the source, give the retrieval date, remove the PSE logo and say how the data was processed (see Source and attribution). Every row carries `source`, `retrievedAt` and `processingNote`.

**What is the difference vs scraping raporty.pse.pl or ENTSO-E feeds?** Scrapers hit HTML UIs and break easily; ENTSO-E is pan-European and differently shaped. This Actor reads the **official PSE market-data API** for Poland only, with 15-min/hourly/daily aggregation, `onlyNew` revisions and attribution fields on every row.

**Is it legal to reuse this data?** Yes. PSE allows reuse for commercial and non-commercial purposes if you name the source, give the retrieval date and say how the data was processed (see Source and attribution). Every row carries these fields.

**Where does the data come from?** The public PSE market-data API at api.raporty.pse.pl. The Actor does not scrape web pages.

**How fresh is it?** It is read live at run time. RCE and the other day-ahead reports for tomorrow appear after about 14:00 Polish time. Settlement values can be revised, and `onlyNew` delivers a revised row again.

**Rate limits?** PSE publishes none. The Actor sends one request at a time at up to `maxRequestsPerSecond` (default 2) and retries failures with backoff.

### Integrations

- **API:** start runs and read the dataset with the Apify API or the Python and JavaScript clients.
- **Schedules:** run every afternoon with `onlyNew` to receive only new or revised rows.
- **Webhooks:** call your endpoint, Make, Zapier or n8n when a run finishes.
- **MCP and AI agents:** call the Actor as a tool through the Apify MCP server.

### Development

```bash
python3 -m venv .venv && .venv/bin/pip install -r requirements-dev.txt
.venv/bin/python -m pytest -q        # offline tests on recorded PSE responses
examples/run-local-ppe.sh examples/smoke-rce-yesterday-tomorrow.json   # local run with simulated pay-per-event prices (apify-cli, no login)
```

`examples/pricing_info.local.json` holds the simulated price. `docs/DESIGN.md` describes the design.

### Limitations

- The PSE reuse page covers information published on www.pse.pl. The market-data API is the PSE service linked from that site and publishes no separate terms.
- Hourly and daily prices are arithmetic means of the 15-minute values, not volume-weighted averages.
- PSE repeats some rows (for example Kompas on 2026-04-21); the latest publication wins.
- `onlyNew` remembers the most recent 100,000 rows per `stateKey`. Runs sharing a key must not overlap.
- A dataset that fails (HTTP error after retries, or an unexpected response shape) does not stop the others; the run ends FAILED with the reason and keeps the rows already saved.
- The source has no published rate limit. Large backfills of many datasets can take several minutes; raise the run timeout if needed.

### Disclaimer

This Actor is unofficial. It is not affiliated with or endorsed by PSE. Check critical values against [raporty.pse.pl](https://raporty.pse.pl) before you rely on them.

### 🇵🇱 Po polsku

**Dane PSE: rynkowa cena energii RCE i Kompas Energetyczny** – Actor pobiera oficjalne dane z API raportów PSE: RCE (ważna dla prosumentów w net-billingu), cenę day-ahead, ceny rozliczeniowe niezbilansowania, Kompas Energetyczny (PDGSZ), zapotrzebowanie KSE i generację według źródeł. Dane są w wierszach 15-minutowych, godzinowych lub dobowych.

- **Wejście:** raporty (`datasets`), okres (`lastDays` albo `dateFrom`/`dateTo`), rozdzielczość (`granularity`), tylko nowe lub zmienione wiersze (`onlyNew`), limit `maxItems`.
- **Wyjście:** wiersze z cenami w PLN/MWh lub mocą w MW, z czasem w UTC i czasie polskim oraz polami źródła wymaganymi przez PSE.
- **Cena:** $0.0003 za wiersz (`data-row`). Wiersze pominięte przez `onlyNew` są bezpłatne.
- Źródło: Polskie Sieci Elektroenergetyczne S.A., informacja pozyskana ze strony www.pse.pl. Actor nie jest oficjalnym narzędziem PSE.

# Changelog

This Actor's version history is a separate document: https://apify.com/enterprising_hamster/polish-electricity-market-pse/changelog.md

# Actor input Schema

## `datasets` (type: `array`):

PSE reports to download, processed in this order. maxItems applies to all of them together.

## `lastDays` (type: `integer`):

Business days before dateTo (or before today) to include, used when dateFrom is empty. Without dateTo the window ends tomorrow, so day-ahead data appears once PSE publishes it (about 14:00 Europe/Warsaw).

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

Inclusive business date (doba handlowa), YYYY-MM-DD. Overrides lastDays. PSE history starts on 2024-06-14.

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

Inclusive business date, YYYY-MM-DD. Empty means tomorrow.

## `granularity` (type: `string`):

native = rows as PSE publishes them (15 min, Kompas hourly). hour and day aggregate: mean of prices and power, sum of energy, maximum Kompas level. Aggregated rows carry intervalsCount and isComplete.

## `maxItems` (type: `integer`):

Maximum dataset rows and charged events in this run, across all datasets.

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

Skip rows whose values were already delivered by earlier runs with the same stateKey. A PSE revision of a value is delivered again.

## `stateKey` (type: `string`):

Name of the remembered-rows set used by onlyNew. Use different keys for independent schedules.

## `maxRequestsPerSecond` (type: `number`):

Rate limit for PSE requests, including retries. One request at a time.

## Actor input object example

```json
{
  "datasets": [
    "rce",
    "kompas"
  ],
  "lastDays": 1,
  "dateFrom": "",
  "dateTo": "",
  "granularity": "native",
  "maxItems": 200,
  "onlyNew": false,
  "maxRequestsPerSecond": 2
}
```

# Actor output Schema

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

PSE report rows stored in the default dataset.

# 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 = {
    "datasets": [
        "rce",
        "kompas"
    ],
    "lastDays": 1,
    "granularity": "native",
    "maxItems": 200
};

// Run the Actor and wait for it to finish
const run = await client.actor("enterprising_hamster/polish-electricity-market-pse").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 = {
    "datasets": [
        "rce",
        "kompas",
    ],
    "lastDays": 1,
    "granularity": "native",
    "maxItems": 200,
}

# Run the Actor and wait for it to finish
run = client.actor("enterprising_hamster/polish-electricity-market-pse").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 '{
  "datasets": [
    "rce",
    "kompas"
  ],
  "lastDays": 1,
  "granularity": "native",
  "maxItems": 200
}' |
apify call enterprising_hamster/polish-electricity-market-pse --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,enterprising_hamster/polish-electricity-market-pse"
        }
    }
}
```

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/kjjcZaFhZjO6zchgc/builds/WoxDPJd44BU3yQMB5/openapi.json
