BUFF sale history is now available - POST /v1/archive/buff returns sale prices and daily total supply since September 2024.

How to Get Current Steam Community Market Prices

Updated

Endpoints used: GET /v1/prices/latest & GET /v1/market/steam/latest

Related pages: Steam price API

The steam source in cs2.sh's GET /v1/prices/latest carries ask, bid, ask_volume, and bid_volume for every tracked CS2 item. GET /v1/market/steam/latest goes further and returns the full bid and ask ladder for each one.

Valve publishes no supported price API for the Community Market. The endpoints people reach for are page-backing calls that were never meant for programmatic use, and they are throttled hard enough that reading a few thousand items becomes an infrastructure project. cs2.sh collects the Steam book continuously and serves it as a normalized response.

What cs2.sh provides for Steam#

Property Value
Current prices steam source in GET / POST /v1/prices/latest
Fields ask, bid, ask_volume, bid_volume
Full orderbooks GET /v1/market/steam/latest
Orderbook refresh About every 5 minutes
Variants Not supported on any Steam endpoint
Currency Always USD
Access Both available on all plans

ask is the lowest active sell listing and bid is the highest generic buy order. Steam is one of only three sources that publish both order counts, so ask_volume and bid_volume both arrive populated.

Steam supports no variants anywhere in the API. The Community Market does not distinguish a Doppler phase from its base item, so there is no phase-level Steam price to return.

Read the top of the book#

bash
curl -X POST https://api.cs2.sh/v1/prices/latest \
  -H "Authorization: Bearer <<YOUR_API_KEY>>" \
  -H "Accept-Encoding: gzip" --compressed \
  -H "Content-Type: application/json" \
  -d '{"items": ["USP-S | Printstream (Factory New)"]}'

The steam object arrives with its own timestamps:

json
"steam": {
  "updated_at": "2026-07-26T18:52:21.42Z",
  "collected_at": "2026-07-26T18:52:56.46Z",
  "ask": 169.14,
  "ask_volume": 70,
  "bid": 155.05,
  "bid_volume": 2951
}

updated_at is when Steam last changed the price; collected_at is when cs2.sh read it. Both are needed, because a value can be freshly collected and still stale at source.

Read the full orderbook#

GET /v1/market/steam/latest returns every tracked regular item's complete bid and ask ladder in one response.

json
"USP-S | Printstream (Factory New)": {
  "updated_at": "2026-07-26T18:52:21.42Z",
  "collected_at": "2026-07-26T18:52:56.46Z",
  "top": { "ask": 169.14, "ask_volume": 70, "bid": 155.05, "bid_volume": 2951 },
  "depth": {
    "ask_levels": 2,
    "bid_levels": 2,
    "asks": { "prices": [169.14, 169.4], "volumes": [1, 1] },
    "bids": { "prices": [155.05, 154.88], "volumes": [1, 1] }
  }
}
Field Type Description
top.ask / top.bid number Best price on each side.
top.ask_volume / top.bid_volume integer Quantity at the top of each side.
depth.ask_levels / depth.bid_levels integer Number of price levels on that side.
depth.asks.prices[] number[] Ask prices, sorted ascending.
depth.bids.prices[] number[] Bid prices, sorted descending.
depth.<side>.volumes[] integer[] Quantity at the price sharing the same array index.

The ladders are columnar rather than an array of objects: prices and volumes are parallel arrays, so level n is prices[n] at volumes[n]. Read them together or the depth is meaningless.

This response is about 100 MB uncompressed, so Accept-Encoding: gzip is required rather than optional. It returns every tracked item at once; there is no per-item form.

Reading the data correctly#

Steam prices settle to Steam Wallet funds, not cash. A Steam number placed beside BUFF, CSFloat, or Skinport is not directly comparable, and any conversion belongs in your own model with the raw value preserved next to it.

ask_volume and bid_volume count active orders. They are not sales and not a rate. A falling ask_volume can mean listings sold, or were cancelled, or were repriced out of the level you are watching. When the question is what actually sold, use POST /v1/archive/steam, which returns Steam's own median sale price and purchase count daily from April 26, 2013.

Depth is a snapshot of resting orders at one collection time, not a promise of executable quantity. Between two five-minute collections the book can turn over completely.

When the orderbook is unavailable#

GET /v1/market/steam/latest returns 503 service_unavailable when the latest snapshot is missing, stale, or empty. Treat it as a transient condition and keep serving the previous snapshot rather than writing an empty book, which would look like a market with no orders.

Worked example: measuring the real cost of buying now#

Take depth.asks and walk the ladder, accumulating volumes[n] at prices[n] until you reach the quantity you want. The weighted average of the prices you consumed is what buying that quantity would actually cost, as opposed to top.ask, which only prices the first unit.

Do the same down depth.bids for a sale. Record collected_at with the result: on a five-minute refresh, a book from four minutes ago may no longer support the walk you just computed.

Full orderbook reference: GET /v1/market/steam/latest. Current price fields: GET /v1/prices/latest. Sale history: POST /v1/archive/steam.