In the last post about the UK's Fuel Finder feed, we wrote that price_last_updated means "last changed", not "last confirmed", and that we therefore let only prices from the last seven days into our averages.
The first half was right. The second half was a mistake, and it took six weeks of history to see it.
The number that kept shrinking
Every average on fuelpricetoday.co.uk carries the number of stations behind it. For unleaded, outside motorway services:
| Day | Stations in the feed | Changed in the last 7 days | Changed in the last 30 days |
|---|---|---|---|
| 9 September | 7,681 | 7,293 | 7,529 |
| 20 October | 7,760 | 3,515 | 7,242 |
Nothing was wrong with the feed. Prices had simply settled. In early September prices were climbing fast and nearly every station repriced within the week. By late October more than half of them were holding a price for longer than seven days.
Why that is a bias, not just a smaller sample
The UK regulations require a forecourt to report a price change within 30 minutes. A price that has not changed for ten days is therefore not stale: it is the price on the pump. A seven-day window does not select fresh data, it selects stations that recently changed their price.
And those are not a random sample. On 19 October, the share of each brand's unleaded prices that had changed in the past week:
| Brand | Stations | Changed in 7 days |
|---|---|---|
| Sainsbury's | 316 | 314 |
| Asda | 404 | 298 |
| Morrisons | 341 | 244 |
| Tesco | 516 | 313 |
| BP | 997 | 490 |
| Esso | 1,440 | 609 |
| Shell | 892 | 321 |
Supermarkets reprice constantly, oil company forecourts much less. A seven-day window kept almost every Sainsbury's and about a third of Shells, so the average drifted towards supermarket prices. On the same day, the unleaded prices that had changed within the week averaged 172.7p; those unchanged for 8 to 30 days averaged 174.8p.
It also exaggerated the trend. The stations that just changed are the ones that just followed the market, so in a falling October the seven-day average ran ahead of the market:
| Day | 7-day window | 30-day window |
|---|---|---|
| 22 September | 172.9p | 172.7p |
| 16 October | 172.8p | 173.9p |
| 20 October | 172.6p | 173.7p |
A 1.1p gap is small in absolute terms, but it is the size of a weekly move, which is exactly what a price tracker exists to report.
The fix
One rule across the site: a price counts unless it has been unchanged for more than 30 days. That threshold is not new to us; it is where we already flagged a price as suspect, because a month without a single change suggests a station that has stopped reporting rather than one holding steady. Averages, rankings and the heat map now use it too.
// A price counts on `day` unless it has been unchanged for more than
// `window` days. price_last_updated dates the last change, not a confirmation.
function counts(row: { day: string; priceLastUpdated: string | null }, window = 30) {
if (!row.priceLastUpdated) return false;
const age = (Date.parse(row.day) - Date.parse(row.priceLastUpdated.slice(0, 10))) / 86_400_000;
return age <= window;
}
The station count behind the national average was 7,137 on 22 October instead of sliding towards 3,000, and its composition no longer depends on how calm the market is that week.
Two things we kept:
- Published figures were not rewritten. Our weekly press bulletins up to mid-October used the seven-day rule. Each bulletin now records the window it was computed with and says so on the page.
- The age stays visible. Every price on the site still shows when it last changed. A price can count in an average and still be shown as "unchanged since 2 October".
The lesson
The mistake was treating a filter as neutral. Any rule that admits rows based on behaviour (here, "changed recently") selects for whoever behaves that way. The check that caught it was cheap: publish the denominator next to every average, and watch it.
The data
The full history, every price at every station each day since 7 September 2026, is free to download under the Open Government Licence:
- fuelpricetoday.co.uk/data: daily UK and town averages, the station list, and one history file per month, refreshed every three hours.
- GitHub, closed months mirrored weekly with a Data Package descriptor.
The official feed shows only today's price, so this history is the part nobody else gives away.
Top comments (0)