Europe Fuel Prices Scraper: Spain and Portugal Stations avatar

Europe Fuel Prices Scraper: Spain and Portugal Stations

Pricing

from $0.50 / 1,000 fuel stations

Go to Apify Store
Europe Fuel Prices Scraper: Spain and Portugal Stations

Europe Fuel Prices Scraper: Spain and Portugal Stations

Current fuel prices at every station in Spain and Portugal, straight from the official government sources: diesel, petrol 95 and 98, LPG and more, each with its update time. Filter by province, city or radius. No personal data, no proxies.

Pricing

from $0.50 / 1,000 fuel stations

Rating

0.0

(0)

Developer

Rowcraft

Rowcraft

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

9 days ago

Last modified

Features

Limited permissions

Share

Get the current fuel prices of petrol stations in Spain and Portugal from the two official government services. This Europe fuel prices scraper reads the Spanish Ministry of Industry and Tourism and the Portuguese DGEG directly, so it does not break when a price website changes its layout and it needs no proxy, no login and no API key. Each station comes back as one row: address, postal code, city, province or district, coordinates, the brand where it is safe to show one, the price of every fuel the station lists (diesel, petrol 95 and 98, LPG, natural gas, hydrogen and more) and the time of the update, as JSON, CSV or Excel.

Filter by province, district, postal code, city, fuel or distance from a point, or take a whole country. Schedule it with Only new rows to get only the stations whose prices changed since the last run, and pay only for those rows.

Results of Europe Fuel Prices Scraper: Spain and Portugal Stations in the Apify dataset view

What you get

Price: $0.80 per 1,000 fuel stations on the Free plan, $0.50 on the Business plan, paid per row delivered; the $5 monthly credit of a free Apify account covers about 6,200 fuel stations. Details in Pricing below.

One row per station, the same columns for every station of both countries:

  • Station: an ID that starts with the country (ES-6207, PT-66676), street address, postal code, city, municipality, province (Spain) or district (Portugal), the autonomous community for Spain, latitude and longitude in decimal degrees
  • Brand: the label the station sells under (Repsol, Galp, BP, Moeve and so on), shown only when it is a recurring label (see Privacy), otherwise null
  • Prices: diesel, dieselPremium, petrol95, petrol98 and lpg as plain columns for quick tables, and prices, the full list: for every fuel the station sells, a normalised fuel code (diesel, petrol_95, petrol_95_e10, cng, hydrogen, adblue and others), the label exactly as the source writes it, the price, the unit (litre, kg or m3) and the update time
  • Availability and type: the list of fuels that have a price, whether the Spanish station sells to the public, the type of Portuguese station (motorway, hypermarket, other), and the opening hours of Spanish stations as readable text
  • Source and time: priceUpdatedAt with its time zone, the name of the publisher in source, the address of the official service in sourceUrl, and the moment the actor read it in fetchedAt
  • Search helpers: distanceKm when you search around a point, and changedFuels when you use Only new rows

Prices are current prices only. Neither service publishes history, so to build one you run the actor on a schedule.

Why this actor

  • Two official services, one table. Spain and Portugal publish their station prices themselves. The actor reads both and returns the same columns, with fuels mapped to the same codes, so a Madrid station and a Lisbon station sit in one dataset.
  • Every price has a time and a source. Each row names the publisher and carries the update time, so you can show where the data comes from, as the source conditions ask, and drop prices that nobody has touched for days.
  • Filters that read like a map. Provinces by code or name (28, Madrid, A Coruña), Portuguese districts (Lisboa, Faro, 7), postal codes, cities written any way you like, fuels, and a centre point with a radius that delivers the nearest stations first.
  • Only the prices that changed. Turn on Only new rows and a station comes back only when one of its prices is new since your last run. An hourly or daily schedule then costs you the changes, not the whole country.
  • Polite by design. The actor reads the robots.txt of each host first, makes at most one request per second, retries with a pause when a service is busy, uses no proxy and never tries to get around a block.
  • No personal data, no surprises on the bill. The services describe stations, not people, and the actor drops what could identify one. You pay per delivered station, with a charge cap you control.

How to use it

  1. Open the Actor and fill in Countries (the other fields are optional filters).
  2. Set Maximum fuel stations to a small number for a first try (the default is a safe start).
  3. Click Start. The status line shows progress; the run stops cleanly at your limit or at the charge limit you set in the run options.
  4. Open the Dataset tab and download JSON, CSV, Excel, XML or HTML, or send the rows to Google Sheets, Slack, Make, n8n or Zapier with the Integrations tab.
  5. To run it on a schedule, use Schedules in Apify Console and turn on Only new rows since the last run below: every run then costs only the new rows, and a webhook URL tells you when something new came in.

Input

Quick start. This input is ready to run (it is also the example in the API tab):

{
"countries": [
"ES"
],
"provinces": [
"02"
],
"fuels": [
"diesel"
],
"maxItems": 100
}

One real row it returns (long texts shortened here):

{
"stationId": "ES-6207",
"country": "ES",
"brand": "REPSOL",
"address": "AUTOVIA A-2 KM. 154",
"postalCode": "42248",
"city": "LODARES",
"municipality": "Medinaceli",
"province": "SORIA",
"provinceCode": "42",
"region": "Castilla y León",
"latitude": 41.189222,
"longitude": -2.403972,
"stationType": null,
"publicSale": true,
"openingHours": "Mon 07:00-00:00; Tue-Fri 24h; Sat 00:00-21:00; Sun 08:00-22:00",
"diesel": 1.925,
"dieselPremium": 2.025,
"petrol95": 1.755,
"petrol98": 1.915,
"lpg": 1.129,
"fuelsAvailable": [
"diesel",
"diesel_premium",
"petrol_95",
"… 2 more"
],
"prices": [
{
"fuel": "diesel",
"rawFuelLabel": "Gasoleo A",
"price": 1.925,
"unit": "litre",
"priceUpdatedAt": "2026-10-26T06:49:42"
},
{
"fuel": "diesel_premium",
"rawFuelLabel": "Gasoleo Premium",
"price": 2.025,
"unit": "litre",
"priceUpdatedAt": "2026-10-26T06:49:42"
},
{
"fuel": "petrol_95",
"rawFuelLabel": "Gasolina 95 E5",
"price": 1.755,
"unit": "litre",
"priceUpdatedAt": "2026-10-26T06:49:42"
},
"… 2 more"
],
"currency": "EUR",
"priceUpdatedAt": "2026-10-26T06:49:42",
"timeZone": "Europe/Madrid",
"source": "Ministerio de Industria y Turismo (Spain)",
"sourceUrl": "https://sedeaplicaciones.minetur.gob.es/ServiciosRESTCarburantes/PreciosCarburantes/EstacionesTerrestres/",
"fetchedAt": "2026-10-26T05:49:40.503Z",
"distanceKm": null,
"changedFuels": null
}
FieldWhat it does
countriesES for Spain, PT for Portugal, or both. Default: Spain
provincesSpanish provinces, one per line: the code 01 to 52 (28, 02) or the name (Madrid, Málaga, A Coruña). Empty = all 52 provinces
districtsPortuguese districts, one per line: the number 1 to 18 or the name (Lisboa, Porto, Faro, Évora). Empty = all 18 districts of the mainland
fuels, fuelsMatchKeep only stations that have a price for these fuels. With several fuels, fuelsMatch chooses between all of them (default) and at least one
maxItemsStops after this many stations. Default 500; 0 = no limit
postalCodes, citiesSpain: five digits (a dropped leading zero is repaired: 2001 = 02001). Portugal: 1000-001, or the first four digits for the whole area. City names in any capitalisation, with or without accents
center, radiusKmLatitude and longitude as Google Maps shows them (40.4168, -3.7038) and a radius in kilometres (default 10). The nearest stations come first and each row carries distanceKm
onlyNew, stateName, notifyUrl, notifyWhenEmptyOnly the stations whose prices changed since the last run, and a webhook message at the end; see Automation below

Different filters narrow each other (province and city and fuel); several values inside one filter widen it (Madrid or Barcelona). A province applies to Spain and a district to Portugal. If you select both countries and give a province but no district, Portugal is read in full, and the actor tells you so in the log and in the run summary. A value that matches nothing is reported there too, instead of silently returning an empty result.

Example: the diesel price of every station within 15 km of the centre of Madrid, nearest first.

{
"countries": ["ES"],
"center": "40.4168, -3.7038",
"radiusKm": 15,
"fuels": ["diesel"],
"maxItems": 0
}

Example: every station of the Lisbon and Porto districts that sells LPG, in one file.

{
"countries": ["PT"],
"districts": ["Lisboa", "Porto"],
"fuels": ["lpg"],
"maxItems": 0
}

More recipes, all of them plain input you can paste into the form's JSON view:

{
"countries": ["ES"],
"provinces": ["Barcelona", "Girona"],
"fuels": ["petrol_95", "petrol_95_e10"],
"fuelsMatch": "any",
"maxItems": 0
}

The stations of two Catalan provinces that sell petrol 95 (E5) or petrol 95 E10. Use fuelsMatch: "all" (the default) to keep only stations that sell both.

{
"countries": ["ES", "PT"],
"provinces": ["Badajoz", "Cáceres"],
"districts": ["Portalegre", "Castelo Branco"],
"maxItems": 0
}

Both sides of the Spanish and Portuguese border in one table, for a cross-border price comparison.

{
"countries": ["ES", "PT"],
"fuels": ["diesel"],
"maxItems": 0,
"onlyNew": true,
"stateName": "iberia-diesel",
"notifyUrl": "https://hooks.example.com/your-webhook"
}

A watch over both countries for a schedule: the first run delivers every station with a diesel price, each later run delivers only the stations whose diesel price changed, and a message goes to your webhook when new rows came in.

Output

30 fields per row. Empty values are null, never missing, so CSV and Excel columns are stable.

FieldTypeExample
stationIdstringES-12054
countrystringES
brandstringREPSOL
addressstringCALLE PRINCIPE DE ASTURIAS (POLÍGONO DE ROMICA), 5
postalCodestring02001
citystringALBACETE
municipalitystringAlbacete
provincestringALBACETE
provinceCodestring02
regionstringCastilla la Mancha
latitudenumber39.054694
longitudenumber-1.832
stationTypestringmotorway
publicSalebooleanTrue
openingHoursstringMon-Sun 06:00-22:00
dieselnumber1.949
dieselPremiumnumber2.039
petrol95number1.765
petrol98number1.905
lpgnumber0.989
fuelsAvailablearray["diesel", "petrol_95", "petrol_98"]
pricesarray[{"fuel": "diesel", "rawFuelLabel": "Gasoleo A", "price": 1.949, "u…
currencystringEUR
priceUpdatedAtstring2026-10-26T06:38:57
timeZonestringEurope/Madrid
sourcestringMinisterio de Industria y Turismo (Spain)
sourceUrlstringhttps://sedeaplicaciones.minetur.gob.es/ServiciosRESTCarburantes/Pr…
fetchedAtstring2026-10-26T05:38:55.771Z
distanceKmnumber3.24
changedFuelsarray["diesel"]

Working with the data

  • Prices are euros, as numbers, with up to three decimals. The unit of each price is in prices[].unit: litre for liquid fuels, kg for natural gas, hydrogen and liquefied biogas, m3 for the Portuguese compressed natural gas price per cubic metre. Do not rank kg prices against litre prices.
  • The five plain columns follow one rule. diesel is the standard diesel (Spanish Gasóleo A, Portuguese Gasóleo simples), dieselPremium the premium grade, petrol95 the standard 95 petrol (Gasolina 95 E5 in Spain, Gasolina simples 95 in Portugal), petrol98 the 98 petrol and lpg the autogas. E10, E25, premium petrol, renewable diesel, natural gas, hydrogen and AdBlue are in prices.
  • Rank by price, filter by time. Sort the dataset on a price column and keep rows whose priceUpdatedAt is recent. A Portuguese price that nobody has touched for a week is common and is the first one to check when you plan a trip.
  • The stationId is stable. The part after the country prefix is the station's own ID in the official service. Use it to join runs over time, to keep a price history of your own, or to match stations with another list.
  • Group on province or region to compute averages in a spreadsheet; provinceCode keeps its leading zero as text, so it survives CSV and Excel.
  • Empty is null. A fuel the station does not sell, a missing opening-hours text or a missing distance is null, never an empty string or a zero, so a filter such as "diesel is not empty" works the same in every tool.

Run summary and coverage

Every run writes a RUN_SUMMARY record to the key-value store: how many stations were read, how many matched your filters, how many were delivered, why the run stopped (all read, maximum reached, charge limit, or a refusal or outage of a source), what each country did, the errors of the sources, the filters as the actor understood them, warnings, and the memory peak. A second record, COVERAGE, lists every province, district, postal code and city you asked for with the number of stations that matched it on its own, so a misspelt city shows up as not_found instead of a silent empty dataset.

Example rows

Two real rows from a run (long texts shortened here, complete in the dataset):

[
{
"stationId": "ES-6207",
"country": "ES",
"brand": "REPSOL",
"address": "AUTOVIA A-2 KM. 154",
"postalCode": "42248",
"city": "LODARES",
"municipality": "Medinaceli",
"province": "SORIA",
"provinceCode": "42",
"region": "Castilla y León",
"latitude": 41.189222,
"longitude": -2.403972,
"stationType": null,
"publicSale": true,
"openingHours": "Mon 07:00-00:00; Tue-Fri 24h; Sat 00:00-21:00; Sun 08:00-22:00",
"diesel": 1.925,
"dieselPremium": 2.025,
"petrol95": 1.755,
"petrol98": 1.915,
"lpg": 1.129,
"fuelsAvailable": [
"diesel",
"diesel_premium",
"petrol_95",
"… 2 more"
],
"prices": [
{
"fuel": "diesel",
"rawFuelLabel": "Gasoleo A",
"price": 1.925,
"unit": "litre",
"priceUpdatedAt": "2026-10-26T06:49:42"
},
{
"fuel": "diesel_premium",
"rawFuelLabel": "Gasoleo Premium",
"price": 2.025,
"unit": "litre",
"priceUpdatedAt": "2026-10-26T06:49:42"
},
{
"fuel": "petrol_95",
"rawFuelLabel": "Gasolina 95 E5",
"price": 1.755,
"unit": "litre",
"priceUpdatedAt": "2026-10-26T06:49:42"
},
"… 2 more"
],
"currency": "EUR",
"priceUpdatedAt": "2026-10-26T06:49:42",
"timeZone": "Europe/Madrid",
"source": "Ministerio de Industria y Turismo (Spain)",
"sourceUrl": "https://sedeaplicaciones.minetur.gob.es/ServiciosRESTCarburantes/PreciosCarburantes/EstacionesTerrestres/",
"fetchedAt": "2026-10-26T05:49:40.503Z",
"distanceKm": null,
"changedFuels": null
},
{
"stationId": "PT-66676",
"country": "PT",
"brand": "REPSOL",
"address": "Rua Mestre João Serra Lt. D",
"postalCode": "7300-069",
"city": "Zona Industrial",
"municipality": "Portalegre",
"province": "Portalegre",
"provinceCode": "12",
"region": null,
"latitude": 39.26658,
"longitude": -7.43713,
"stationType": "other",
"publicSale": null,
"openingHours": null,
"diesel": 2.304,
"dieselPremium": 2.374,
"petrol95": 2.109,
"petrol98": null,
"lpg": 1.029,
"fuelsAvailable": [
"lpg",
"petrol_95",
"diesel",
"… 1 more"
],
"prices": [
{
"fuel": "lpg",
"rawFuelLabel": "GPL Auto",
"price": 1.029,
"unit": "litre",
"priceUpdatedAt": "2026-10-26T00:00:00"
},
{
"fuel": "petrol_95",
"rawFuelLabel": "Gasolina simples 95",
"price": 2.109,
"unit": "litre",
"priceUpdatedAt": "2026-10-26T00:00:00"
},
{
"fuel": "diesel",
"rawFuelLabel": "Gasóleo simples",
"price": 2.304,
"unit": "litre",
"priceUpdatedAt": "2026-10-26T00:00:00"
},
"… 1 more"
],
"currency": "EUR",
"priceUpdatedAt": "2026-10-26T00:00:00",
"timeZone": "Europe/Lisbon",
"source": "DGEG (Portugal)",
"sourceUrl": "https://precoscombustiveis.dgeg.gov.pt/",
"fetchedAt": "2026-10-26T05:49:43.647Z",
"distanceKm": null,
"changedFuels": null
}
]

Results can be downloaded as JSON, CSV, Excel, XML or HTML from the Dataset tab, or read through the Apify API.

Input form of Europe Fuel Prices Scraper: Spain and Portugal Stations

Pricing

Pay per result. You pay for each fuel station delivered to your dataset, nothing else: no subscription, no minimum, no charge for rows your filters drop or for the requests behind them.

Your Apify planPrice per 1,000 rowsPrice per row
Free plan$0.80$0.0008
Starter plan$0.70$0.0007
Scale plan$0.60$0.0006
Business plan and above$0.50$0.0005

Example: 1,000 fuel stations cost $0.80 on the Free plan and $0.50 on the Business plan. Platform usage of the run (compute, storage) is included in that price and is not billed to you separately (pay per event: the actor covers it). A start event of $0.00005 is charged once per run (Apify default). Cap your spend: set Maximum total charge in the run options. The actor stops cleanly when the cap is reached and you keep everything delivered until then. The run summary (RUN_SUMMARY in the key-value store) says why a run stopped.

A run over the whole of Spain (about 11,400 stations, maxItems set to 0) costs about $9.12 at the Free plan price and $5.70 at the Business plan price. A Spanish province holds between about 10 and 900 stations, so one province costs between 1 cent and 72 cents at the Free plan price. A Portuguese district holds between about 50 and 400 stations.

Automation: only new rows, notifications, schedules

Only new rows since the last run. Turn on onlyNew and the actor remembers every fuel station it delivered to you (in a key-value store named rowcraft-europe-fuel-prices-scraper-state in your Apify account). The next run with the same stateName skips what you already have and you pay only for new rows. The first run delivers everything that matches. Use a different stateName for each schedule or search so they keep separate memories.

Notification when the run ends. Put a webhook address in notifyUrl and the actor sends one JSON POST with the number of new rows, links to the dataset (JSON and CSV) and the run. It works out of the box with Slack and Discord incoming webhooks (the message is in text and content), with Make, n8n and Zapier catch hooks, and with your own endpoint. By default it is sent only when there is at least one new row; notifyWhenEmpty sends it every time.

Schedules. Create a schedule in Apify Console (hourly, daily, weekly or cron) with onlyNew on. A daily schedule gives you a feed of new fuel stations for the price of the new rows only.

Integrations. Send the results to Make, n8n, Zapier, Google Sheets, Slack, Google Drive, Airtable or any webhooks from the Integrations tab of the Actor, with no code. Apify also offers native actions for Make, n8n and Zapier.

API, SDKs and AI agents. Every run is available through the Apify API and the official JavaScript and Python clients; the Actor can also be called by AI agents through the Apify MCP server. The example input in the API tab is a working call.

Use with AI agents (MCP). Add the Apify MCP server to Claude, Cursor, VS Code or any MCP client and the agent can run this Actor as a tool:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=rowcraft/europe-fuel-prices-scraper",
"headers": {
"Authorization": "Bearer <YOUR_APIFY_TOKEN>"
}
}
}
}

Call it from a shell or any language. One request runs the Actor with the input below and returns the rows as JSON:

curl -X POST "https://api.apify.com/v2/acts/rowcraft~europe-fuel-prices-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"countries": ["ES"], "provinces": ["02"], "fuels": ["diesel"], "maxItems": 100}'

Python (pip install apify-client):

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("rowcraft/europe-fuel-prices-scraper").call(run_input={'countries': ['ES'], 'provinces': ['02'], 'fuels': ['diesel'], 'maxItems': 100})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)

JavaScript / Node.js (npm install apify-client):

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('rowcraft/europe-fuel-prices-scraper').call({"countries": ["ES"], "provinces": ["02"], "fuels": ["diesel"], "maxItems": 100});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

What counts as new here. The two services work differently, and so does the comparison.

  • Portugal gives every price its own timestamp. The actor remembers each combination of station, fuel and timestamp it has delivered to you, and a station comes back when at least one of its prices carries a timestamp you do not have yet.
  • Spain publishes one timestamp for the whole file, refreshed about every half hour, so a timestamp cannot tell which prices moved. The actor remembers each combination of station, fuel and price value instead, and a station comes back when it has a price value that was never delivered to you for that fuel. A price that returns to a value you already received is not delivered again.

In both cases the changedFuels column says which fuels are new, and the row still carries all current prices of the station. Stations without anything new are skipped and are not charged.

Use cases

  • Price monitoring: a scheduled run per province or district, a webhook into Slack or a spreadsheet, and an alert when the cheapest diesel of your area moves.
  • Fleet and logistics: the cheapest stations around a depot or along a border crossing, with the fuel you need, ranked by distance, in two countries at once.
  • Price comparison and apps: a fresh, normalised table of stations with coordinates for a map or a comparison page, refreshed on a schedule.
  • Journalism and research: regional price differences, the gap between Spanish and Portuguese diesel, and the spread between standard and premium grades, from official sources you can cite.
  • Spreadsheets and dashboards: send the dataset to Google Sheets, Airtable or a BI tool and compute your own averages per province, district or brand.

Ready-made examples, each with the input filled in (open one and press Start, or save it as your own task):

What this actor does not do

  • Deliver a brand for every station. A label that only one or two stations use can be the name of a person, so it is replaced by null.
  • Deliver station names, phone numbers, e-mail addresses or the names of operators.
  • Deliver price history. It reads the current prices; use a schedule to collect your own history.
  • Look up addresses or place names for the radius search. Give coordinates in center; the actor does not call a geocoder or any other website.
  • Cover other countries, electric charging prices or heating oil. France has its own Rowcraft actor, listed below.
  • Cover the Portuguese islands: the Portuguese service lists no station in the Azores or Madeira.
  • Compute averages, rankings or forecasts. It delivers the rows; the calculation is yours.
  • Use proxies, log in, solve CAPTCHAs or look for a way around a block.

Limits and fair use

  • Read one province or district at a time. Spain's service is read one province per request (the whole country in one file is 12 MB and would not fit a small run), Portugal's one district per request, with all road fuels in one go. A whole-country run is 52 requests for Spain and about 20 for Portugal, about a minute each at the default pace of one request per second. The minimum pause is 500 ms.
  • Robots.txt first. The actor reads the robots.txt of each host before its first request and skips a country whose rules forbid the path.
  • Freshness. Spain refreshes its file about every half hour and stamps the whole file with one time. Portugal stamps each price when the operator reports it, so some prices are days old. Filter on priceUpdatedAt if you need recent prices only.
  • Default of 500 stations. Without filters the first 500 stations are delivered and reading stops there; the run summary says that more exist. Set Maximum items to 0 for everything that matches.
  • Spain without a province. A city, centre point or fuel filter without a province reads all 52 provinces first, because the service cannot be searched by city. A Spanish postal code names its province, so the run reads only that one.
  • If a source is down or refuses the request, the run ends normally, delivers nothing from that country and charges only the start event. After three failed requests in a row the actor gives that country up, and the run summary lists the errors. Run again later.
  • Memory. The default of 256 MB is enough for both countries in full.

What a run does, step by step

  1. It reads your input and checks the values that could cost you money if misread: an unknown country, a centre point that is not a coordinate, a radius that is not a number, a fuel it does not know. A bad value stops the run before any request is sent.
  2. For each country it requests the robots.txt of the data host and skips the country if the path is disallowed.
  3. It reads the provinces or districts one request after the other, at the pace you set.
  4. It maps every station to a row, counts the brand labels, applies your filters and, with Only new rows, drops the stations without anything new.
  5. It delivers the rows in batches of 500 and stops at your maximum or your charge limit.
  6. It writes the run summary and the coverage report, and sends the webhook message if you set one.

Data source (and licence)

The Spanish prices come from the Precios de carburantes REST service of the Ministerio de Industria y Turismo, at sedeaplicaciones.minetur.gob.es, which the ministry publishes with its open data (see its open data portal). The general reuse conditions of that portal, which follow Law 37/2007 on the reuse of public sector information, ask you to name the source, to state the date of the last update and not to alter the content or its meaning. The Portuguese prices come from the Preços de Combustíveis service of the Direção-Geral de Energia e Geologia (DGEG), at precoscombustiveis.dgeg.gov.pt, whose published policy lets the data be used freely, asks you to identify DGEG as the source, to give the date and time of the last update of the prices, and to reproduce the information faithfully.

The actor delivers the values as the services publish them: it converts decimal commas into numbers, writes the times in one format, adds a normalised fuel code and a unit next to the source's own label (rawFuelLabel) and leaves the prices and the update times unchanged. Every row carries source and priceUpdatedAt, so keep them next to the prices you publish and name the Ministerio de Industria y Turismo (Spain) or DGEG (Portugal) as the source. The Spanish file has a single update time for all its prices; the Portuguese service has one per price.

The actor reads only those two services. Rowcraft is independent and not affiliated with or endorsed by the Ministerio de Industria y Turismo, the DGEG or any other public body; the names belong to their owners.

Privacy: no personal data

Rowcraft actors are built not to collect personal data:

  • The services describe fuel stations, which are business locations: an address, prices and, for Spain, opening hours. They carry no e-mail addresses and no phone numbers, and the actor adds none.
  • The Portuguese service gives each station a name, which can be the name of a person who runs it. The actor does not read it.
  • A station's brand label is delivered only when the same label is used by at least five stations in the data read in the run. A label used by fewer stations may be the name of an individual operator, so it becomes null. The check counts the stations read in the run, so a run over one small province can show null for a brand that a nationwide run would show.
  • The only coordinates delivered are those of the stations.

You are responsible for using the data in line with the law that applies to you.

Other Rowcraft actors

Related Rowcraft actors. All of them read official or public sources, deliver flat rows without private contact details and support only-new runs and notifications; the full list is on the Rowcraft profile:

FAQ

How fresh are the prices? Spain refreshes its file about every half hour and the actor reads it at the start of the run, so a run shows what the service held a few minutes earlier. Portugal marks every price with the time the operator reported it, which can be days ago.

Why is a fuel null? The station does not sell that fuel, or has no price for it at the moment. fuelsAvailable lists the fuels that do have a price, and prices holds all of them with the source's own label.

Why is the brand null? The brand is shown only when at least five stations in the data read in the run use the same label. A rarer label can be the name of the person who runs the station, so the actor does not deliver it. Reading more provinces or districts in one run raises the counts.

Why do two stations in the same place have different times? In Spain the whole file carries one time, so all prices of a run share it. In Portugal every price has its own time, and prices of one station can differ by days.

What does the time in priceUpdatedAt mean? It is local time as the service publishes it, without a time zone: Spanish time for Spain and Portuguese time for Portugal. The timeZone column says which. The actor does not shift it.

How do I find the cheapest stations near me? Set center to your coordinates, radiusKm to the distance you accept and fuels to your fuel, then sort the dataset by the price column. The nearest stations are delivered first and distanceKm shows how far each one is. Add a province or district to make the run faster.

What is the difference between petrol95 and the E10 price? petrol95 is the standard 95 petrol, which in Spain is E5 and in Portugal is Gasolina simples 95. Spanish stations that sell E10 or E25 list those prices in prices under petrol_95_e10 and petrol_95_e25.

Why is Portugal's island territory missing? The Portuguese service lists stations of the mainland only; the Azores and Madeira do not appear in it, so the actor has nothing to deliver for them.

Can I get other countries? Not from this actor. France is covered by its own Rowcraft actor. The actor reads only sources that publish open, official prices at station level and that allow automated access.

Is it legal? Yes, for the data as published. Both services publish the prices for reuse and ask for the source and the time of the update, which each row carries. The actor reads them politely: robots.txt first, at most one request per second, no proxy. How you use the data is your responsibility under the law that applies to you.

Can I pay only for new fuel stations? Yes. Turn on Only new rows since the last run: the actor remembers what it delivered to you and later runs with the same state name deliver (and charge) only the new rows.

How do I get the results into Slack, Google Sheets, Make, n8n or Zapier? Use the Integrations tab of the Actor for the data, and the notifyUrl field for a message when a run ends (Slack and Discord webhooks work directly; catch hooks of Make, n8n and Zapier too).

Can I call it from code or from an AI agent? Yes: through the Apify API, the JavaScript and Python clients, and the Apify MCP server. The API tab shows a working example with the input of this Actor.

Does it collect personal data? No. Contact persons, e-mails and phone numbers are removed and fields about people are never requested. See the Privacy section.

The run finished with 0 rows. Did I pay? No: with no rows delivered nothing is charged apart from the start event. Check the run summary (RUN_SUMMARY) for warnings, widen the filters, or run with Only new rows off if everything matching was already delivered to you.

Support and reviews

Problems, missing fields, questions: open an issue on the Issues tab of this Actor. We answer within one working day and fix confirmed bugs in the next release; the changelog lists every change.

If this Actor saved you time, a short review on its page helps other users find it and helps us keep improving it.