Skip to main content

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.

Updated 6 min readIntermediatecurl · TypeScript · PythonMarkdown
On this page
  1. How phases are identified
  2. Step 1: list the phases of an item
  3. Step 2: get a cross-market price for every phase
  4. Step 3: break a phase down by float
  5. Step 4: track a phase band over time
  6. Pitfalls that cost money
  7. When to reach for a different endpoint

Doppler and Gamma Doppler knives are the clearest case where one Steam market name hides several very different items. A ★ Karambit | Doppler (Factory New) can be any of four phases or one of three gems, and those trade at very different prices, yet the market hash name is identical for all of them. A price quoted for the plain name is a blend, and it is wrong for every specific knife you might hold.

SkinPricer prices each phase and gem as its own item, so you can ask for exactly the variant you care about. This guide shows how to list an item's phases, get a cross-market price for each, break a phase down by float band, and pull a band's history.

How phases are identified#

Every phase and gem is a separate catalog item whose name is the base name plus a suffix. The plain base name still exists and represents the blended market; use it only when you really mean "any phase".

FinishVariant item names
Doppler<base> - Phase 1 to <base> - Phase 4, plus the gems <base> - Ruby, <base> - Sapphire, and <base> - Black Pearl
Gamma Doppler<base> - Phase 1 to <base> - Phase 4, plus the gem <base> - Emerald

For example, ★ Karambit | Doppler (Factory New) - Phase 2 and ★ Karambit | Gamma Doppler (Factory New) - Emerald. Not every knife and wear has every gem, so do not build the names by hand; list them from the catalog as shown next.

Step 1: list the phases of an item#

Look up the base item in the item schema. Its record carries a variants array with one entry per phase or gem: the variant's exact marketHashName, its family (doppler or gamma_doppler), its display name, and a numeric phase for Phase 1 to 4. The schema lookup is available from the Developer plan up. It is not wrapped by the published SDK yet, so the TypeScript sample calls it with fetch.

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

curl -s "https://pricing.skinpricer.com/v1/schema/items/%E2%98%85%20Karambit%20%7C%20Doppler%20(Factory%20New)" \
  -H "Authorization: ApiKey $SKINPRICER_API_KEY"
interface SchemaVariant {
  marketHashName: string;
  family: "doppler" | "gamma_doppler";
  name: string;
  phase?: number;
}

const base = "★ Karambit | Doppler (Factory New)";
const res = await fetch(
  `https://pricing.skinpricer.com/v1/schema/items/${encodeURIComponent(base)}`,
  { headers: { Authorization: `ApiKey ${process.env.SKINPRICER_API_KEY}` } },
);
if (!res.ok) throw new Error(`schema lookup failed: ${res.status}`);

const { item } = (await res.json()) as { item: { variants?: SchemaVariant[] } };
const variants = item.variants ?? [];
console.log(variants.map((v) => v.name).join(", "));
import os
from urllib.parse import quote

import requests

base = "★ Karambit | Doppler (Factory New)"
res = requests.get(
    f"https://pricing.skinpricer.com/v1/schema/items/{quote(base, safe='')}",
    headers={"Authorization": f"ApiKey {os.environ['SKINPRICER_API_KEY']}"},
    timeout=10,
)
res.raise_for_status()
variants = res.json()["item"].get("variants") or []
print([v["name"] for v in variants])
Response 200GET /v1/schema/items/:idOrName
Field reference
{
  "schemaVersion": 1783069455007,
  "item": {
    "id": "cmlofcu700pem01yop1965ua2",
    "marketHashName": "★ Karambit | Doppler (Factory New)",
    "slug": "karambit-doppler-factory-new",
    "category": "skin",
    "baseName": "★ Karambit | Doppler",
    "weapon": "Karambit",
    "finish": "Doppler",
    "rarity": "covert",
    "wear": "Factory New",
    "wears": ["Factory New", "Minimal Wear"],
    "stattrak": false,
    "souvenir": false,
    "hasStattrak": true,
    "hasSouvenir": false,
    "variants": [
      {
        "marketHashName": "★ Karambit | Doppler (Factory New) - Phase 1",
        "family": "doppler",
        "name": "Phase 1",
        "phase": 1,
        "image": "https://community.akamai.steamstatic.com/economy/image/..."
      },
      {
        "marketHashName": "★ Karambit | Doppler (Factory New) - Phase 2",
        "family": "doppler",
        "name": "Phase 2",
        "phase": 2,
        "image": "https://community.akamai.steamstatic.com/economy/image/..."
      },
      {
        "marketHashName": "★ Karambit | Doppler (Factory New) - Phase 3",
        "family": "doppler",
        "name": "Phase 3",
        "phase": 3,
        "image": "https://community.akamai.steamstatic.com/economy/image/..."
      },
      {
        "marketHashName": "★ Karambit | Doppler (Factory New) - Phase 4",
        "family": "doppler",
        "name": "Phase 4",
        "phase": 4,
        "image": "https://community.akamai.steamstatic.com/economy/image/..."
      },
      {
        "marketHashName": "★ Karambit | Doppler (Factory New) - Black Pearl",
        "family": "doppler",
        "name": "Black Pearl",
        "image": "https://community.akamai.steamstatic.com/economy/image/..."
      },
      {
        "marketHashName": "★ Karambit | Doppler (Factory New) - Ruby",
        "family": "doppler",
        "name": "Ruby",
        "image": "https://community.akamai.steamstatic.com/economy/image/..."
      },
      {
        "marketHashName": "★ Karambit | Doppler (Factory New) - Sapphire",
        "family": "doppler",
        "name": "Sapphire",
        "image": "https://community.akamai.steamstatic.com/economy/image/..."
      }
    ],
    "image": "https://community.akamai.steamstatic.com/economy/image/...",
    "ids": { "buff163": "42998", "marketcsgo": "★ Karambit | Doppler (Factory New)" }
  },
  "registries": {
    "rarities": [{ "key": "covert", "name": "Covert", "tier": 6, "color": "#eb4b4b" }],
    "collections": {},
    "containers": {}
  }
}
The documented schema record for the Factory New Doppler Karambit: four phases and three gems, each with its own market hash name.

Step 2: get a cross-market price for every phase#

Each variant name works anywhere the API takes a market hash name. The NBBO for a phase returns the best ask and best bid across every venue that lists that phase separately, with the usual freshness and confidence signals. Venues that only list the blended item simply do not contribute a quote.

Node (SDK)
// npm i @skinpricer/sdk
import { SkinpricerClient, formatUsd } from "@skinpricer/sdk";

const client = new SkinpricerClient({
  apiKey: process.env.SKINPRICER_API_KEY!,
  authScheme: "ApiKey",
});

for (const variant of variants) {
  const q = await client.nbbo.get({ marketHashName: variant.marketHashName });
  const ask = q.bestAsk ? `${formatUsd(q.bestAsk.price)} on ${q.bestAsk.market}` : "no asks";
  console.log(variant.name.padEnd(12), ask, `(${q.freshMarketCount} fresh venues)`);
}
One NBBO call per variant. Seven variants cost seven requests, so cache the results for your polling interval.

Step 3: break a phase down by float#

Within one phase, float still moves the price, and the lowest bands usually carry a premium. The attribute price endpoint returns BUFF163's phase buckets for a variant: a phase-wide bucket that covers every float, and one bucket per float band within the phase. Both are tagged with the phase in dimensions.variant. Request attributes=float,tag; the phase-wide bucket is a pure tag bucket and is omitted by the default float-only filter.

curl -s "https://pricing.skinpricer.com/v1/attribute-prices/latest?marketHashName=%E2%98%85%20Karambit%20%7C%20Doppler%20(Factory%20New)%20-%20Phase%202&attributes=float,tag" \
  -H "Authorization: ApiKey $SKINPRICER_API_KEY"
const phase = await client.attributePrices.latest({
  marketHashName: "★ Karambit | Doppler (Factory New) - Phase 2",
  attributes: ["float", "tag"],
});

for (const item of phase.items) {
  for (const bucket of item.buckets) {
    const band = bucket.dimensions.float;
    const label = band ? `float ${band.min} to ${band.max}` : "all floats";
    const ask = bucket.askCents === null ? "no asks" : formatUsd(bucket.askCents);
    console.log(item.market, bucket.dimensions.variant, label, ask);
  }
}
Response 200GET /v1/attribute-prices/latest
Field reference
{
  "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": []
}
Two float bands of the Phase 2 Karambit on BUFF163. attributeTypes shows each bucket bands on both the phase tag and a float range.

Step 4: track a phase band over time#

Every bucket has a stable bucketId. Pass it to attribute price history to get that band's open, high, low, and close asks per interval, plus the closing bid. History requires the Pro plan. Daily spacing over a quarter is a good default for charts; switch to 1h or 10m for recent, fast-moving windows.

Node (SDK)
const history = await client.attributePrices.history({
  bucketId: "buff163:cmlofa7dh08ww01yo9lrpej3e:tag:446954:float:0-0.01",
  granularity: "1d",
  from: new Date(Date.now() - 90 * 24 * 60 * 60 * 1000),
});

for (const point of history.items[0]?.buckets[0]?.points ?? []) {
  console.log(point.bucketStart.slice(0, 10), point.closeAskCents, point.closeBidCents);
}

Pitfalls that cost money#

  • Never value a specific knife from the plain base name. The blended price mixes cheap and expensive phases and fits none of them.
  • dimensions.variant uses the source market's own label (for example Phase2 or Emerald). Treat the variant item name from Step 1 as the authoritative label and the bucket tag as confirmation.
  • Gems are thin. A Ruby or Emerald may have only a handful of listings across all venues, so check isStale, freshMarketCount, and askListingCount before trusting a single quote.
  • null bids are common on gem bands. No buy order is not the same as a zero bid.
  • On knives, a listing's paintIndex identifies the phase when the market exposes it: Doppler Ruby is 415, Sapphire 416, Black Pearl 417, and Phases 1 to 4 are 418 to 421; Gamma Doppler Emerald is 568 and Phases 1 to 4 are 569 to 572.

When to reach for a different endpoint#

To price ordinary skins by float, without a phase, follow the float range guide. To inspect the individual listings behind a phase price, including exact floats and paint indexes, use the listing data guide. And for BUFF's full bucket set and history in one place, see BUFF163 prices and history.

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.