# EV Charging Prices Netherlands: Find the Cheapest Charger (`subtleasianmerch/ev-charging-prices`) Actor

Charging prices for every public EV charge point in the Netherlands, cheapest first, with an estimated session cost. From official AFIR open data: per kWh, per minute, session and idle fees. Filter by city, operator or power; get price alerts.

- **URL**: https://apify.com/subtleasianmerch/ev-charging-prices.md
- **Developed by:** [Public Data Tools](https://apify.com/subtleasianmerch) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 charge point with a prices

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

## EV Charging Prices Netherlands: Find the Cheapest Charger

Get the published **charging price** of every public **EV charge point in the Netherlands**, cheapest first, with an estimated cost per session. The prices come from the national open data that operators must publish under the EU's AFIR rules.

- ⚡ **About 170,000 priced charge points** from about 50 operators, Fastned and Tesla among them.
- 🏛️ **Official open data, no scraping:** NDW's DOT-NL files under CC0, status updated every minute.
- 💶 **Comparable prices:** per kWh, per minute, session and idle fees, plus a session cost estimate.
- 📍 **Your area and charger type:** city, postal code or radius; operator, minimum kW and connector.
- 🔔 **Price-change alerts:** scheduled runs return only new charge points and changed tariffs.
- 💸 **$1 per 1,000 priced charge points.** Unpriced, filtered-out and unchanged ones are free.

**Try it:** the input comes pre-filled. Click **Start** to get the 20 cheapest fast chargers (50 kW and up) in Amsterdam, with their prices and an estimated cost for a 20 kWh session.

### What you get

One row per charge point (EVSE), in one format for every operator:

| Data | What's in it |
|---|---|
| **Charge point** | EVSE ID, location ID, operator, owner, address, postal code, city, latitude and longitude, distance from your point |
| **Hardware** | maximum power in kW, AC or DC, connector types (`type2`, `ccs`, `chademo`, …) with each connector's power, voltage and current |
| **Status** | live status as the operator last reported it (`AVAILABLE`, `CHARGING`, `OUTOFORDER`, …), opening hours, parking type, payment options, green energy |
| **Price now** | the price at the start of a session now: per kWh, per hour and per minute of charging, session fee, idle (parking) fee, a later blocking fee, currency, VAT rate |
| **Conditions in words** | e.g. `0.5717 EUR/kWh + 0.0068 EUR/min charging time (every day, 16:00-22:00)`, plus the operator's own tariff text |
| **Estimated session cost** | a standard session (20 kWh starting now by default, or your own size and length), with and without VAT where the operator gives the rate |
| **Tariff as published** | the OCPI 2.2.1 tariff elements, the tariff's ID, type and update time |
| **Changes** | with a monitor ID: new charge point, tariff changed, and the previous prices |
| **Credit** | when the source files were produced, the source address, the licence and the credit line |

### Who it's for

- **Route planners and navigation apps:** show the ad hoc price of each charger along a route, in one format for every operator.
- **Fleet and logistics managers:** find the cheapest fast chargers around depots and routes, and get told when prices change.
- **Price-comparison sites and EV apps:** a daily or hourly feed of charging prices per charge point, through the Apify API.
- **Analysts, journalists and policy researchers:** compare operators, regions and AC/DC prices, and check how complete operators' AFIR price data is.

### How much does it cost?

You pay **$1 per 1,000 charge points** delivered with a price ($0.001 each), plus Apify's standard run start fee.

| Example | Charge points | Cost |
|---|---|---|
| The pre-filled example: the 20 cheapest fast chargers in Amsterdam | 20 | $0.02 |
| Any 1,000 priced charge points | 1,000 | $1 |
| Every priced charge point in Utrecht (a test run on 2 November 2026) | 2,830 | $2.83 |

**Free:**

- charge points outside your filters or beyond your limit;
- charge points without a published price, and all-zero tariffs (both left out by default);
- with a monitor ID, charge points whose tariff hasn't changed;
- runs that fail.

If you turn off **Only charge points with a published price**, those without one cost $0.0002 each. Set a maximum cost per run in the run options. The run stops cleanly at that amount.

### How to use it

1. **Choose the area:** cities (`Amsterdam`, `Den Haag`), postal codes (`1012 AB`, or `10` for central Amsterdam), or a point and a radius in km. Leave both empty for the whole country.
2. **Narrow it down (optional):** operators by name or party ID (`Fastned`, `Allego`, `TSL`), a minimum power (50 for fast chargers), connector types.
3. **Choose the order and the estimate:** cheapest first (by estimated session cost) or nearest first, how many charge points, and the session size.
4. **For price alerts,** add a **Monitor ID** and schedule the Actor, for example hourly. Keep **Output only new charge points and price changes** on.
5. **Click Start.** The **Charge points** table shows the city, address, operator, power, connectors, prices, estimate, status and distance. Export it as JSON, CSV or Excel.

A city also matches its districts, and Den Haag / 's-Gravenhage / The Hague are the same place. With both cities and a point, a charge point is kept when it matches either.

### Example input

**The 10 cheapest fast chargers (50 kW+) within 15 km of central Amsterdam:**

```json
{
  "latitude": 52.3676,
  "longitude": 4.9041,
  "radiusKm": 15,
  "minPowerKw": 50,
  "sortBy": "cheapest",
  "maxChargePoints": 10
}
```

**Every Fastned, IONITY and Tesla charge point with CCS, nearest to Utrecht first:**

```json
{
  "operators": ["Fastned", "IONITY", "Tesla"],
  "connectorTypes": ["ccs"],
  "latitude": 52.0907,
  "longitude": 5.1214,
  "radiusKm": 300,
  "sortBy": "nearest"
}
```

**Hourly price alerts for Rotterdam (schedule this input):**

```json
{
  "locations": ["Rotterdam"],
  "monitorId": "rotterdam-prices",
  "onlyChanges": true
}
```

### Example output

A real Fastned charge point from the national files of 2 November 2026, shortened:

```json
{
  "evseId": "NLFASE3124801",
  "operator": "Fastned",
  "address": "A27, 't Veentje, Eemnes",
  "postalCode": "3755 MV",
  "city": "Eemnes",
  "maxPowerKw": 300,
  "currentType": "DC",
  "connectorTypes": ["ccs"],
  "status": "AVAILABLE",
  "tariffType": null,
  "currency": "EUR",
  "energyPricePerKwh": 0.6364,
  "timePricePerMinute": null,
  "sessionFee": null,
  "vatPercent": 21,
  "pricesIncludeVat": false,
  "priceConditions": ["0.6364 EUR/kWh excl. VAT (21%)"],
  "estimatedSessionCost": 12.73,
  "estimatedSessionCostInclVat": 15.4,
  "estimatedSession": { "kWh": 20, "minutes": 30, "averagePowerKw": 40, "startsAt": "2026-11-02T18:30:00.000Z" },
  "licence": "CC0 1.0 (Creative Commons Zero), NDW open data terms"
}
```

The log shows how many charge points matched and the cheapest estimated session. The `RUN_SUMMARY` record in the run's key-value store has the details:

- what was downloaded;
- how many charge points each filter left out;
- the three cheapest;
- the reason for anything skipped.

#### How the prices are read

- **Units:** the source uses OCPI 2.2.1. Energy is per kWh, time and parking per hour (the rows also give per minute), and prices **exclude VAT** when the operator states a rate. `vatPercent` gives the rate (21% in the Netherlands) and `estimatedSessionCostInclVat` adds it. Some operators state no rate; then `pricesIncludeVat` is null and their prices are as published (often VAT included in practice).
- **Which tariff:** where a charge point has several tariffs, the one typed `AD_HOC_PAYMENT` wins, then an untyped one (valid for every session), then `REGULAR`. Some operators, Vattenfall among them, publish only a `REGULAR` tariff; it's used and labelled. Turn on **Only tariffs that apply to ad hoc payment** to leave those out.
- **Time-of-day and dynamic prices** are worked out for the time of the run, in Dutch time. Dynamic quarter-hour prices (PowerGo and others) are listed from the current window on.
- **Overlapping conditions:** where an operator lists a general price and a narrower one (e.g. idle fee "from minute 0" and "after 45 minutes"), the narrower one applies when it matches.
- **The estimate** charges the energy evenly from now over the session length, or longer when the charge point can't deliver it that fast (20 kWh at 11 kW takes 110 minutes). It adds charging-time prices and the session fee, but no idle time. It's left empty when the tariff doesn't price the whole session (for example a day price with no night price). **It is an estimate, not a quote.**
- **Charge points without a price:** about 12% of charge points have no tariff on the national access point. They're left out free by default.
- **All-zero tariffs:** about 750 charge points have a tariff whose every price is zero: free charging, or a placeholder. They're left out free by default, so they don't crowd a cheapest-first list. Turn on **Include free (all-zero) tariffs** to get them, marked `isFree`.

### Integrations

- **Schedules:** run it hourly or daily in Apify Console. With a monitor ID, each run returns only price changes.
- **Apify API:** start a run and get the charge points back as JSON in one call:

  ```bash
  curl -X POST "https://api.apify.com/v2/acts/subtleasianmerch~ev-charging-prices/run-sync-get-dataset-items?token=YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"locations": ["Utrecht"], "minPowerKw": 50, "maxChargePoints": 10}'
  ```

  Replace `YOUR_TOKEN` with your Apify API token.
- **Webhooks:** call your own endpoint when a run finishes, for example to update prices in your app.
- **Make, Zapier and n8n:** send price changes to Slack, email or a database with Apify's apps for these tools.
- **Monitoring:** Apify's monitoring can alert you when a scheduled run fails or returns fewer results than usual.

### FAQ

#### Is it legal to use?

The data is published as open data under CC0 1.0. NDW's terms, read on 2 November 2026, allow use, copying, changing and passing it on, for commercial purposes too, without asking. NDW asks no credit but appreciates it; each row carries a credit line. The data describes businesses' charge points and holds no personal data, as NDW's FAQ says. This isn't legal advice.

#### Where does the data come from?

From DOT-NL, the Dutch national access point for charging data, run by NDW (Nationaal Dataportaal Wegverkeer) for the Ministry of Infrastructure and Water Management. Under the EU's AFIR regulation (2023/1804), charge point operators must make their locations, status and ad hoc prices available free of charge. The Dutch ones push them to DOT-NL. This Actor downloads the two official files (about 22 MB) once per run.

#### How current are the prices?

NDW rewrites the locations file (with live status) every minute or so; the tariffs file less often (in tests it stayed the same for more than an hour). Each row has `dataUpdatedAt` (the locations file), `tariffsFileUpdatedAt` (the tariffs file) and `tariffUpdatedAt` (when the operator last changed that tariff). Operators are responsible for their data; some tariffs haven't been updated for months.

#### Why does a charge point have no price?

Its operator hasn't published a tariff to the national access point, or refers to a tariff that isn't in the file. A 2026 BEUC and T\&E report found prices often missing or outdated on national access points. This Actor shows what is published, and says so when it isn't.

#### Is the estimated cost what I will pay?

Not exactly. It's an estimate from the operator's published tariff for a standard session starting now. It leaves out idle time, rounding steps and price caps. Your app or card provider may charge differently.

#### How do price alerts work?

Give a **Monitor ID** and schedule the Actor. Runs with the same ID remember each charge point's tariff:

- the first run delivers every matching charge point, marked `isNew: true`;
- later runs deliver only new charge points and those whose tariff changed (`priceChanged: true`), with the previous energy price, time price, session fee and estimate in `previous`;
- unchanged charge points aren't delivered and aren't charged.

A change means any change to the operator's tariff: a new price, a new condition or a new time window. Dynamic tariffs change several times a day. Turn off **Output only new charge points and price changes** to get every charge point each time, with changes marked. Charge points not seen for 60 days are forgotten.

#### What about other countries?

Germany's MobiData BW service was checked in November 2026: only about a third of its charge points carry a price, because most come from the federal register, which has none. France's national file has prices as free text only. More countries may follow where the open data carries structured prices.

### Related Actors

| Actor | What it does |
|---|---|
| [Fuel Prices](https://apify.com/subtleasianmerch/fuel-prices) | Petrol and diesel prices per station in France and Spain, from the governments' open data |

# Actor input Schema

## `locations` (type: `array`):

One per line, e.g. Amsterdam, Utrecht, Den Haag, 3511 or 1012 AB. A shorter postal code covers an area: 10 is central Amsterdam. A city also matches its districts ("Amsterdam" includes "Amsterdam Zuidoost"). Leave empty, with no point below, for the whole country.

## `latitude` (type: `number`):

With longitude and radius: charge points within the radius of this point, e.g. 52.3676 for central Amsterdam. Combined with the cities above, a charge point is kept when it matches either.

## `longitude` (type: `number`):

E.g. 4.9041 for central Amsterdam.

## `radiusKm` (type: `number`):

Used only with a latitude and longitude. Each charge point gets its distance from the point (distanceKm).

## `operators` (type: `array`):

Only these charge point operators, by name or 3-letter party ID, e.g. Fastned, Allego, Shell Recharge, Vattenfall, TSL. A name matches part of the operator's, owner's or sub-operator's name.

## `minPowerKw` (type: `number`):

Only charge points whose fastest connector reaches this power, e.g. 50 for fast chargers or 150 for high-power chargers.

## `connectorTypes` (type: `array`):

Only charge points with at least one of these connectors. Leave empty for every type.

## `onlyWithPrice` (type: `boolean`):

On: charge points whose operator published no tariff to the national access point are left out, free. Off: they're delivered too, without prices, at the lower no-price rate.

## `adHocOnly` (type: `boolean`):

On: only tariffs typed AD_HOC_PAYMENT or untyped (valid for every session) count as a price; tariffs typed REGULAR (charge-card sessions, used by Vattenfall and others as their only tariff) don't. Off: the best published tariff is used, and tariffType says which.

## `includeFree` (type: `boolean`):

Off: charge points whose published tariff prices everything at zero (free charging, or a placeholder some operators publish) are left out, free, so they don't crowd the top of a cheapest-first list. On: they're delivered, marked isFree.

## `sessionKwh` (type: `number`):

The estimated session cost on every row is for this much energy, starting now. 20 kWh is roughly 100-130 km in a typical EV.

## `sessionMinutes` (type: `integer`):

How long the session lasts. When a charge point can't deliver the energy in this time at its maximum power, the estimate uses the longer time it needs (e.g. 55 minutes for 20 kWh at 22 kW).

## `sortBy` (type: `string`):

Cheapest first (by the estimated session cost, including VAT where the operator states the rate), nearest first (needs a point), or as the source lists them. With a limit below, the order decides which charge points are kept.

## `maxChargePoints` (type: `integer`):

E.g. 20 for the 20 cheapest charge points in your area. Leave empty for every matching charge point. Each charge point delivered is charged.

## `monitorId` (type: `string`):

Any name, e.g. "utrecht-fast". Runs with the same ID remember each charge point's tariff, so a schedule can report new charge points and price changes, with the previous prices.

## `onlyChanges` (type: `boolean`):

With a monitor ID: on, only charge points that are new or whose tariff changed since the last run (unchanged ones are free); off, every charge point, with changes marked.

## Actor input object example

```json
{
  "locations": [
    "Amsterdam"
  ],
  "radiusKm": 5,
  "minPowerKw": 50,
  "onlyWithPrice": true,
  "adHocOnly": false,
  "includeFree": false,
  "sessionKwh": 20,
  "sessionMinutes": 30,
  "sortBy": "cheapest",
  "maxChargePoints": 20,
  "onlyChanges": true
}
```

# Actor output Schema

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

The dataset rows this run produced.

## `runSummary` (type: `string`):

Counts, costs and anything skipped, saved as RUN_SUMMARY.

# 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 = {
    "locations": [
        "Amsterdam"
    ],
    "minPowerKw": 50,
    "maxChargePoints": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("subtleasianmerch/ev-charging-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 = {
    "locations": ["Amsterdam"],
    "minPowerKw": 50,
    "maxChargePoints": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("subtleasianmerch/ev-charging-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 '{
  "locations": [
    "Amsterdam"
  ],
  "minPowerKw": 50,
  "maxChargePoints": 20
}' |
apify call subtleasianmerch/ev-charging-prices --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,subtleasianmerch/ev-charging-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/vrMZU3zovsICs1JHT/builds/3RhA4K7qxm1rEyw9h/openapi.json
