Bulk Latest Prices
Latest prices for every catalog item of one game in a single call: each item's per-market asks and bids plus its best ask and best bid, in the same shape and with the same values as /v2/pricing/:marketHashName in its default all-markets view. Rebuilt every 10 minutes and served gzip-compressed. Enterprise plans only. The bulk alternative to /v1/items/all. Prices are integer USD cents.
One request returns every item of the game that has a servable quote: items[], ordered by canonicalItemId, with itemCount closing the envelope. Each item carries the same markets[] (asks), buyOrders[] (bids), bestAsk and bestBid as /v2/pricing/:marketHashName in its default all-markets view, so a snapshot row matches what the per-item route returned when the snapshot was built. As there, bestBid only considers cash-executable venues. Both bestAsk and bestBid are nullable and a missing bestBid is common, so null-check both. Items the per-item route would answer with 404 (no servable quote) are left out rather than listed empty.
The snapshot is rebuilt every 10 minutes. generatedAt is when the build started, and every quote in it was read at or after that time. Each quote's isStale is evaluated when the snapshot is built.
Efficient polling: send Accept-Encoding: gzip. The body is served compressed and is roughly 10 times smaller that way (about 7 MB instead of 75 MB for CS2 today), and gzip downloads are never limited; uncompressed downloads are limited to a few at a time and can answer 503. Keep the ETag from each 200 and send it back as If-None-Match: you get a 304 with no body until the next snapshot, which is rebuilt every 10 minutes. Responses carry Cache-Control: private, max-age=60, Vary: Accept-Encoding, and Last-Modified (the snapshot's generatedAt). Poll every 1 to 10 minutes with gzip and If-None-Match; a new snapshot lands every 10 minutes. Quota: every request that passes the plan check counts toward your per-minute limit (and the monthly limit where your plan has one), 304s and 503s included; a 401 or a plan 403 does not.
Games: pass game=cs2. The route also accepts game=rust, which answers 503 until Rust is enabled on it. See Games: CS2 & Rust.
Parameters
cs2 or rust; missing or any other value returns 400. rust answers 503 until Rust is enabled on this route.gzip. The body is served compressed, roughly 10 times smaller (about 7 MB instead of 75 MB for CS2 today), and compressed downloads are never limited. Uncompressed downloads are limited to a few at a time and can answer 503.ETag from your last download; returns 304 with no body until the next snapshot (rebuilt every 10 minutes).Response fields
Last-Modified.cs2 or rust, as requested.USD: the currency of every price field.canonicalItemId.items.Nested and shared shapes link to the API Objects reference.
Errors
game missing or not cs2 / rust.Authorization header, unsupported scheme, or a key that is unknown, inactive, expired, or revoked.Retry-After: 60: retry then, ideally with Accept-Encoding: gzip.export SKINPRICER_API_KEY="sp_live_•••"
# --compressed asks for gzip and unpacks it. etag.txt keeps the last ETag:
# until the next snapshot (every 10 minutes) the API answers 304 and
# prices-cs2.json stays as it is. Needs curl 7.68 or newer.
curl -G "https://pricing.skinpricer.com/v2/prices/latest" \
--data-urlencode "game=cs2" \
-H "Authorization: ApiKey $SKINPRICER_API_KEY" \
--compressed \
--etag-compare etag.txt \
--etag-save etag.txt \
-o prices-cs2.json// No SDK helper for this endpoint yet, so call it directly.
// Poll every 1 to 10 minutes; a new snapshot lands every 10.
let etag: string | null = null;
async function pollLatestPrices() {
const url = new URL("https://pricing.skinpricer.com/v2/prices/latest");
url.searchParams.set("game", "cs2");
const res = await fetch(url, {
headers: {
Authorization: `ApiKey ${process.env.SKINPRICER_API_KEY}`,
"Accept-Encoding": "gzip", // fetch unpacks the body for you
...(etag ? { "If-None-Match": etag } : {}),
},
});
if (res.status === 304) return null; // no new snapshot since the last poll
if (!res.ok) throw new Error(`HTTP ${res.status}`); // 503: retry after Retry-After
etag = res.headers.get("etag");
return res.json();
}
const snapshot = await pollLatestPrices();
if (snapshot) console.log(snapshot.itemCount, "items, built at", snapshot.generatedAt);import os
import requests
etag = None # keep the last ETag between polls (every 1 to 10 minutes)
def poll_latest_prices():
global etag
headers = {
"Authorization": f"ApiKey {os.environ['SKINPRICER_API_KEY']}",
"Accept-Encoding": "gzip", # requests unpacks the body for you
}
if etag:
headers["If-None-Match"] = etag
res = requests.get(
"https://pricing.skinpricer.com/v2/prices/latest",
params={"game": "cs2"},
headers=headers,
timeout=60,
)
if res.status_code == 304:
return None # no new snapshot since the last poll
res.raise_for_status() # 503: retry after the Retry-After header
etag = res.headers.get("ETag")
return res.json()
snapshot = poll_latest_prices()
if snapshot:
print(snapshot["itemCount"], "items, built at", snapshot["generatedAt"])Authenticated endpoint: call it with your API key from your own client (see the code sample).
{
"generatedAt": "2026-09-28T12:00:00.000Z",
"game": "cs2",
"currency": "USD",
"items": [
{
"name": "AK-47 | Redline (Field-Tested)",
"canonicalItemId": "cmlofczf90qj401vsd80dskd1",
"bestAsk": {
"market": "buff163",
"price": 1450,
"updatedAt": "2026-09-28T11:58:12.000Z",
"isStale": false
},
"bestBid": {
"market": "buff163",
"price": 1400,
"updatedAt": "2026-09-28T11:57:40.000Z",
"isStale": false
},
"markets": [
{
"market": "buff163",
"price": 1450,
"fetchedAt": "2026-09-28T11:58:12.000Z",
"isStale": false,
"quoteSize": 20,
"originalPriceCents": 10150,
"originalCurrency": "CNY"
},
{
"market": "csfloat",
"price": 1512,
"fetchedAt": "2026-09-28T11:55:03.000Z",
"isStale": false,
"quoteSize": 7,
"originalPriceCents": 1512,
"originalCurrency": "USD"
}
],
"buyOrders": [
{
"market": "buff163",
"price": 1400,
"fetchedAt": "2026-09-28T11:57:40.000Z",
"isStale": false,
"quoteSize": 5,
"totalQuantity": 44
},
{
"market": "youpin",
"price": 1385,
"fetchedAt": "2026-09-28T11:56:20.000Z",
"isStale": false,
"quoteSize": 3,
"originalPriceCents": 9695,
"originalCurrency": "CNY",
"totalQuantity": 31,
"totalOrdersCount": 12,
"orderBookComplete": true
}
]
}
],
"itemCount": 1
}