Skip to main content
Thirdwatchthirdwatch
Business & local data

Track Gas Prices by State for Fleet Cost Planning

Export AAA's state-level gas averages — regular, mid, premium, diesel, E85 — as JSON to model fleet fuel costs where your vehicles actually drive.

Sep 21, 2026 · 2 min read · 486 words
See the scraper →

TL;DR — The Fuel Prices Scraper exports AAA's daily state and national gas averages — five grades plus diesel — as JSON. Filter to your operating states and fleet fuel budgeting becomes a dated data feed instead of a guess.

Why fleet fuel budgets need state-level rates

Fuel is one of the largest variable costs in fleet operations — ATRI's annual operational cost research consistently puts it near a quarter of marginal cost for trucking. And the national average is nearly useless: California diesel and Texas diesel are different worlds.

The job-to-be-done is a dated table of state averages, per grade, pulled daily — the input to route costing, surcharge tables, and budget variance.

How does this compare to the alternatives?

Checking AAA's site Fuel-card reports Thirdwatch actor
Cost Free, manual Bundled but narrow Pay per result
Reliability One screen at a time Only your fueling All 50 states
Setup time Zero Fleet program Minutes
Maintenance Daily habit Monthly lag Scheduled runs

Fuel-card data tells you what you paid. State averages tell you what the market did — the benchmark your actuals get judged against.

How to track state fuel costs in 4 steps

How do I pull my operating states?

import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("thirdwatch/fuel-prices-scraper").call(
    run_input={"states": ["california", "texas", "illinois", "georgia"]}
)
rows = list(client.dataset(run["defaultDatasetId"]).iterate_items())

scope marks each row national or state:ca-style — the national row always comes along as the benchmark.

How do I build the cost table?

import pandas as pd
df = pd.DataFrame(rows)
diesel = df[df["diesel"].notna()][["region", "diesel", "week_ago", "month_ago"]]
diesel["wow_change"] = diesel.diesel - diesel.week_ago
print(diesel.sort_values("diesel", ascending=False))

week_ago/month_ago/year_ago columns arrive in the same record — trend without storing history.

How do I persist for trend analysis?

Append the full frame daily; date keys the series:

df.to_json("fuel_daily.jsonl", orient="records", lines=True, mode="a")

How do I wire it into routing?

Join diesel or regular per state onto route legs — cost per leg = miles × consumption × state average. Weekly refreshed rates beat last quarter's assumption.

Sample output

{"region": "California", "scope": "state:ca", "date": "2026-09-21",
 "regular": 4.61, "mid_grade": 4.82, "premium": 4.99,
 "diesel": 5.12, "e85": 3.45,
 "yesterday": 4.60, "week_ago": 4.55, "month_ago": 4.71, "year_ago": 4.42}

Common pitfalls

These are statewide averages — a metro corridor can run meaningfully higher than its state's mean. AAA publishes once daily; intraday spikes aren't visible until the next fix. E85 coverage is thinner — expect nulls in some states. The actor structures AAA's table; pump-level pricing is a different data product.

Related use cases

Frequently asked questions

What does each record contain?

Region name, scope (national or a state), the date, and per-grade averages — regular, mid-grade, premium, diesel, E85 — plus yesterday/week/month/year-ago columns for context.

Where does the data come from?

AAA's published state and national gas price averages — the standard public reference for US fuel costs. The actor structures the tables into JSON.

Can I pull only the states I operate in?

Yes. The states array accepts lowercase state names; empty means national coverage. Each run also returns the national benchmark row.

How fresh is the data?

AAA updates averages daily. Schedule a daily run and the week_ago/month_ago columns give you built-in trend context per row.

Related

Try it yourself

100 free credits, no credit card.

About 30 real searches. Add the MCP to Claude or Cursor in two minutes.