How to Get CS2 Sale Volume and Supply Data
Updated
Three cs2.sh endpoints report sale activity and they count different things. CSFloat reports actual daily sale counts from 2022, Steam reports its own purchase counts from 2013, and the aggregate archive reports an approximate estimate from 2023. None of them is total CS2 volume.
"How many of these sold?" has no single answer in CS2, because no marketplace publishes a global figure and each one counts only itself. The useful question is which covered market you mean.
Choose the volume definition first
| Need | Endpoint | Field | Coverage |
|---|---|---|---|
| Cash marketplace sales, with variants | POST /v1/archive/csfloat |
data[].volume |
From 2022 |
| Steam Community Market purchases | POST /v1/archive/steam |
data[].volume |
Daily from April 26, 2013 |
| Approximate cross-source activity | POST /v1/archive/history |
aggregate.hourly_volume |
From 2023 |
All three require a Scale or Enterprise API key and accept up to 100 items per request.
CSFloat and Steam volumes are marketplace-reported counts of real transactions. hourly_volume is explicitly an estimate: the hourly approximation in 1h responses, and the sum of those hourly estimates in each 1d bucket. Label it as approximate wherever it appears.
Youpin is the exception worth knowing. POST /v1/archive/youpin deliberately publishes no sale volume, because Youpin exposes one sale per sampling bucket. Counting the returned points measures how often a sample was published, not how many items traded. POST /v1/archive/buff behaves the same way: it returns sampled sale prices and the daily total_supply BUFF reports, and its count is the number of samples rather than a sale count.
Request activity and supply together
curl -X POST https://api.cs2.sh/v1/archive/history \
-H "Authorization: Bearer <<YOUR_API_KEY>>" \
-H "Accept-Encoding: gzip" --compressed \
-H "Content-Type: application/json" \
-d '{
"items": ["USP-S | Printstream (Factory New)"],
"start": "2023-01-01",
"interval": "1d"
}'"aggregate": {
"time": "2026-04-27T23:59:07Z",
"ask": 130.05,
"ask_volume": 1225,
"bid": 130.19,
"bid_volume": 133,
"hourly_volume": 27,
"total_supply": 31291,
"sample_count": 24
}| Field | Type | Description |
|---|---|---|
hourly_volume |
integer |
Approximate sales in the bucket. Hourly for 1h, summed across the day for 1d. |
total_supply |
integer |
Approximate cumulative copies of the item in circulation. aggregate only. |
ask_volume / bid_volume |
integer |
Last-observed active listing and buy-order counts. |
time |
string (date-time) |
When the last observation in the bucket happened. |
sample_count |
integer |
Number of readings behind the bucket. |
sources defaults to aggregate only, which is what you want here: hourly_volume and total_supply exist only on that source.
The four counts that are not sales
This is where most CS2 volume analysis goes wrong. Four different fields look like quantity and only one of them counts transactions.
| Field | What it counts |
|---|---|
ask_volume |
Active sell listings resting on the book right now |
bid_volume |
Active buy orders resting on the book right now |
depth levels in the Steam orderbook |
Quantity available at each price |
total_supply |
Approximate copies of the item in existence |
None of these is a sale. A falling ask_volume can mean listings sold, or were cancelled, or were repriced. Subtracting consecutive snapshots does not produce sale volume, and any model that does so will report phantom activity every time a seller changes their mind.
Reading the data correctly
Use one definition per analysis. Adding Steam purchases to CSFloat sales gives a covered-market total, not all CS2 sales, and it silently weights the result toward whichever marketplace has better coverage for that item.
For cross-market comparison, report separate series or index each marketplace against its own baseline. Steam counts purchases settled in Steam Wallet funds; CSFloat counts cash transactions. They are not the same unit of activity.
Keep the matching price beside every volume value. A busy day at a falling price and a busy day at a rising price are different events, and volume alone cannot distinguish them.
A missing bucket is a gap, not a zero-sale period, unless the endpoint explicitly returns a zero. Forward-filling before summing inflates activity in exactly the quiet stretches where the error matters most.
Archive history updates about 1-2x per day, so hourly buckets describe the bucket width rather than the collection rate.
Reading supply correctly
total_supply is approximate. Treat short-lived reversals or jumps as observations to validate rather than as literal destruction or issuance of items. Calculate change only between consecutive valid observations, and for issuance across a window, subtract the first valid observation from the last while disclosing any internal gaps.
A volume-to-supply ratio is a useful activity measure and a poor probability. It is not the chance that a listed item sells: the same ratio arises from heavy trading in a large population and from light trading in a tiny one. Store the raw sales and supply figures beside any ratio so those two cases stay distinguishable.
When items fail
All three archive endpoints validate items independently and return 200 with both items and errors[]. not_in_archive is the one to expect: it means a valid item has no rows in that archive, which is a coverage fact rather than a retryable error. unknown_item and invalid_format cover naming problems.
A 404 not_found means no requested valid item has rows in that dataset at all. Request-level failures carry error, message, and a request_id.
Worked example: did activity follow a supply change
Request 1d aggregate archive buckets across a window containing a case or collection change. Plot total_supply and hourly_volume on separate axes, never one unlabelled scale, and mark where supply moved.
Then check whether hourly_volume changed in the same direction and whether the aggregate ask moved with it. A supply increase that arrives with more sales and a flat price reads very differently from one that arrives with more sales and a falling price. Keep sample_count visible, because a bucket assembled from few readings can move for collection reasons rather than market ones.
Full references: POST /v1/archive/history, POST /v1/archive/csfloat, POST /v1/archive/steam. All need a Scale or Enterprise key.