Skip to main content

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.

Updated 5 min readBeginnercurl · TypeScript · PythonMarkdown
On this page
  1. What each listing carries
  2. Step 1: request the listings
  3. Step 2: know what the sample is
  4. Step 3: filter by float, pattern, or stickers
  5. Coverage varies by market
  6. When to reach for a different endpoint

Aggregated prices answer "what does this item cost". They cannot answer "what does this particular skin cost", because two listings of the same market hash name can differ in float, pattern, and applied stickers, and each of those moves the price. For that you need the individual listings, one row per skin for sale, with its attributes attached.

GET /v1/pricing/:marketHashName/listings returns exactly that: a sample of live listings across markets, each with its price, float value, paint seed, paint index, stickers, and StatTrak flag, plus metadata about which markets exposed floats. It powers float-versus-price scatter plots, sticker-craft searches, and pattern hunting.

What each listing carries#

FieldMeaning
market / listingIdThe venue and its own listing id. listingId is null on aggregate fallback rows (see below).
priceThe listing price in integer USD cents.
floatValueThe wear value from 0 to 1, or null when the market does not publish it.
paintSeedThe pattern index that decides the texture placement, or null.
paintIndexThe finish catalog index, which also identifies Doppler phases on knives, or null.
stickersApplied stickers as { name, slot, wear } objects. An empty array when none are applied or reported. wear is the sticker's scratch wear, 0 (new) to 1 (fully scratched), and is omitted when the market does not report it. Treat a missing wear as unknown, not 0.
isStatTrakWhether the listing is StatTrak.
inspectLink / fetchedAtAn inspect reference when available, and when the listing was last fetched.

Step 1: request the listings#

Put the URL-encoded market hash name in the path. limit controls the sample size (1 to 2000, default 500), and market (or its alias markets) restricts the venues with a comma-separated list. The endpoint is included from the Developer plan up.

export SKINPRICER_API_KEY="sp_live_•••"   # from your account's API keys page

curl -s "https://pricing.skinpricer.com/v1/pricing/AK-47%20%7C%20Redline%20(Field-Tested)/listings?limit=200" \
  -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.pricing.listings("AK-47 | Redline (Field-Tested)", {
  limit: 200,
});

console.log(`${res.sampledListings} of ${res.totalListings} listings, float coverage: ${res.floatCoverage.coverage}`);
for (const l of res.listings.slice(0, 5)) {
  console.log(l.market, formatUsd(l.price), l.floatValue ?? "no float", l.paintSeed ?? "no seed");
}
import os
from urllib.parse import quote

import requests

name = "AK-47 | Redline (Field-Tested)"
res = requests.get(
    f"https://pricing.skinpricer.com/v1/pricing/{quote(name, safe='')}/listings",
    params={"limit": 200},
    headers={"Authorization": f"ApiKey {os.environ['SKINPRICER_API_KEY']}"},
    timeout=10,
)
res.raise_for_status()
data = res.json()

with_float = [l for l in data["listings"] if l["floatValue"] is not None]
print(f"{len(with_float)} of {data['sampledListings']} sampled listings have a float")
Response 200GET /v1/pricing/:marketHashName/listings
Field reference
{
  "marketHashName": "AK-47 | Redline (Field-Tested)",
  "canonicalItemId": "cmlofczf90qj401vsd80dskd1",
  "totalListings": 22022,
  "sampledListings": 2,
  "floatCoverage": {
    "coverage": "partial",
    "sampledListings": 2,
    "listingsWithFloat": 2,
    "marketsWithFloat": [
      "avanmarket"
    ],
    "marketsWithoutFloat": [
      "buff163",
      "csfloat",
      "cstrade",
      "dmarket",
      "itrade",
      "lis-skins",
      "lootfarm",
      "mannco-store",
      "marketcsgo",
      "skindeck",
      "skinport",
      "steamcommunity",
      "swapgg",
      "tradeit-store",
      "tradeit-trade",
      "waxpeer",
      "whitemarket"
    ]
  },
  "floatSummary": {
    "observed": 0.15027404,
    "itemMin": 0.15,
    "itemMax": 0.38,
    "observedSource": {
      "market": "avanmarket",
      "price": 9404,
      "fetchedAt": "2026-09-25T11:25:44.891Z",
      "isStale": false
    }
  },
  "listings": [
    {
      "listingId": "listing:5698b064-d92a-4b7f-8c5f-4aa014d1400e",
      "market": "avanmarket",
      "price": 9484,
      "currency": "USD",
      "originalPriceCents": 9484,
      "originalCurrency": "USD",
      "floatValue": 0.15005141,
      "paintSeed": null,
      "paintIndex": null,
      "inspectLink": null,
      "stickers": [],
      "isStatTrak": false,
      "fetchedAt": "2026-09-25T11:25:44.891Z",
      "isStale": false
    },
    {
      "listingId": "listing:e40c11f4-73f7-4d15-89e4-765e3ee14253",
      "market": "avanmarket",
      "price": 9404,
      "currency": "USD",
      "originalPriceCents": 9404,
      "originalCurrency": "USD",
      "floatValue": 0.15027404,
      "paintSeed": null,
      "paintIndex": null,
      "inspectLink": null,
      "stickers": [
        {
          "name": "Sticker | device | Cologne 2016",
          "slot": 0
        },
        {
          "name": "Sticker | Astralis (Holo) | Cologne 2016",
          "slot": 1
        },
        {
          "name": "Sticker | device (Foil) | Cologne 2016",
          "slot": 2
        }
      ],
      "isStatTrak": false,
      "fetchedAt": "2026-09-25T11:25:44.891Z",
      "isStale": false
    }
  ],
  "calculatedAt": "2026-09-25T11:33:18.805Z"
}
The documented response. floatCoverage says which markets contributed floats to this sample; floatSummary places the observed float inside the item's possible range.
Live
Try it live

Fetch live AK-47 | Redline (Field-Tested) listings right now, in your browser.

Step 2: know what the sample is#

The response is a sample of up to limit listings (sampledListings) out of all active listings (totalListings), drawn from listings seen in the last 24 hours. It is ordered for attribute work: listings with a known float come first, lowest float first, and price breaks ties. That makes it the right input for float and pattern analysis, and the wrong one for finding the cheapest listing, which is what the best ask is for.

  • floatCoverage.coverage is complete, partial, or none. marketsWithFloat lists the venues that contributed a float in this sample, and marketsWithoutFloat lists the active venues that did not.
  • floatSummary.observed is the float of the cheapest float-bearing listing in the sample, with observedSource naming its market, price, and fetch time. itemMin and itemMax are the item's possible float range, already clamped to its exterior.
  • When no individual listings are available, the endpoint falls back to one latest row per market, with listingId: null and no attributes. Treat those as prices, not as skins.

Step 3: filter by float, pattern, or stickers#

With the sample in hand, the filters are ordinary code. The published SDK types stickers loosely, so narrow each entry before reading it. The example below finds listings under a float ceiling, a set of paint seeds you care about, and any listing carrying a given sticker, then prints that listing's stickers with a missing wear shown as unknown.

Node (SDK)
interface Sticker {
  name: string;
  slot: number;
  wear?: number | null; // 0 (new) to 1 (fully scratched); omitted when unknown
}

function isSticker(value: unknown): value is Sticker {
  return typeof value === "object" && value !== null && "name" in value && "slot" in value;
}

// A missing wear is unknown, never 0% scratched.
function stickerWear(s: Sticker): string {
  return s.wear == null ? "unknown" : `${Math.round(s.wear * 100)}%`;
}

const lowFloat = res.listings.filter((l) => l.floatValue !== null && l.floatValue < 0.16);
const wantedSeeds = new Set([661, 670]);
const patterns = res.listings.filter((l) => l.paintSeed !== null && wantedSeeds.has(l.paintSeed));
const withCrown = res.listings.filter((l) =>
  l.stickers.filter(isSticker).some((s) => s.name.includes("Crown (Foil)")),
);

console.log(lowFloat.length, "low floats,", patterns.length, "pattern matches,", withCrown.length, "with Crown (Foil)");
for (const s of withCrown[0]?.stickers.filter(isSticker) ?? []) {
  console.log(`slot ${s.slot}: ${s.name}, wear ${stickerWear(s)}`);
}
Paint seeds and sticker names here are placeholders. Which seeds matter is specific to each finish.

Coverage varies by market#

Only some venues expose per-listing attributes, and coverage changes as markets change their feeds. Read floatCoverage on every response rather than hard-coding a list. If you need a float-level price but the listing sample for an item is thin, the market-level float buckets are often better populated: the float range guide shows how to read them.

Rust has no float, pattern, or sticker semantics. The game-scoped /v2 listings route returns the same shape with those fields always null or empty; see Games: CS2 & Rust.

When to reach for a different endpoint#

For the price of a float band rather than individual skins, use attribute prices. For Doppler and Gamma Doppler, the phase pricing guide prices each phase separately. And for the current best price across every venue, regardless of attributes, use the live pricing snapshot.

Endpoints used in this guide

Run this guide against live data

Plans start at $50/month on the Developer tier. Want to try first? Ask in our Discord for a free 2-day Developer key.