How to get Steam Community Market prices without scraping
Get Steam Community Market prices for CS2 without scraping or IP bans: current asks, per-market history, and a comparison with cash marketplaces.
On this page
The Steam Community Market is the reference price many CS2 players know, and it is the first thing most developers try to automate. The usual route is to call the same endpoints the Steam website uses in the browser. Those endpoints are part of Valve's website, not a published API: there is no documented contract, no quota you can plan against, and no notice when a response changes. Our own ingestion had to be updated in August 2026 when Steam changed the format of its order-book responses, which is exactly the kind of break a hand-rolled scraper finds out about in production.
SkinPricer already collects Steam Community Market data alongside every other venue and serves it under one key, in the same shape as everything else. This guide shows how to read Steam's current ask and buy orders, pull Steam-only price and sale history, and put Steam next to cash markets without mixing up the currencies.
What you get for Steam from the API#
| You want | Call | Plan |
|---|---|---|
| Steam's current lowest ask and highest buy order | GET /v1/pricing/:marketHashName?markets=steamcommunity | Developer and up |
| Steam ask, buy-order, or sale history over time | GET /v1/pricing/:marketHashName/history/markets?markets=steamcommunity | Pro and up |
| Steam alongside cash venues, fee-adjusted | GET /v1/nbbo?markets=steamcommunity,... | Developer and up |
Steam's market id is steamcommunity, the same join key the market health endpoint uses. Items are identified by their exact Steam market_hash_name, so the names you already store keep working. Every price comes back as integer USD cents, regardless of which wallet currency the listing was shown in.
Step 1: read Steam's current ask and buy order#
Restrict the pricing snapshot to Steam. The markets[] entry is Steam's representative ask; the buyOrders[] entry is its highest standing buy order with the quantity behind it. Each row carries fetchedAt, ingestedAt, and isStale, so you always know how old the number is.
export SKINPRICER_API_KEY="sp_live_•••" # from your account's API keys page
curl -s "https://pricing.skinpricer.com/v1/pricing/AK-47%20%7C%20Redline%20(Field-Tested)?markets=steamcommunity" \
-H "Authorization: ApiKey $SKINPRICER_API_KEY"// npm i @skinpricer/sdk
import { SkinpricerClient, formatUsd } from "@skinpricer/sdk";
const client = new SkinpricerClient({
apiKey: process.env.SKINPRICER_API_KEY!,
authScheme: "ApiKey",
});
const name = "AK-47 | Redline (Field-Tested)";
const steam = await client.pricing.get(name, { markets: ["steamcommunity"] });
const ask = steam.markets.find((q) => q.market === "steamcommunity");
const bid = steam.buyOrders?.find((q) => q.market === "steamcommunity");
console.log("Steam lowest ask:", ask ? formatUsd(ask.price) : "no listings");
console.log("Steam highest buy order:", bid ? formatUsd(bid.price) : "no buy orders");import os
from urllib.parse import quote
import requests
name = "AK-47 | Redline (Field-Tested)"
res = requests.get(
f"https://pricing.skinpricer.com/v1/pricing/{quote(name, safe='')}",
params={"markets": "steamcommunity"},
headers={"Authorization": f"ApiKey {os.environ['SKINPRICER_API_KEY']}"},
timeout=10,
)
res.raise_for_status()
data = res.json()
ask = next((q for q in data["markets"] if q["market"] == "steamcommunity"), None)
bid = next((q for q in data.get("buyOrders") or [] if q["market"] == "steamcommunity"), None)
print("ask:", ask and ask["price"] / 100, "bid:", bid and bid["price"] / 100){
"canonicalItemId": "cmlofca920lka01yozajhixt3",
"name": "Glock-18 | Water Elemental (Factory New)",
"aggregate": {
"minPrice": 6500,
"maxPrice": 8012,
"avgPrice": 7102,
"medianPrice": 7119,
"stdDev": 439.12,
"marketCount": 10,
"freshMarketCount": 9,
"listingCount": 710,
"updatedAt": "2026-06-23T21:59:48.717Z"
},
"markets": [
{
"market": "csfloat",
"price": 6500,
"currency": "USD",
"fetchedAt": "2026-06-23T21:52:27.427Z",
"ingestedAt": "2026-06-23T21:55:56.923Z",
"quoteSize": 132,
"ingestLatencyMs": 209496,
"isStale": false,
"sourceUpdatedAt": "2026-06-23T21:01:13.000Z",
"sourceTimeKind": "last_modified",
"sourceAgeSeconds": 3074
}
],
"buyOrders": [
{
"market": "buff163",
"price": 6440,
"currency": "USD",
"fetchedAt": "2026-06-23T21:59:48.717Z",
"ingestedAt": "2026-06-23T21:59:48.000Z",
"quoteSize": 47,
"totalQuantity": 47,
"ingestLatencyMs": 0,
"isStale": false
}
],
"bestAsk": {
"market": "csfloat",
"price": 6500,
"updatedAt": "2026-06-23T21:52:27.427Z",
"isStale": false
},
"bestBid": {
"market": "buff163",
"price": 6440,
"updatedAt": "2026-06-23T21:59:48.717Z",
"isStale": false
},
"spreadBps": 93,
"marketCount": 10,
"freshMarketCount": 9,
"calculatedAt": "2026-06-23T22:07:13.752Z"
}Fetch the full cross-market snapshot for AK-47 | Redline (Field-Tested) live, Steam included.
Step 2: pull Steam-only history#
Per-market history returns one series per venue, so filtering it to steamcommunity gives you a Steam-only chart. listingType picks what you are charting: SELL_OFFER for asks (the default), BUY_ORDER for bids, or SALE_HISTORY for completed-sale statistics, which Steam publishes and SkinPricer ingests as rolling windows. With SALE_HISTORY, salesWindow (24h, 7d, 30d, or 90d, default 30d) selects the window and each bucket's volume is the number of sales in that window.
const weekAgo = new Date(Date.now() - 7 * 24 * 3600 * 1000);
const sales = await client.history.byMarket(name, {
markets: ["steamcommunity"],
listingType: "SALE_HISTORY",
salesWindow: "7d",
from: weekAgo,
interval: "DAY_1",
});
for (const series of sales.series) {
for (const bucket of series.history) {
console.log(bucket.timestamp, "median sale:", bucket.medianPrice, "sales in 7d:", bucket.volume);
}
}curl -s "https://pricing.skinpricer.com/v1/pricing/AK-47%20%7C%20Redline%20(Field-Tested)/history/markets?markets=steamcommunity&listingType=SALE_HISTORY&salesWindow=7d&interval=DAY_1" \
-H "Authorization: ApiKey $SKINPRICER_API_KEY"- Bucket widths snap to stored rollups:
MINUTE_5andMINUTE_15serve 10-minute buckets,HOUR_1andHOUR_6serve hourly buckets,DAY_1serves daily buckets. - Without
interval, the width follows your range: up to 7 days gets 10-minute buckets, up to 180 days hourly, anything longer daily. maxPriceon ask history includes extreme listings with no outlier cap. It is not a fair-value estimate.
Step 3: put Steam next to cash markets#
Steam prices settle in wallet credit, so they are usually higher than cash-market prices for the same skin. That is why the default cross-market best bid on the NBBO excludes Steam: a wallet-credit bid is not money you can withdraw. To see Steam compete, pass an explicit markets list that includes steamcommunity; the executionAdjusted block then shows what the Steam bid nets after an estimated seller fee.
const book = await client.nbbo.get({
marketHashName: name,
markets: ["steamcommunity", "csfloat", "buff163", "skinport"],
});
const adjustedBid = book.executionAdjusted?.bestBid;
if (adjustedBid) {
console.log("Best bid nets", formatUsd(adjustedBid.price), "on", adjustedBid.market,
adjustedBid.market === "steamcommunity" ? "(wallet credit)" : "(cash)");
}Scraping versus an API, in practice#
- Maintenance: a scraper breaks when the page or response changes. An API contract is versioned, and changes are announced in the changelog.
- Identity: SkinPricer joins Steam rows to the same canonical item as every other venue, so one name resolves across markets.
- Currency: Steam shows prices in the viewer's wallet currency. The API normalizes every quote to USD cents.
- Freshness: each quote carries fetch and ingest timestamps and a stale flag, instead of a number of unknown age.
- Budget: your plan's per-minute and monthly quotas are published up front and reported on every response in
X-RateLimit-*headers.
When to reach for a different endpoint#
For the full cross-market view rather than Steam alone, start with live CS2 prices. For longer charts and aggregate history across every venue, see CS2 price history. The field-level reference for everything above is on the pricing, per-market history, and NBBO pages.
Endpoints used in this guide
Plans start at $50/month on the Developer tier. Want to try first? Ask in our Discord for a free 2-day Developer key.
Related guides
- Prices & quotesIntermediate
Steam Market vs cash-market prices: how to compare them correctly
Steam Market prices are wallet credit, not cash. Learn how to compare Steam and cash-market CS2 prices after fees, using execution-adjusted quotes.
GET /v1/nbboGET /v1/pricing/:marketHashName5 min read - History & backtestingBeginner
How to get CS2 skin price history at any interval
Fetch CS2 skin price history in 10-minute, hourly, or daily buckets, across all markets or split per market, ready for charts, alerts, and analysis.
GET /v1/pricing/:marketHashName/historyGET /v1/pricing/:marketHashName/history/markets6 min read - Prices & quotesBeginner
How to get live CS2 skin prices from every marketplace
Pull live CS2 skin prices from every major marketplace in one call: per-market asks, bids, and aggregate stats in USD cents, with runnable curl and TypeScript.
GET /v1/pricing/:marketHashNameGET /v1/items6 min read