Skip to main content
Thirdwatchthirdwatch
Business & local data

Build a Fuel Cost Model With AAA Price Data

Feed daily AAA fuel averages into a cost model — state-level grade prices as JSON for shipping quotes, delivery fees, and route economics.

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

TL;DR — The Fuel Prices Scraper delivers AAA's daily per-state fuel averages as JSON — five grades with comparison columns. Join them to route mileage and your delivery quotes, fees, and margins run on today's prices, not last quarter's.

Why fuel cost models go stale

A shipping quote computed on $3.40 diesel and billed during a $4.10 week is a margin leak. Fuel averages move daily — AAA's gas price tracking exists precisely because the number isn't static — but most cost models treat fuel as a quarterly assumption.

The fix is a daily rate table your model can read: per state, per grade, dated.

How does this compare to the alternatives?

Static assumptions Fuel hedging desk Thirdwatch actor
Cost Free, inaccurate Treasury overhead Pay per result
Reliability Stale quarterly Sophisticated Daily fresh
Setup time Zero Months Minutes
Maintenance Quarterly revisits Team Scheduled runs

How to build the model in 4 steps

How do I get the price table?

import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("thirdwatch/fuel-prices-scraper").call(
    run_input={"states": ["texas", "oklahoma", "kansas", "colorado", "new-mexico"]}
)
prices = {r["region"]: r for r in
          client.dataset(run["defaultDatasetId"]).iterate_items()}

How do I compute per-leg cost?

def leg_cost(state_miles: dict, mpg: float = 6.5, grade: str = "diesel") -> float:
    return sum(
        miles / mpg * prices[s.title()][grade]
        for s, miles in state_miles.items()
    )

quote = leg_cost({"texas": 420, "oklahoma": 180, "kansas": 220})
print(f"${quote:.2f}")

How do I version the inputs?

Each record carries date — persist the run's rows so every quote is reproducible: "priced on 2026-09-21 averages."

How do I sanity-check moves?

The built-in week_ago/month_ago columns flag drift — a quote model should log when a grade moved more than a few percent between runs.

Sample output

{"region": "Texas", "scope": "state:tx", "date": "2026-09-21",
 "regular": 3.01, "mid_grade": 3.35, "premium": 3.68,
 "diesel": 3.55, "e85": 2.55,
 "yesterday": 3.00, "week_ago": 2.98, "month_ago": 3.11, "year_ago": 2.94}

Common pitfalls

State averages understate metro corridors — pad a few percent for urban-heavy routes. Diesel and gasoline move semi-independently; don't proxy one with the other. Daily fixes miss weekend spikes — Monday quotes inherit Friday's risk. The actor supplies honest benchmarks; margins and surcharges are your policy layer.

Related use cases

Frequently asked questions

Why use AAA averages in a cost model?

They're daily, authoritative, state-level, and free — the standard public benchmark for US fuel costs. The actor delivers them as JSON so the model reads data, not a webpage.

How do I model a multi-state route?

Split the route into per-state mileage, multiply each leg by that state's grade-specific average, and sum. The records' region field joins directly to your leg table.

Can the model auto-update?

Yes — schedule the actor daily, read the latest dataset rows, and every downstream cost uses that morning's fix. The date field versions each input.

What about fuel efficiency differences?

The actor supplies the price; consumption (MPG, load effects) lives in your model. Keep them separate — prices change daily, vehicle physics don't.

Related

Try it yourself

100 free credits, no credit card.

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