// HACKER NEWS — CYBERSECURITY
Tracking Costco gas prices
TL;DR: I tracked gas prices at 600 Costco warehouses during the Strait of
Hormuz fuel crisis and mapped out how they changed.
Back in April, I lived almost exactly between two Costco warehouses, and for years I ran the same mental math every time I needed gas: which of the two was actually cheaper that week.
Unfortunately, Costco doesn't publish gas prices anywhere centrally. The official site buries them on individual warehouse pages, and my two nearest warehouses were rarely priced the same. Costco gas is famously a loss leader, typically running 15 to 20 cents below surrounding stations. That gap is usually enough to make the detour worth it, though not enough to make the choice between my two Costcos obvious.
As a commuter in Tampa, a sprawling city with almost no public transportation, I got a lot more conscious of where I filled up as gas prices climbed that spring. I started getting curious about Costco's prices specifically: were they climbing at the same rate as other gas stations, and could Costco realistically keep running gas as a loss leader if prices kept rising?
There was no good way to see that trend historically. So naturally, I built one.
Unfortunately, this was probably the easiest part of the project. I wish I had a cool reversing method to talk about like the Waffle House story, but Costco gave me very little resistance in collecting this data.
My first find when I started digging through Costco's site was AjaxGetGasPricesService, an endpoint that takes an input of warehouse IDs formatted as ID1_ID2_ID3_ID4. Underscores as an array delimiter is an interesting choice! It was useful, but not quite what I wanted; I needed the location data for each warehouse so I could map them out and figure out which was actually shorter to drive to.
Digging a little further surfaced exactly what I needed: AjaxWarehouseBrowseLookupView. Much like the name suggests, the function looks up warehouses using a latitude and longitude parameter input. Even better, the parameter populateWarehouseDetails stuffs the response with just about every piece of information you could want about a Costco: address, hours, services, food court availability (!!), and most importantly, gas prices.
The only catch with populateWarehouseDetails is the response body is massive. As much as I'd like to get every single Costco in the United States all at once, their API caps results at 50 warehouses per call and returns them sorted by distance from the lat/long you provide. To get national coverage, I needed to sweep the map.
The approach was simple enough: lay out a grid of coordinates across the country, sweep each point, and deduplicate the warehouse IDs that come back. With ~600 Costco locations and 50 per response, a 3-degree grid across the continental US plus a few hand-picked points for Alaska and Hawaii gives more than enough overlap to catch every warehouse.