How to Get CSFloat Buy-Order Prices
Updated
The
csfloat.bidfield in cs2.sh'sGETorPOST /v1/prices/latestis the highest buy order currently standing on CSFloat. It is the price a seller could accept immediately, as opposed toask, which is the lowest price a buyer would have to pay.
Most CS2 price data describes what sellers want. Buy orders describe what buyers have actually committed to, which is a different and often more useful number: it is the side of the book you can transact against without waiting.
What cs2.sh provides for CSFloat buy orders
| Property | Value |
|---|---|
| Current value | csfloat.bid in GET / POST /v1/prices/latest |
| History | bid OHLC in POST /v1/prices/history with sources: ["csfloat"], from December 24, 2025 |
| Refresh | About every 5 minutes; CSFloat variant bids about every 10-15 minutes |
| Variants | Doppler, Gamma Doppler, and Case Hardened, under variants |
| Bid depth | Not published. CSFloat returns ask_volume but no bid_volume. |
| Access | Current prices on all plans; history requires Scale or Enterprise |
That last row is the constraint to design around. CSFloat reports ask, bid, and ask_volume, but no bid_volume. You know the highest buy order and nothing about how many items stand behind it.
Request the current buy order
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 CSFloat object arrives under each item:
"csfloat": {
"updated_at": "2026-07-26T18:53:05.094Z",
"collected_at": "2026-07-26T18:53:05.134Z",
"ask": 107.99,
"ask_volume": 227,
"bid": 105
}| Field | Type | Description |
|---|---|---|
csfloat.bid |
number | null |
Highest standing buy order, USD. |
csfloat.ask |
number | null |
Lowest active sell listing, USD. |
csfloat.ask_volume |
integer | null |
Number of active sell listings. |
csfloat.updated_at |
string (date-time) |
When CSFloat last updated the price. |
csfloat.collected_at |
string (date-time) |
When cs2.sh collected it. |
Base item source objects are dense, so csfloat is present whenever any source has data for the item and bid is null when no buy order exists. Variant source objects are sparse: csfloat appears under a variant only when CSFloat has data for that exact phase.
Follow the buy order over time
POST /v1/prices/history with sources: ["csfloat"] returns open_bid, high_bid, low_bid, and close_bid per bucket from December 24, 2025, at 5m, 30m, 1h, or 1d.
| Interval | Maximum request range |
|---|---|
5m |
14 days |
30m |
90 days |
1h |
365 days |
1d |
Unlimited |
Those ranges are per request, not per account: a year of 30m history is four requests stitched together, not an error.
Each bucket also carries open_time, close_time, and sample_count. bucket is the UTC interval boundary, while open_time and close_time are the first and last actual observations inside it. On a thin item those can sit far apart, which explains gaps that look like missing data but are really sparse collection.
Reading the data correctly
The gap between ask and bid is the distance between what sellers want and what buyers have committed to. Calculate it only from values in the same source object, collected at the same time. Comparing a bid collected now against an ask collected eight minutes ago produces a number that describes neither moment.
Without bid_volume, a buy order cannot be multiplied by an intended quantity. It tells you the price of the next unit, not the tenth. Any model that assumes depth on CSFloat is assuming data the marketplace does not publish.
A buy order is not a completed sale. It is an offer that can be filled, changed, or cancelled before you act on it. When the question is what items actually sold for, use POST /v1/archive/csfloat, which returns a daily average sale price and sale count from 2022.
Variant bids are independent. A missing Phase 3 buy order cannot inherit the base Doppler bid or another phase's.
When the value is absent
bid is null when CSFloat has no standing buy order for that item, which is common on illiquid skins and on individual phases. That is a real market state rather than an error, and it should propagate as absent rather than as zero. In history responses, per-source objects appear only when that source had data in the bucket, and valid items with no buckets in the requested range are omitted from items entirely.
When items and variants fail
Item-level failures arrive in errors[] beside successful results in a 200 response. unknown_item and invalid_format cover naming problems, not_in_cache covers a valid item with no current data, and unsupported_variant covers a phase or tier CSFloat does not carry.
In history responses, request-level failures carry error, message, and a request_id. A 403 means history is not included in your plan, which is the most common first failure against this endpoint since current prices are available on all plans and history is not.
Worked example: what a seller could get today
Read csfloat.bid for the item, confirm collected_at is within your freshness tolerance, and treat that as the immediately acceptable price. Compare it against csfloat.ask from the same object to see the gap the seller is giving up by not waiting, and against the most recent price in the CSFloat sale archive to see whether recent sales cleared above or below the standing buy order.
Apply marketplace fees and transfer assumptions outside the API, and store the raw bid, the adjusted figure, the source, and the timestamp as separate fields so the derived number is always traceable to the observation it came from.
Full field reference: GET /v1/prices/latest. History intervals and limits: POST /v1/prices/history. Variant naming and versions: variants.