# European Fuel Prices - Spain, France & Italy Official Feeds (`eu_open_data/eu-fuel-station-prices`) Actor

Fuel prices for ~41,000 stations from the official Spanish, French and Italian government feeds, normalised into one schema, with daily price-change detection and brand/region aggregates.

- **URL**: https://apify.com/eu\_open\_data/eu-fuel-station-prices.md
- **Developed by:** [joeri munsterman](https://apify.com/eu_open_data) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 station returneds

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

## European Fuel Prices - Spain, France & Italy Official Feeds

Fuel prices for about **41,000 stations**, straight from the **official government feeds** of Spain, France and Italy, normalised into one schema — plus **price-change detection** between runs and **brand/region aggregates**.

No scraping, no proxies, no blocked requests: these are the same published feeds the national price comparison sites use.

### Why not just read the feeds yourself

Because the three governments describe the same pump in three incompatible ways:

- **Spain** publishes one large JSON with comma decimals (`1,459`), and a column per fuel with empty strings where a fuel is absent.
- **France** publishes coordinates as integers multiplied by 100,000, and a separate price and timestamp field per fuel.
- **Italy** publishes two pipe-separated CSVs you have to join, where the fuel names are brand names: *HVOlution*, *Blue Diesel*, *Hi-Q Diesel*, *Gasolio Artico*.

Getting that wrong is easy and expensive. Treat *HVOlution* as ordinary diesel and Italy suddenly looks cheap; treat *Gasolio Artico* (winter diesel) as regular diesel and your cheapest-station ranking is wrong.

### What this Actor gives you

| | |
|---|---|
| **One fuel taxonomy** | `diesel`, `diesel_premium`, `hvo`, `benzine95_e5`, `benzine95_e10`, `benzine98`, `e85`, `lpg`, `cng`, `lng`, `waterstof`, `adblue` — the same names in all three countries |
| **Bad data removed** | Prices more than 30% below or 60% above the national median for that fuel are dropped. The Italian feed alone contains diesel listed at exactly €1.000 |
| **Price changes** | Each run compares with the previous one and emits change rows with old price, new price, difference and percentage |
| **Aggregates** | Average, median, lowest and highest price per brand and country — only brands with at least 5 stations in your result, at most 25 per country, so the add-on never costs more than a few dollars |
| **Geo filter** | Latitude, longitude and radius in km, sorted nearest first |
| **Fresh** | Spain updates continuously, France per station, Italy daily at 08:00 |

### Example output

```json
{
  "land": "ES",
  "stationId": "ES-16106",
  "merk": "Plenergy",
  "adres": "Avenida Del Mar, 12",
  "postcode": "35500",
  "plaats": "Arrecife",
  "regio": "Las Palmas",
  "lat": 28.970139,
  "lon": -13.547056,
  "prijzen": {
    "diesel": { "prijs": 1.467, "valuta": "EUR", "bijgewerktOp": "2026-09-20T21:54:35.000Z", "zelfbediening": null },
    "benzine95_e5": { "prijs": 1.519, "valuta": "EUR", "bijgewerktOp": "2026-09-20T21:54:35.000Z", "zelfbediening": null }
  },
  "aantalPrijzen": 2,
  "goedkoopsteBrandstof": "diesel",
  "bronBijgewerktOp": "2026-09-20T21:54:35.000Z",
  "bron": "MINETUR (Spanje)",
  "bronUrl": "https://geoportalgasolineras.es/"
}
```

A price-change row looks like this:

```json
{
  "type": "prijswijziging",
  "stationId": "IT-3464",
  "land": "IT",
  "brandstof": "diesel",
  "vorigePrijs": 2.339,
  "nieuwePrijs": 2.289,
  "verschil": -0.05,
  "procent": -2.14
}
```

### Typical uses

- **Fleet and fuel-card operators**: find the cheapest station on a corridor, or watch what a competitor's network charges.
- **Price comparison and navigation apps**: one feed instead of three parsers to maintain.
- **Market analysts**: daily brand-level medians per country.
- **Agents and automations**: schedule it daily with *Only price changes* on, and you get just the deltas.

### Pricing

Pay per event, so you pay for results instead of runtime:

| Event | Price |
|---|---|
| `station-snapshot` | $0.004 per station returned |
| `price-change-detected` | $0.02 per detected change |
| `brand-region-aggregate` | $0.15 per aggregate row |

### Sources and limits

- Spain — [MINETUR fuel price API](https://geoportalgasolineras.es/)
- France — [prix-des-carburants, flux instantané](https://data.economie.gouv.fr/explore/dataset/prix-des-carburants-en-france-flux-instantane-v2/)
- Italy — [MIMIT price and station exports](https://carburanti.mise.gov.it/ospzSearch/)

Known limits, stated plainly:

- **France does not publish brand names**, so `merk` is empty there and the brand filter has no effect on French stations.
- Prices are what the operator reported; stations can be late or wrong, and a station that reports nothing simply has no price for that fuel.
- Italian stations report bediend and self-service separately. The lower of the two is used, with `zelfbediening` recording which one it was.
- Spain includes the Canary Islands, where fuel is genuinely cheaper than on the mainland. Those are real prices, not errors.
- If one country's feed is down, the run continues with the others and says which one failed.

# Actor input Schema

## `landen` (type: `array`):

Which official feeds to query.

## `brandstoffen` (type: `array`):

Keep only stations selling these fuels. The first one also decides the sort order. Leave empty for all.

## `merk` (type: `string`):

Filter on brand name, e.g. "repsol", "total", "eni". France does not publish brands.

## `centrum` (type: `string`):

Together with the radius: keep only stations within that radius, nearest first. Example: 40.4168,-3.7038 for Madrid.

## `straalKm` (type: `integer`):

Distance from the centre point, in kilometres. Only used together with a centre point.

## `maxResultaten` (type: `integer`):

Upper bound per run. Also caps the cost, since billing is per station returned.

## `alleenWijzigingen` (type: `boolean`):

Return just the prices that changed since the previous run with the same country selection.

## `aggregaten` (type: `boolean`):

Append rows with average, median, lowest and highest price per brand and country.

## Actor input object example

```json
{
  "landen": [
    "ES"
  ],
  "brandstoffen": [
    "diesel"
  ],
  "centrum": "40.4168,-3.7038",
  "maxResultaten": 100,
  "alleenWijzigingen": false,
  "aggregaten": false
}
```

# Actor output Schema

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

Station rows, followed by price-change rows and brand aggregate rows if those options were enabled. Prices are in EUR per litre (per kg for CNG and hydrogen).

## `overview` (type: `string`):

Stations with only the key columns: country, brand, town, address, prices and last update.

# 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 = {
    "centrum": "40.4168,-3.7038"
};

// Run the Actor and wait for it to finish
const run = await client.actor("eu_open_data/eu-fuel-station-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 = { "centrum": "40.4168,-3.7038" }

# Run the Actor and wait for it to finish
run = client.actor("eu_open_data/eu-fuel-station-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 '{
  "centrum": "40.4168,-3.7038"
}' |
apify call eu_open_data/eu-fuel-station-prices --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,eu_open_data/eu-fuel-station-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/N53vbjXeAwf9LcwaI/builds/gv3NXujhtw45Al39D/openapi.json
