How to find the best bid and ask for a CS2 skin across every market
Find the highest buy order and lowest ask for any CS2 skin across every marketplace at once, with freshness, spread, and confidence. Runnable code included.
On this page
Every CS2 marketplace shows you its own lowest listing and, if it has a buy-order book, its own highest bid. None of them shows you the best price across all of them. If you are pricing a trade, routing a purchase, or deciding where to sell, you need both sides of the book across every venue at once, with enough metadata to know whether each side is still real.
That cross-market top of book is called the NBBO (national best bid and offer, a term borrowed from equities). SkinPricer computes it for every tracked item and serves it from one endpoint, GET /v1/nbbo. This guide shows how to call it, how to read every field, and which checks to run before you act on the number.
What you get back#
One request returns the lowest ask and the highest bid across every integrated marketplace, each naming the venue it came from, plus the spread between them and a few quality signals. All prices are integer USD cents, so 6500 means $65.00.
| Field | What it tells you |
|---|---|
bestAsk | The cheapest live listing across all venues: market, price, updatedAt, isStale. null when nothing is listed. |
bestBid | The highest standing buy order. In the default view only cash-executable venues count (see below). null when no venue has a bid. |
spreadBps | (ask − bid) ÷ bid, in basis points (100 bps = 1%). null when a side is missing or the spread would exceed 10000 bps. |
marketCount / freshMarketCount | How many venues quote the item, and how many of those quotes are fresh. |
confidence | A 0 to 1 score built from coverage, freshness, and cross-market agreement. |
locked / crossed | Zero spread, or a bid that nets above the ask after the selling venue's fees. |
executionAdjusted | The same book re-ranked by what you would actually pay and receive after fees. |
Step 1: make the request#
Identify the item by its exact Steam market_hash_name (or by its canonical id if you already store one). Send your API key in the Authorization header. The endpoint is included in every plan, starting with Developer.
export SKINPRICER_API_KEY="sp_live_•••" # from your account's API keys page
curl -s "https://pricing.skinpricer.com/v1/nbbo?market_hash_name=AK-47%20%7C%20Redline%20(Field-Tested)" \
-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 quote = await client.nbbo.get({
marketHashName: "AK-47 | Redline (Field-Tested)",
});
if (quote.bestAsk && quote.bestBid) {
console.log(`Buy on ${quote.bestAsk.market} at ${formatUsd(quote.bestAsk.price)}`);
console.log(`Sell on ${quote.bestBid.market} at ${formatUsd(quote.bestBid.price)}`);
console.log(`Spread: ${quote.spreadBps ?? "n/a"} bps`);
}import os
import requests
res = requests.get(
"https://pricing.skinpricer.com/v1/nbbo",
params={"market_hash_name": "AK-47 | Redline (Field-Tested)"},
headers={"Authorization": f"ApiKey {os.environ['SKINPRICER_API_KEY']}"},
timeout=10,
)
res.raise_for_status()
nbbo = res.json()
ask, bid = nbbo["bestAsk"], nbbo["bestBid"]
if ask and bid:
print(f"Buy on {ask['market']} at ${ask['price'] / 100:.2f}")
print(f"Sell on {bid['market']} at ${bid['price'] / 100:.2f}")
print(f"Spread: {nbbo['spreadBps']} bps"){
"marketHashName": "Glock-18 | Water Elemental (Factory New)",
"canonicalItemId": "cmlofca920lka01yozajhixt3",
"bestAsk": {
"market": "csfloat",
"price": 4373,
"updatedAt": "2026-09-25T11:20:00.981Z",
"isStale": false
},
"bestBid": {
"market": "marketcsgo",
"price": 4486,
"updatedAt": "2026-09-25T11:20:03.070Z",
"isStale": false
},
"spreadBps": -252,
"marketCount": 16,
"freshMarketCount": 15,
"locked": false,
"crossed": false,
"confidence": 0.88,
"executionAdjusted": {
"bestAsk": {
"market": "csfloat",
"price": 4373,
"rawPrice": 4373,
"appliedFeeBps": 0,
"executability": 0.51,
"updatedAt": "2026-09-25T11:20:00.981Z",
"isStale": false,
"reasons": [
"unknown_executable_depth"
]
},
"bestBid": {
"market": "buff163",
"price": 4256,
"rawPrice": 4365,
"appliedFeeBps": 250,
"withdrawalFlatUsdCents": 0,
"executability": 0.51,
"updatedAt": "2026-09-25T11:20:11.402Z",
"isStale": false,
"reasons": [
"unknown_executable_depth"
]
},
"spreadBps": 275,
"locked": false,
"crossed": false,
"executableConfidence": 0.7,
"reasons": [
"unknown_executable_depth"
],
"feeModelVersion": "exec-fees-v1-estimated",
"calculatedAt": "2026-09-25T11:28:40.236Z"
},
"calculatedAt": "2026-09-25T11:28:40.236Z"
}Fetch the current NBBO for AK-47 | Redline (Field-Tested) right now, in your browser.
Step 2: read the bid the way the market pays it#
Not every bid is cash. Steam Community Market buy orders settle in Steam wallet credit, and some trade-bot venues pay in site balance. If those bids were mixed into the book, a wallet-denominated bid would routinely sit above a cash ask and every popular item would look like free money. So in the default all-markets view, bestBid only considers cash-executable venues.
If you do want every venue's bid considered, pass an explicit markets list (for example markets=steamcommunity,buff163,csfloat). The filter is then off and each requested venue's bid is taken verbatim. The Ask, bid & NBBO concept page explains the rule in full.
Step 3: use the execution-adjusted book for real decisions#
The executionAdjusted block re-ranks the same quotes by what a trade would actually cost. Its ask price is the total a buyer pays, its bid price is the net a seller receives after commission and withdrawal, and both carry the untouched rawPrice, the appliedFeeBps, and an executability score that discounts stale or thin quotes. Its spreadBps is the realistic round-trip cost; the top-level spreadBps is the display spread.
const adj = quote.executionAdjusted;
if (adj?.bestAsk && adj.bestBid) {
console.log(`Display spread: ${quote.spreadBps} bps`);
console.log(`After fees: ${adj.spreadBps} bps`);
console.log(
`A ${formatUsd(adj.bestBid.rawPrice)} bid nets ${formatUsd(adj.bestBid.price)}`,
`on ${adj.bestBid.market} (${adj.bestBid.appliedFeeBps} bps in fees)`,
);
}Step 4: decide whether to trust the quote#
A top-of-book number is only as good as the quotes behind it. Every side carries its own updatedAt and isStale flag (stale means older than a uniform 30-minute window), and the response as a whole carries confidence, freshMarketCount, and the crossed flag. A sensible gate before acting looks like this:
import type { NbboResponse } from "@skinpricer/sdk";
/** True when both sides are live, fresh, and backed by more than one venue. */
export function isActionable(q: NbboResponse): boolean {
if (!q.bestAsk || !q.bestBid) return false;
if (q.bestAsk.isStale || q.bestBid.isStale) return false;
if (q.crossed) return false; // one leg probably moved first
return q.freshMarketCount >= 2 && q.confidence >= 0.6;
}nullis not zero. A missing bid means nobody is bidding, not that the bid is $0. Keep nulls out of averages.- A
crossedbook usually means one venue refreshed before the other. Re-query before you trade it. spreadBpsuses the bid as its denominator here, and is clamped tonullabove 10000 bps because a spread that wide almost always means a stale bid.- Cache for your polling interval rather than calling per page view. Your plan's per-minute budget is shared across every key on the account.
When to reach for a different endpoint#
The NBBO is the top of the book: one price per side. If you need to know how many units sit behind that price, read order-book depth. If you want every venue's quote side by side for a comparison table, use the full pricing snapshot. And to turn the quote into an estimate of what the item is worth, see estimating fair value.
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
- Prices & quotesBeginner
How to get live CS2 skin prices from every marketplace
Pull live CS2 skin prices from every major marketplace in one call: per-market asks, bids, and aggregate stats in USD cents, with runnable curl and TypeScript.
GET /v1/pricing/:marketHashNameGET /v1/items6 min read - Liquidity & depthIntermediate
How to read CS2 order-book depth across every marketplace
Read aggregated CS2 order-book depth: bid and ask ladders merged across marketplaces, cumulative quantity, and what thin books mean for your fills.
GET /v1/nbbo/depthGET /v1/nbbo6 min read - Prices & quotesIntermediate
Steam Market vs cash-market prices: how to compare them correctly
Steam Market prices are wallet credit, not cash. Learn how to compare Steam and cash-market CS2 prices after fees, using execution-adjusted quotes.
GET /v1/nbboGET /v1/pricing/:marketHashName5 min read - Prices & quotesIntermediate
How to estimate what a CS2 skin is really worth
Estimate what a CS2 skin is really worth: combine NBBO, recent history, and a suggested list price with confidence scores instead of one market's number.
GET /v1/recommendations/:marketHashNameGET /v1/nbbo6 min read