# EU Fuel Prices: Spain, France, Italy (official open data) (`italy/eu-fuel-prices`) Actor

Current petrol, diesel, LPG and CNG prices of ~45,000 fuel stations in Spain, France and Italy in ONE normalized format. Official open data. Search by radius, city or postcode; track price changes.

- **URL**: https://apify.com/italy/eu-fuel-prices.md
- **Developed by:** [L Braam](https://apify.com/italy) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 fuel station scrapeds

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

## EU Fuel Prices: Spain, France, Italy (official open data, one format)

Current petrol, diesel, LPG, CNG, E85 and more for **about 45,000 fuel stations** in Spain, France and Italy, in **one normalized format**. The data comes straight from each country's official open-data feed, so there is no scraping of consumer websites and no login.

Every country publishes its prices in a different shape: different field names, decimal commas, time zones, fuel names and unit conventions. This Actor removes that work. You ask "cheapest diesel within 15 km of Girona" or "every LPG station in Italy" and get the same clean fields for every country.

### What you can do with it

- **Find the cheapest fuel** near a point (radius search) or in a city, province or postcode area.
- **Price alerts and monitoring**: switch on *Only new stations and price changes since my last run*, schedule the Actor daily, and receive only what changed, with the previous price included.
- **Compare countries**: national min, median and average per fuel type are added to every run summary.
- **Feed apps, spreadsheets, dashboards and fleet or trip-planning tools** with a consistent structure, as JSON, CSV, Excel or via API.
- Track alternative fuels: LPG (autogas), CNG, LNG, E85, HVO and hydrogen where the country reports them.

### Data sources

| Country | Official source | Stations |
|---|---|---|
| Spain | Ministerio para la Transición Ecológica (Geoportal Gasolineras) | ~11,500 |
| France | data.economie.gouv.fr, "Prix des carburants en France, flux instantané" | ~9,800 |
| Italy | MIMIT (Ministero delle Imprese e del Made in Italy), price and station registry files | ~24,000 |

Every record carries a `dataSource` field with the publisher and licence, and `dataUpdatedAt` with the publication time of the government data set.

Not included: Portugal (the DGEG portal does not allow commercial use without an agreement), Germany (the official feed needs a personal API key) and Austria (feed was unavailable when this Actor was built).

### Normalization

- **One list of fuel types**: `petrol95`, `petrol95E10`, `petrolPremium`, `petrol98`, `diesel`, `dieselPremium`, `lpg`, `cng`, `lng`, `e85`, `hvo`, `hydrogen`. The original name from the source is kept in `label`.
- **Prices as numbers** in EUR per litre (EUR per kg for CNG, LNG and hydrogen), with `unit` on every price.
- **Timestamps in UTC** (ISO 8601). Local times of each source are converted correctly, including summer and winter time.
- **Stale prices are dropped by default**: a station that has not updated a price for more than 7 days is ignored (change with *Ignore prices older than*, 0 keeps everything).
- **Typing errors in the source are dropped**: prices outside a plausible range (for example 18.79 EUR/L) and impossible coordinates are removed, not passed on.
- **Italy**: the self-service price is used when available; the price with service is kept in `servedPrice`.
- **Spain**: stations that sell only to members or fleets are excluded unless you turn on *Include stations that are not open to the public*.

### Input

| Field | What it does |
|---|---|
| Countries | ES, FR, IT. Each selected country is loaded completely and then filtered. |
| Fuel types | Only these fuels (empty = all). With several, price sorting uses the first. |
| Latitude, longitude, radius | Only stations within the radius. Results are sorted nearest first. |
| City, province or street contains | Accent-insensitive text match. |
| Postal code starts with | One or more prefixes, for example `08` or `75`. |
| Brands | For example `repsol`, `total`, `eni`, `galp`. |
| Maximum price | Drops prices above this value. |
| Ignore prices older than | Days. Default 7. 0 = keep all. |
| Include stations not open to the public | Default off. |
| Sort by | Automatic, price, distance or none. |
| Output format | One record per station, or one flat row per station and fuel. |
| Only new stations and price changes | Change tracking between runs (see below). |
| Tracking name | Separate memory per watch list, for change tracking. |
| Maximum results | Safety cap on cost. Default 100. |
| Proxy | Optional. Normally not needed. |

#### Example: cheapest diesel near Barcelona

```json
{
  "countries": ["ES"],
  "fuelTypes": ["diesel"],
  "latitude": 41.3874,
  "longitude": 2.1686,
  "radiusKm": 15,
  "sortBy": "price",
  "maxItems": 20
}
```

### Example output (one record per station)

```json
{
  "country": "ES",
  "stationId": "ES-4375",
  "name": "Nº 10.935",
  "brand": "Nº 10.935",
  "address": "AVENIDA CASTILLA LA MANCHA, 26",
  "postalCode": "02250",
  "city": "ABENGIBRE",
  "province": "Albacete",
  "latitude": 39.211417,
  "longitude": -1.539167,
  "open24h": false,
  "openingHours": "L-D: 07:00-22:00",
  "distanceKm": null,
  "prices": {
    "diesel": { "price": 1.879, "unit": "EUR/L", "updatedAt": "2026-09-21T08:38:32.000Z", "label": "Gasoleo A" },
    "petrol95": { "price": 1.849, "unit": "EUR/L", "updatedAt": "2026-09-21T08:38:32.000Z", "label": "Gasolina 95 E5" }
  },
  "dataSource": "Ministerio para la Transición Ecológica y el Reto Demográfico (Spain), Geoportal de Hidrocarburos",
  "dataUpdatedAt": "2026-09-21T08:38:32.000Z",
  "scrapedAt": "2026-09-21T09:00:00.000Z"
}
```

With *One row per station and fuel*, each fuel becomes its own row (`fuelType`, `price`, `unit`, `updatedAt`, ...), which is the easiest shape for spreadsheets and databases.

### Price changes and alerts

Turn on **Only new stations and price changes since my last run** and schedule the Actor (for example every morning). The first run returns everything. Later runs return only stations that are new or whose price for your chosen fuels changed, each with a `changes` list such as `{ "fuelType": "diesel", "previousPrice": 1.86, "price": 1.879 }`. Runs with no changes return nothing and cost nothing.

The remembered prices are stored per country in your own account (a named key-value store called `eu-fuel-prices-state`). Give each scheduled task with different filters its own **Tracking name**, so their remembered prices do not mix.

### Run summary

Every run saves a `SUMMARY` record: per country the status, number of stations, and the national min, median, average and max for each fuel type. If one country's source is down, the other countries still complete and the summary tells you which one failed.

### Pricing

Pay per result: a small fee per station returned (or per price row in the row format). You only pay for what is delivered, and *Maximum results* caps the cost of a run. Runs with no results, and runs that fail, are not charged for results.

### Limits and honest notes

- Prices are what stations report to their government. The Actor cannot see if a pump is out of stock, and reporting delays of hours to days exist, especially in Italy and France.
- Government servers can change their format or be down for maintenance. If a source fails, the affected country is reported as failed in the summary while other countries continue.
- Some government servers may refuse traffic from outside their country. If that happens, choose *Apify Proxy* with a country in the Proxy field.
- This Actor is not affiliated with, endorsed by or sponsored by any government body. It reuses public data under the sources' own terms: France under the Licence Ouverte 2.0, Italy under the Italian Open Data License (IODL 2.0), Spain under the Ministry's reuse conditions (cite the source, keep the update date, no suggestion of official endorsement). If you redistribute the data yourself, keep the `dataSource` attribution and check the licence links above. This is not legal advice.
- Fuel stations are businesses, not people. No personal data is collected.

### Support

Something not working or a country you need? Open an issue from the Actor page and include the run link.

# Actor input Schema

## `countries` (type: `array`):

Which countries to read. Each country is loaded completely from its official source, then filtered.

## `fuelTypes` (type: `array`):

Only stations with these fuels, and only these fuels in the result. Leave empty for all. With several fuels, 'sort by price' uses the first one.

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

Together with longitude and radius: only stations within the radius of this point. Example: 41.3874 (Barcelona).

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

Example: 2.1686 (Barcelona).

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

Search radius around the centre point. Ignored without latitude and longitude.

## `place` (type: `string`):

Case- and accent-insensitive text match on city, province/department, region and address. Example: Girona, Lyon, Torino, Palermo.

## `postalCodePrefixes` (type: `array`):

For example 08 (Barcelona province), 75 (Paris), 4780. Empty = no filter.

## `brands` (type: `array`):

Only stations whose brand or name contains one of these words, for example repsol, total, eni, eni.

## `maxPrice` (type: `number`):

Drop prices above this value (EUR per litre; per kg for CNG, LNG and hydrogen). Stations with no remaining price are left out.

## `maxPriceAgeDays` (type: `integer`):

Stations sometimes keep a price that has not been updated for weeks. Those are dropped by default. Set 0 to keep everything.

## `includeRestricted` (type: `boolean`):

Spain flags stations that sell only to members or fleets (for example supermarket or company pumps). Off by default.

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

'Automatic' = by distance when a centre point is given, otherwise by price when fuel types are chosen.

## `outputFormat` (type: `string`):

One record per station (all prices inside), or one flat row per station and fuel (best for spreadsheets and databases).

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

Remembers the last delivered prices between runs (per country) and returns only stations that are new or whose price for the chosen fuels changed. Ideal for scheduled runs and price alerts. The first run returns everything.

## `trackingName` (type: `string`):

Name of this watch list. Use a different name for each scheduled task that has different filters, so their remembered prices do not mix. Letters, numbers and dashes.

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

Stops after this many records (stations, or price rows). Protects you from unexpected cost.

## `proxyConfiguration` (type: `object`):

Normally not needed. If a government server refuses the connection from outside its country, choose Apify Proxy and a country code.

## `sources` (type: `object`):

Override the data source URLs. Leave empty.

## Actor input object example

```json
{
  "countries": [
    "ES"
  ],
  "fuelTypes": [
    "diesel"
  ],
  "radiusKm": 10,
  "maxPriceAgeDays": 7,
  "includeRestricted": false,
  "sortBy": "auto",
  "outputFormat": "stations",
  "onlyChanges": false,
  "trackingName": "default",
  "maxItems": 100,
  "sources": {}
}
```

# Actor output Schema

## `stations` (type: `string`):

All returned stations (or price rows) from the dataset.

## `summary` (type: `string`):

Per country: status, number of stations, and national min/median/average/max price per fuel type.

# 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 = {
    "countries": [
        "ES"
    ],
    "fuelTypes": [
        "diesel"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("italy/eu-fuel-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 = {
    "countries": ["ES"],
    "fuelTypes": ["diesel"],
}

# Run the Actor and wait for it to finish
run = client.actor("italy/eu-fuel-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 '{
  "countries": [
    "ES"
  ],
  "fuelTypes": [
    "diesel"
  ]
}' |
apify call italy/eu-fuel-prices --silent --output-dataset

```

## MCP server setup

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