How to price a CS2 skin by its float range
Price a CS2 skin by its exact float: how float-range buckets work per market, how to query them, and how to spot low-float premiums. Runnable API code.
On this page
Every CS2 skin has a float value between 0 and 1 that sets its wear. The market hash name only tells you the exterior band the float falls in, such as Field-Tested (0.15 to 0.38), but buyers care about where inside that band a skin sits. A 0.151 Field-Tested AK-47 | Redline looks close to Minimal Wear and usually sells above a 0.37 one, even though both share one market hash name and one headline price.
To price a specific item, you need prices by float range. SkinPricer collects them from the markets that segment by float and serves them from GET /v1/attribute-prices/latest as buckets: one price per float band, per market, with ask, bid, and listing counts. This guide covers how the buckets are built, how to find the one your float falls into, and how to measure the low-float premium.
How float buckets work#
Buckets follow each market's own segmentation rather than an invented common scheme, so bucket widths differ by venue. Every bucket describes its exact bounds in dimensions.float, as a half-open range (minInclusive: true, maxInclusive: false), and never crosses an exterior boundary.
| Market | Float bands |
|---|---|
buff163 | BUFF's native, non-uniform ranges. For Field-Tested: 0.15 to 0.18, 0.18 to 0.21, 0.21 to 0.24, 0.24 to 0.27, and 0.27 to 0.38. |
steamcommunity, marketcsgo, csfloat, dmarket | Uniform 0.01-wide bins: 0.15 to 0.16, 0.16 to 0.17, and so on, clamped to the exterior. |
The full band table for every exterior lives on the attribute buckets concept page. The practical rule is simple: never parse or compare bucket labels across markets. Compare on dimensions.float.min and dimensions.float.max.
Step 1: fetch the float buckets for an item#
Scope the request to one item with marketHashName (or canonicalItemId). Float buckets are returned by default, from every supported market, and the latest read is included from the Developer plan up. Restrict venues with markets; any venue you ask for that has no bucket coverage is listed in sourceGaps instead of being silently dropped.
export SKINPRICER_API_KEY="sp_live_•••" # from your account's API keys page
curl -s "https://pricing.skinpricer.com/v1/attribute-prices/latest?marketHashName=AK-47%20%7C%20Redline%20(Field-Tested)&markets=buff163,csfloat" \
-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 res = await client.attributePrices.latest({
marketHashName: "AK-47 | Redline (Field-Tested)",
markets: ["buff163", "csfloat"],
});
for (const item of res.items) {
console.log(`${item.market}: ${item.buckets.length} float buckets`);
}import os
import requests
res = requests.get(
"https://pricing.skinpricer.com/v1/attribute-prices/latest",
params={
"marketHashName": "AK-47 | Redline (Field-Tested)",
"markets": "buff163,csfloat",
},
headers={"Authorization": f"ApiKey {os.environ['SKINPRICER_API_KEY']}"},
timeout=10,
)
res.raise_for_status()
data = res.json()
print("markets without coverage:", data["sourceGaps"]){
"bucketSchemaVersion": 1,
"markets": ["buff163", "steamcommunity", "marketcsgo", "csfloat", "dmarket"],
"currency": "USD",
"asOf": "2026-06-23T09:18:45.864Z",
"items": [
{
"canonicalItemId": "cmlofa7dh08ww01yo9lrpej3e",
"marketHashName": "★ Karambit | Doppler (Factory New) - Phase 2",
"market": "buff163",
"buckets": [
{
"bucketId": "buff163:cmlofa7dh08ww01yo9lrpej3e:tag:446954:float:0-0.01",
"bucketKey": "tag:446954:float:0-0.01",
"bucketType": "attribute",
"attributeType": "tag",
"attributeTypes": ["tag", "float"],
"dimensions": {
"variant": "Phase2",
"float": { "min": 0, "max": 0.01, "minInclusive": true, "maxInclusive": false },
"fade": null,
"pattern": null,
"paintSeed": null
},
"sourceItemId": "44102",
"sourceBucketId": "buff163:44102:tag446954:f0-0.01",
"askCents": 197795,
"avgAskCents": 201340,
"medianAskCents": 199500,
"bidCents": 179787,
"askListingCount": 82,
"bidOrderCount": null,
"sourceUpdatedAt": "2026-06-23T09:10:00.000Z",
"collectedAt": "2026-06-23T09:11:35.446Z"
},
{
"bucketId": "buff163:cmlofa7dh08ww01yo9lrpej3e:tag:446954:float:0.01-0.02",
"bucketKey": "tag:446954:float:0.01-0.02",
"bucketType": "attribute",
"attributeType": "tag",
"attributeTypes": ["tag", "float"],
"dimensions": {
"variant": "Phase2",
"float": { "min": 0.01, "max": 0.02, "minInclusive": true, "maxInclusive": false },
"fade": null,
"pattern": null,
"paintSeed": null
},
"sourceItemId": "44102",
"sourceBucketId": "buff163:44102:tag446954:f0.01-0.02",
"askCents": 189676,
"avgAskCents": 191220,
"medianAskCents": 190100,
"bidCents": 179344,
"askListingCount": 66,
"bidOrderCount": null,
"sourceUpdatedAt": "2026-06-23T09:10:00.000Z",
"collectedAt": "2026-06-23T09:11:35.446Z"
}
]
}
],
"nextCursor": null,
"sourceGaps": []
}dimensions.float holds the exact band.Step 2: find the bucket your float falls into#
Given one skin's float, pick the bucket whose range contains it on each market. Respect the inclusivity flags so a float of exactly 0.18 lands in the 0.18 to 0.21 band, not the 0.15 to 0.18 one.
import type { AttributePriceBucket } from "@skinpricer/sdk";
/** The float bucket containing `value`, honoring half-open bounds. */
function bucketFor(value: number, buckets: AttributePriceBucket[]) {
return buckets.find((b) => {
const r = b.dimensions.float;
if (!r) return false;
const aboveMin = r.minInclusive ? value >= r.min : value > r.min;
const belowMax = r.maxInclusive ? value <= r.max : value < r.max;
return aboveMin && belowMax;
});
}
const myFloat = 0.1512;
for (const item of res.items) {
const bucket = bucketFor(myFloat, item.buckets);
const ask = bucket?.askCents;
console.log(item.market, ask == null ? "no listing in this band" : formatUsd(ask));
}Step 3: measure the low-float premium#
The premium for a low float is easiest to read as a ratio: the ask in your band divided by the ask in the item's highest band on the same market. Comparing within one market avoids mixing different band widths and different fee structures. On BUFF, the 0.15 to 0.18 band of a Field-Tested item is the one closest to Minimal Wear, and it is typically where the premium concentrates.
for (const item of res.items) {
const priced = item.buckets.filter((b) => b.askCents !== null && b.dimensions.float);
const top = priced.reduce<AttributePriceBucket | undefined>(
(hi, b) => (!hi || b.dimensions.float!.min > hi.dimensions.float!.min ? b : hi),
undefined,
);
if (!top?.askCents) continue;
for (const b of priced) {
const ratio = b.askCents! / top.askCents;
console.log(item.market, b.bucketKey, `${((ratio - 1) * 100).toFixed(1)}% vs highest band`);
}
}Step 4: watch one band over time#
Each bucket has a stable bucketId. Pass one or more of them (bucketIds accepts a list) to attribute price history to get a points[] series with open, high, low, and close asks and the closing bid per interval. History reads require the Pro plan, default to the last 7 days, and accept 10m, 1h, or 1d spacing.
const lowBand = res.items
.find((i) => i.market === "buff163")
?.buckets.find((b) => b.dimensions.float?.min === 0.15);
if (lowBand) {
const history = await client.attributePrices.history({
bucketIds: [lowBand.bucketId],
granularity: "1d",
from: new Date(Date.now() - 60 * 24 * 60 * 60 * 1000),
});
const points = history.items[0]?.buckets[0]?.points ?? [];
console.log(points.map((p) => p.closeAskCents));
}{
"bucketSchemaVersion": 1,
"markets": ["buff163", "steamcommunity", "marketcsgo", "csfloat", "dmarket"],
"currency": "USD",
"granularity": "10m",
"items": [
{
"canonicalItemId": "cmlofa7dh08ww01yo9lrpej3e",
"marketHashName": "★ Karambit | Doppler (Factory New) - Phase 2",
"market": "buff163",
"buckets": [
{
"bucketId": "buff163:cmlofa7dh08ww01yo9lrpej3e:tag:446954:float:0-0.01",
"bucketKey": "tag:446954:float:0-0.01",
"bucketType": "attribute",
"attributeType": "tag",
"attributeTypes": ["tag", "float"],
"dimensions": {
"variant": "Phase2",
"float": { "min": 0, "max": 0.01, "minInclusive": true, "maxInclusive": false },
"fade": null,
"pattern": null,
"paintSeed": null
},
"points": [
{
"bucketStart": "2026-06-16T14:40:00.000Z",
"openAskCents": 192390,
"highAskCents": 192390,
"lowAskCents": 192390,
"closeAskCents": 192390,
"avgAskCents": 192390,
"closeBidCents": 179367,
"askListingCount": 87,
"bidOrderCount": null,
"firstObservedAt": "2026-06-16T14:41:02.190Z",
"lastObservedAt": "2026-06-16T14:41:04.342Z"
},
{
"bucketStart": "2026-06-16T14:50:00.000Z",
"openAskCents": 192390,
"highAskCents": 192390,
"lowAskCents": 192390,
"closeAskCents": 192390,
"avgAskCents": 192390,
"closeBidCents": 179367,
"askListingCount": 87,
"bidOrderCount": null,
"firstObservedAt": "2026-06-16T14:51:03.475Z",
"lastObservedAt": "2026-06-16T14:51:12.491Z"
},
{
"bucketStart": "2026-06-16T15:00:00.000Z",
"openAskCents": 192410,
"highAskCents": 192410,
"lowAskCents": 192410,
"closeAskCents": 192410,
"avgAskCents": 192410,
"closeBidCents": 179385,
"askListingCount": 87,
"bidOrderCount": null,
"firstObservedAt": "2026-06-16T15:00:49.830Z",
"lastObservedAt": "2026-06-16T15:00:49.830Z"
}
]
}
]
}
],
"sourceGaps": []
}Pitfalls that skew float prices#
- Bands differ per market, so a BUFF 0.15 to 0.18 price and a Steam 0.15 to 0.16 price are not the same thing. Compare markets only on overlapping ranges.
- Not every market reports buy orders per float band, so
bidCentsandbidOrderCountare oftennulloutside BUFF. That means no band-level bid was observed, not a bid of zero. - A band's ask is the cheapest listing inside that band. On thin bands it can be a single listing, so check
askListingCountbefore quoting it. - Without an item scope the endpoint returns a paginated snapshot of every item. Follow
nextCursoruntil it isnull(the SDK'slatestEachdoes this for you). - Fade and pattern buckets are omitted by default. Add
attributes=float,fade,tagfor fade percentages (such as 90 to 93) and phase or pattern tags.
When to reach for a different endpoint#
For Doppler and Gamma Doppler, float bands sit inside each phase; the phase pricing guide covers that case. If BUFF is the only venue you need, the BUFF163 guide uses the market-scoped endpoints. And if you need each item's possible float range before you price anything, sync it from the item schema as shown in syncing the CS2 item catalog.
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
- Floats & attributesIntermediate
How to get CS2 Doppler phase prices, from Phase 1 to Emerald
Price CS2 Doppler and Gamma Doppler by phase: Phase 1 to 4, Ruby, Sapphire, Black Pearl, and Emerald, with live buckets and history. Runnable code.
GET /v1/schema/items/:idOrNameGET /v1/nbbo6 min read - Floats & attributesBeginner
How to get float, paint seed, and sticker data for live CS2 listings
Get per-listing CS2 data: float value, paint seed, paint index, and stickers for live listings across marketplaces, with runnable curl and TypeScript.
GET /v1/pricing/:marketHashName/listings5 min read - History & backtestingIntermediate
How to get BUFF163 prices, float buckets, and history in USD
Get BUFF163 prices, native float buckets, and price history for CS2 items in USD cents, without scraping or converting currency. Runnable API code included.
GET /v1/markets/buff163/latestGET /v1/markets/buff163/history6 min read - Catalog & data qualityIntermediate
How to sync the full CS2 item catalog with float ranges and images
Sync every CS2 item with float ranges, collections, images, and per-market ids, then keep it current with ETags and incremental change cursors.
GET /v1/schemaGET /v1/schema/changes6 min read