# How to Scrape Official Steam Community Market Orderbooks

> Valve's official Steam Community Market exposes a name-based `market/orderbook` response with the lowest sell listing, highest buy order, active-order counts, and compact depth arrays. The older `itemordershistogram` route requires a numeric `item_nameid`. Both routes are undocumented and neither is an official Market API.

## Use the name-based orderbook route

Request `https://steamcommunity.com/market/orderbook` with `q=Load`, `cc=US`, `l=english`, and `currency=1`. The `qp` parameter is a URL-encoded JSON array containing the app ID and exact name: `[730,"<market_hash_name>"]`.

Use the exact listing page as the referer and send `x-valve-request-type: queryAction`. The response should contain `success=true` and a `data` object.

| Steam field | Meaning |
| --- | --- |
| `amtMinSellOrder` | Lowest sell listing in integer currency cents |
| `amtMaxBuyOrder` | Highest buy order in integer currency cents |
| `cSellOrders` | Total active sell-listing count |
| `cBuyOrders` | Total active buy-order count |
| `rgCompactSellOrders` | Flat sell-side price and quantity pairs |
| `rgCompactBuyOrders` | Flat buy-side price and quantity pairs |

Each compact array alternates price cents and quantity. Split `[price, quantity, price, quantity]` into aligned levels, reject odd-length arrays, and preserve Steam's order. The declared total order count can differ from the sum of compact quantities; record that difference without inventing missing levels.

## Decode a representative response

A shortened response is `{"success":true,"data":{"amtMaxBuyOrder":4124,"amtMinSellOrder":4132,"eCurrency":1,"cBuyOrders":53678,"cSellOrders":1120,"rgCompactBuyOrders":[4124,27,4106,26],"rgCompactSellOrders":[4132,2,4146,1]}}`.

The first sell levels decode to 2 orders at $41.32 and 1 at $41.46. The first buy levels decode to 27 orders at $41.24 and 26 at $41.06. `cSellOrders=1120` describes the full active sell-listing count, not the sum of the compact levels returned in this shortened example.

## Understand itemordershistogram

The older request is `market/itemordershistogram` with `country`, `language`, `currency`, `item_nameid`, and `two_factor`. Find `item_nameid` in the exact listing page's `Market_LoadOrderSpread(<id>)` call. Do not reuse an ID from a different wear or item.

Its response includes `highest_buy_order`, `lowest_sell_order`, buy and sell graphs, small HTML tables, and summary fields. Prices are commonly integer minor units even when graph labels are formatted strings. The graph quantities are cumulative, so calculate per-level quantity only if the application needs it.

The name-based route removes the numeric-ID discovery step and is what cs2.sh currently uses for direct Steam depth collection. The legacy route remains useful when maintaining an older integration.

## Validate before storing a snapshot

Require `success=true`, confirm the response currency, validate numeric prices, and verify every compact pair. `success=false` can mean Steam does not resolve that market name; it is not proof of a network outage. HTML, 403, 429, and 5xx responses need separate retry handling.

Attach an observation timestamp and exact market hash name to every accepted snapshot. Active orders are not completed sales, and a full ladder can change before an application acts on it.

## Skip the collector for stored depth

[GET /v1/market/steam/latest](/docs/market-steam-latest) returns full-depth Steam orderbooks across every tracked regular item. [Historical Steam depth](/docs/market-steam-history) stores hourly and daily snapshots from June 9, 2026. Those are the parts a one-time free request cannot provide later.

Self-scraping remains useful when raw responses or exact request timing are part of the product. Otherwise, [cs2.sh](https://cs2.sh/) avoids numeric-ID discovery, currency checks, malformed ladders, per-item scheduling, blocks, retries, and years of snapshot storage.

## The same data from cs2.sh

`GET /v1/market/steam/latest` returns the same ladder shape for every tracked regular item, on all plans, without numeric-ID discovery or per-item scheduling.

```json
"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] }
}
```

For depth over time, `POST /v1/market/steam/history` returns the last complete orderbook collected inside each bucket, from June 9, 2026:

| Property | Value |
| --- | --- |
| Intervals | `1h` (max range 90 days), `1d` (unlimited) |
| Shape | Same `top` and `depth` objects as the latest endpoint |
| Items per request | 100 |
| Access | Requires a Scale or Enterprise API key |

This is sampled history, not OHLC. Each bucket is one real observed book rather than an aggregation, so a `1d` bucket is the last snapshot of that day and not a summary of it. `503 service_unavailable` on the latest endpoint means the current snapshot is missing, stale, or empty.

Disclosure: this free DIY guide is published by cs2.sh. These interfaces are undocumented and subject to the [Steam Subscriber Agreement](https://store.steampowered.com/subscriber_agreement/). Review authorization before running an automated collector. Live fields and both routes were checked on August 5, 2026.
