# Canary Islands Electricity Consumption Monitor (ISTAC JSON) (`steadfetch/canarias-electricity-consumption-monitor`) Actor

Return official ISTAC daily electricity consumption for every Canary Island and municipality as JSON, split by Total, Residential, Services and Industry. Public CSV, no login or browser.

- **URL**: https://apify.com/steadfetch/canarias-electricity-consumption-monitor.md
- **Developed by:** [Steadfetch](https://apify.com/steadfetch) (community)
- **Categories:** Business, Other
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 result delivereds

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

## Canary Islands Electricity Scraper (ISTAC Daily Consumption)

Official daily electricity consumption for every Canary Island and municipality, straight from ISTAC (the Canary Islands Statistics Institute). One dataset item per territory, day and economic flow.

### What it does

The Actor downloads the public ISTAC dataset `ISTAC/C00022A_000005` - "Consumo final de energia electrica segun grandes sectores. Municipios de Canarias por dias" - as CSV over plain HTTP and streams it once per run. It keeps the rows that match your filters and pushes one dataset item per observation:

- **Territory:** islands and aggregates (`ES70`, `ES708`, ...) plus 88 municipalities with their 5-digit INE code.
- **Date:** one observation per day.
- **Economic flow:** `Total`, `Residencial`, `Servicios` and `Industria`.
- **Value:** the published consumption figure; the unit is read from the dataset metadata (`MWH` - megawatt-hour - in the current version) and is `null` if the source ever stops declaring one.

No login, no API key, no paywall, no CAPTCHA and no browser. The CSV is downloaded exactly once per run and reading stops as soon as `maxRows` matching rows are found.

#### Coverage measured on 21 October 2026

| Measure | Value |
| --- | --- |
| CSV size | 82,109,984 bytes |
| Data rows | 771,072 (plus 1 header row) |
| Territories | 96 (88 municipalities + islands and aggregates) |
| Dates | 2020-01-01 to 2025-06-30 |
| Economic flows | 4 (`_T`, `RESIDENCIAL`, `SERVICIOS`, `INDUSTRIA`) |
| Rows with an empty `OBS_VALUE` | 0 |
| Source last modified | 2025-09-04 |

The specification written before this build counted 771,073 rows. The file has 771,072 data rows and one header row, so the difference is the header. The Actor publishes what it reads; the delta is recorded in `docs/measurements.md` and is not corrected by hand.

### Example output

The source labels are Spanish; the JSON below uses `\u` escapes so this README stays ASCII. The actual dataset item contains the decoded text.

```json
{
    "measure": "Energ\u00eda el\u00e9ctrica",
    "measureCode": "ENERGIA_ELECTRICA",
    "territory": "Lanzarote",
    "territoryCode": "ES708",
    "date": "2020-07-14",
    "flow": "Total",
    "flowCode": "_T",
    "value": 1759.37,
    "unit": "MWH",
    "notes": null,
    "confidentiality": null,
    "status": null,
    "dataset": "ISTAC/C00022A_000005",
    "sourceUrl": "https://datos.canarias.es/api/estadisticas/statistical-resources/v1.0/datasets/ISTAC/C00022A_000005/1.11.csv",
    "url": "https://datos.canarias.es/api/estadisticas/statistical-resources/v1.0/datasets/ISTAC/C00022A_000005/1.11.csv",
    "scrapedAt": "2026-10-21T15:24:00.000Z"
}
```

`url` is the common Steadfetch envelope field and carries the same value as `sourceUrl`. Every item is validated against `.actor/dataset_schema.json` before it reaches the dataset; with `strictSchema: true` (default) the run fails instead of pushing a malformed item.

### Input

```json
{
    "territories": ["ES708"],
    "dateFrom": "2025-01-01",
    "dateTo": "2025-06-30",
    "flows": ["Total"],
    "maxRows": 100,
    "delayMs": 1000
}
```

- `territories`: `TERRITORIO_CODE` values. Empty means all 96.
- `dateFrom` / `dateTo`: ISO dates (`YYYY-MM-DD`), inclusive. Empty means no bound.
- `flows`: `Total`, `Residencial`, `Servicios`, `Industria`. Empty means all four.
- `maxRows`: 1 to 100000, default 100.
- `delayMs`: politeness delay before the single download, at least 1000 ms. Concurrency is always 1.

### Pricing

| Event | Charged when | Price |
| --- | --- | --- |
| `apify-actor-start` | a run starts (synthetic, automatic) | 0.00005 USD per run |
| `apify-default-dataset-item` | a result is saved to the dataset (synthetic, automatic) | 0.001 USD per result = 1.00 USD per 1,000 results |

There is no custom per-item event and no `Actor.charge()` call, so a result is never billed twice. The price sits between the INE-style reference (`sefran1/ine-spain-statistics`, 0.50 USD per 1,000) and the only energy comparable on the Store (`promptica/eprel-etichette-energetiche`, 3.00 USD per 1,000); no Store Actor packages Canary municipal electricity consumption.

**Measured cost:** estimated at or below **0.05 USD per 1,000 results** - one plain CSV download (about 82 MB) and one small metadata request per run, no browser, no API key, single concurrency. Platform compute cost will be confirmed with a minimal Store run after publication; the estimate is not presented as a measured platform bill.

### FAQ

**Does the Actor need a login or paid subscription?**
No. The ISTAC dataset is public and the Actor only reads it over HTTP.

**Which unit are the values in?**
The metadata declares `MWH` (megawatt-hour) with unit multiplier 0. The Actor reads the unit from the metadata on every run and returns `null` if the source stops declaring one. It never guesses or converts.

**Does it scrape personal data?**
No. Every row is an aggregate for a territory and a day; there are no people, accounts, emails or phone numbers in the dataset.

**How fresh is the data?**
The Actor returns what ISTAC publishes. The current dataset version ends on 2025-06-30 and was last modified on 2025-09-04. The README reports the measured coverage instead of promising a delay the source does not meet.

**How many downloads does one run make?**
Exactly one CSV download plus one metadata request. Reading stops at `maxRows`.

**Is the output schema stable?**
Yes. New fields are added additively and required fields never change; `url` and `scrapedAt` are always present.

### Data licence and attribution

Source: Instituto Canario de Estadistica (ISTAC), Gobierno de Canarias - dataset `ISTAC/C00022A_000005`. Published under **Creative Commons Attribution 4.0 (CC-BY 4.0)**. This Actor attributes ISTAC and the dataset in this README and in `docs/legal-gate.md`, as the licence requires.

### Maintenance

This Actor is **tested daily**: automated runs keep the source reachable and the output schema valid. A failing run becomes an issue in the Steadfetch repository.

### Honest demand note

As of 21 October 2026, Apify Store demand for this niche is **near zero**: no Store Actor packages Canary municipal electricity consumption, and the **first paying buyer** is still being tested. The Actor stays private until that test is positive; the build is justified by the data gap and a Board request, not by proven sales.

# Actor input Schema

## `territories` (type: `array`):

TERRITORIO_CODE values, for example ES708 (Lanzarote) or 35004 (Arrecife). Empty returns all 96 territories (islands, aggregates and municipalities).

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

First observation date, ISO format (YYYY-MM-DD). Empty means no lower bound.

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

Last observation date, ISO format (YYYY-MM-DD). Empty means no upper bound.

## `flows` (type: `array`):

Flow labels to include. Empty returns all four. Codes in the source are \_T, RESIDENCIAL, SERVICIOS and INDUSTRIA.

## `maxRows` (type: `integer`):

Maximum number of results to push to the dataset. The CSV is streamed and reading stops as soon as this many matching rows are found.

## `delayMs` (type: `integer`):

Wait before the single dataset download. Minimum 1000 ms, concurrency is always 1.

## `strictSchema` (type: `boolean`):

Fail the run when an item does not match the OUTPUT schema. Keep enabled: Steadfetch never publishes Actors without output-schema validation.

## Actor input object example

```json
{
  "territories": [
    "ES708",
    "35004"
  ],
  "dateFrom": "2025-01-01",
  "dateTo": "2026-10-31",
  "flows": [
    "Total"
  ],
  "maxRows": 100,
  "delayMs": 2000,
  "strictSchema": true
}
```

# Actor output Schema

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

Dataset items validated against the item schema in dataset_schema.json (fields).

# 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 = {
    "territories": [
        "ES708"
    ],
    "dateFrom": "2020-07-14",
    "dateTo": "2020-07-16",
    "flows": [
        "Total"
    ],
    "maxRows": 10,
    "strictSchema": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadfetch/canarias-electricity-consumption-monitor").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 = {
    "territories": ["ES708"],
    "dateFrom": "2020-07-14",
    "dateTo": "2020-07-16",
    "flows": ["Total"],
    "maxRows": 10,
    "strictSchema": True,
}

# Run the Actor and wait for it to finish
run = client.actor("steadfetch/canarias-electricity-consumption-monitor").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 '{
  "territories": [
    "ES708"
  ],
  "dateFrom": "2020-07-14",
  "dateTo": "2020-07-16",
  "flows": [
    "Total"
  ],
  "maxRows": 10,
  "strictSchema": true
}' |
apify call steadfetch/canarias-electricity-consumption-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadfetch/canarias-electricity-consumption-monitor"
        }
    }
}
```

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/95HgRo1gJDN9ZI5o7/builds/NfXOUErx44A0sjTGs/openapi.json
