UK Carbon Intensity Scraper: Grid Mix & Emissions
Pricing
from $0.37 / 1,000 intensity scrapeds
UK Carbon Intensity Scraper: Grid Mix & Emissions
Scrape the UK National Grid carbon intensity API: actual and forecast gCO2/kWh, generation mix by fuel type, and regional breakdowns. No login, no proxy, no browser.
Pricing
from $0.37 / 1,000 intensity scrapeds
Rating
0.0
(0)
Developer
Arman Hossain
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
a day ago
Last modified
Categories
Share

UK Carbon Intensity Scraper exports half-hourly carbon intensity for the GB electricity grid, actual and forecast gCO₂/kWh, the intensity index, and the generation mix broken down by fuel, nationally or for any of the 18 grid regions.
It reads the National Grid ESO Carbon Intensity API directly: no proxy setup, no browser, no credentials to manage. Payloads are tiny, which suits the half-hourly cadence of the underlying settlement periods.
Agent skill: SKILL.md
https://api.apify.com/v2/key-value-stores/t7YoTxpZEJOWvw4Ug/records/uk-carbon-intensity-scraper.md
What you get
| Output field | Meaning |
|---|---|
from, to | The half-hour settlement period, ISO 8601 UTC |
intensityForecast | Forecast carbon intensity in gCO₂/kWh |
intensityActual | Settled actual intensity, national only, null for future periods and for regions |
intensityIndex | very low, low, moderate, high, very high |
region | Region ID (1-18), or null for a national reading |
regionName | National, or the region short name such as London |
generationMix | Raw source array: [{ fuel, perc }, …] |
fuelShares | The same data flattened to { biomass: 7.9, coal: 0, … } so it survives a CSV export |
postcode | The outward code you queried, when you queried by postcode |
scrapedAt | Run timestamp |
A RUN_SUMMARY record in the key-value store holds per-run counts, the filters used, and any request that failed.
Four modes
| Mode | What it returns | Needs |
|---|---|---|
current | The settlement period happening right now, nationally | - |
forecast | The next 48 hours, 97 half-hourly periods | - |
historical | Every half hour in your window, nationally | fromDate |
regional | Per-region readings, snapshot or time series | optional regions, optional fromDate |
Common use cases
- Carbon-aware compute scheduling. Run batch jobs when
intensityForecastdips, using the 48-hour forecast. - Scope 2 and ESG reporting. Pull a full reporting year of
intensityActualand multiply by metered consumption. - Smart charging and demand response. Shift EV or heat-pump load into
very lowperiods for a specific postcode. - Renewables analysis. Track wind and solar share over time from
fuelShares. - Regional comparison. North Scotland and London differ by an order of magnitude at the same moment.
Quick start
Right now, nationally:
{"mode": "current"}
The next 48 hours, for a load-shifting scheduler:
{"mode": "forecast"}
A full month of settled national data for reporting:
{"mode": "historical","fromDate": "2026-07-01","toDate": "2026-08-01"}
Two postcodes as a week-long time series:
{"mode": "regional","regions": ["SW1A 1AA", "RG10"],"fromDate": "2026-08-01","toDate": "2026-08-08"}
All 18 regions right now, one request:
{"mode": "regional","regions": []}
Input
| Field | Type | Default | Notes |
|---|---|---|---|
mode | string | current | current, forecast, historical or regional. |
fromDate | string | - | YYYY-MM-DD or ISO 8601. Required for historical. In regional mode it turns a snapshot into a time series. |
toDate | string | now | YYYY-MM-DD or ISO 8601. Windows over 14 days are split into 14-day requests automatically. |
regions | array | [] | Region IDs 1-18, or UK postcodes. Empty in regional mode returns all 18 in one request. |
includeGenerationMix | boolean | true | Include per-fuel shares. Turn off for a smaller, faster dataset. |
maxResults | integer | 0 | Cap on readings saved. 0 = no limit. |
fromDate is ignored in current mode, and regions is ignored in every mode except regional.
Output example
{"from": "2026-08-06T11:00Z","to": "2026-08-06T11:30Z","intensityForecast": 62,"intensityActual": 61,"intensityIndex": "low","region": null,"regionName": "National","generationMix": [{ "fuel": "biomass", "perc": 7.9 },{ "fuel": "coal", "perc": 0 },{ "fuel": "imports", "perc": 17.2 },{ "fuel": "gas", "perc": 7.5 },{ "fuel": "nuclear", "perc": 12.7 },{ "fuel": "other", "perc": 0 },{ "fuel": "hydro", "perc": 0 },{ "fuel": "solar", "perc": 24.5 },{ "fuel": "wind", "perc": 30.2 }],"fuelShares": {"biomass": 7.9, "coal": 0, "imports": 17.2, "gas": 7.5,"nuclear": 12.7, "other": 0, "hydro": 0, "solar": 24.5, "wind": 30.2},"postcode": null,"scrapedAt": "2026-08-06T12:00:00.000Z"}
API example
curl -X POST "https://api.apify.com/v2/acts/arman-bd~uk-carbon-intensity-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H "Content-Type: application/json" \-d '{"mode": "historical","fromDate": "2026-08-01","toDate": "2026-08-02"}'
JavaScript example
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_TOKEN' });const run = await client.actor('arman-bd/uk-carbon-intensity-scraper').call({mode: 'forecast',});const { items } = await client.dataset(run.defaultDatasetId).listItems();const greenest = items.reduce((a, b) => (b.intensityForecast < a.intensityForecast ? b : a));console.log(`Cleanest window: ${greenest.from} at ${greenest.intensityForecast} gCO2/kWh`);
Notes
- Regional readings have no
intensityActual. The source publishes a settled actual for the national grid only; regional data is forecast-based. The field is present andnullrather than missing, so your schema stays stable. - Forecast periods also have a
nullactual. Anything in the future has not settled yet. That is expected, not a gap. - Forecast mode has no generation mix. The
/generationendpoint accepts settled windows only; there is no forward variant, sogenerationMixandfuelSharesarenullinforecastmode. Regional forecasts do carry a mix, because it is embedded in the regional response. - Long windows are split automatically. The API documents a 14-day ceiling per historical request, so a year-long window becomes 27 sequential requests. Each is a separate entry in
RUN_SUMMARY.failuresif it fails, and one failure never discards the others. - The national generation mix comes from a second endpoint.
/intensityand/generationare keyed on the same settlement periods, so the two are joined onfrom. If the mix call fails, the intensity record is still saved withgenerationMix: null. fuelSharesexists because arrays flatten badly.generationMixis the source array;fuelSharesis the same numbers as named columns, which is what you want in CSV or a spreadsheet.- Postcodes are trimmed to the outward code.
SW1A 1AAbecomesSW1A, because the API rejects anything longer. - Transient errors are retried. 429, 5xx and network errors get four attempts with exponential backoff (0.5 s → 1 s → 2 s). A rejected region or malformed window fails immediately rather than burning retries.
- Public data only. No authentication, no personal data, no access-control bypass.
FAQ
Do I need a proxy? No. Proxy configuration is not required to run this Actor.
Do I need an account on the source? No, and there is no credentials to manage.
What happens if a request fails? It is reported in RUN_SUMMARY.failures and the run continues. The Actor only errors out if every request failed.
Can I schedule it? Yes, it is designed for scheduled runs. A half-hourly current run mirrors the grid's own settlement cadence.
Does it cover Northern Ireland? No. The API covers Great Britain; Northern Ireland runs on a separate grid.
What are the region IDs? 1-14 are the DNO regions, running roughly north to south: 1 North Scotland, 2 South Scotland, 3 North West England, 13 London, 14 South East England. Then 15 England, 16 Scotland, 17 Wales and 18 GB. Run regional with an empty regions list to see all of them with their names. Note that the API's own error message wrongly says the range is 1-17; 18 works.
Why does intensityForecast differ from intensityActual? The forecast is published ahead of time; the actual is settled afterwards from metered generation. Comparing the two is a legitimate use of this data.
How far back does history go? To May 2017, when the API began publishing.
Can I integrate it with something else? Yes, Apify API, client libraries, webhooks, scheduled runs, dataset exports (JSON/CSV/Excel) or MCP. Output is structured JSON.