Appearance
Live Prices WebSocket
This documentation explains how to subscribe to the live price_changed feed — every price update from every marketplace we track, streamed over Socket.IO in one-second batches. It replaces polling get-aggregated-min-prices for use cases that need real-time data.
Connection
The feed runs on the standard Socket.IO protocol (client libraries exist for JavaScript, Python, Go, C#, Java and more — no custom protocol to implement):
| Parameter | Value |
|---|---|
| URL | https://api.csmarketcap.com |
| Path | /sockets |
| Auth | auth: { token: <generated_jwt> } (or query: { token }) |
The token is the same JWT you already use for the REST and GraphQL APIs. For information on how to generate it, please refer to the Authentication Guide.
js
import { io } from "socket.io-client";
const socket = io("https://api.csmarketcap.com", {
path: "/sockets",
auth: { token: "<generated_jwt>" },
});
socket.on("connect", () => {
// subscribe to everything…
socket.emit("prices:subscribe", {}, (ack) => {
console.log(ack); // { subscribed: "all" }
});
// …or to specific marketplaces only (recommended):
socket.emit(
"prices:subscribe",
{ markets: ["buff163", "csfloat"] },
(ack) => console.log(ack), // { subscribed: ["buff163", "csfloat"] }
);
});
socket.on("price_changed", ({ count, events }) => {
for (const event of events) {
// handle the update
}
});
socket.on("connect_error", (err) => {
// invalid / expired token — the reason is in err.message
console.error(err.message);
});python
import socketio
sio = socketio.Client()
@sio.event
def connect():
sio.emit("prices:subscribe", {"markets": ["buff163"]})
@sio.on("price_changed")
def on_prices(frame):
for event in frame["events"]:
pass # handle the update
sio.connect(
"https://api.csmarketcap.com",
socketio_path="/sockets",
auth={"token": "<generated_jwt>"},
)Subscribing
| Event | Payload | Effect |
|---|---|---|
prices:subscribe | {} | Receive every marketplace |
prices:subscribe | { "markets": ["buff163", "csfloat"] } | Receive only the listed marketplaces |
prices:unsubscribe | — | Stop receiving without disconnecting |
Re-sending prices:subscribe replaces the previous filter. Both events accept an acknowledgement callback confirming the active subscription.
Market names match the market_name values used across the rest of the API (buff163, csfloat, skinport, waxpeer, …). The feed carries the same marketplaces as the REST endpoints — internal or inactive markets are not included. The acknowledgement always lists the markets you were actually subscribed to; unavailable names are dropped from it.
The price_changed event
Updates are batched and delivered once per second per subscription:
json
{
"count": 584,
"events": [
{
"market_name": "buff163",
"game_id": 730,
"item_name": "AK-47 | Redline (Field-Tested)",
"price": 31250,
"offers": 143,
"price_locked": 29980,
"change_datetime": "2026-07-13 16:18:34"
}
]
}| Field | Description |
|---|---|
market_name | Marketplace that reported the change |
game_id | 730 CS2, 570 Dota 2, 440 TF2, 252490 Rust |
item_name | Full market hash name |
price | Minimum price for immediately tradable items |
price_locked | Minimum price for trade-locked items (may be absent) |
offers | Listing count on that marketplace (may be absent) |
change_datetime | UTC timestamp of the change |
Usage Notes
- Price values are provided in cents (divide by 1000 to get dollar value) — same convention as the REST API
- The unfiltered stream averages ~650 events per second with bursts far above that; subscribe per-market unless you truly need everything
- One
price_changedframe per second per subscription — an empty second produces no frame - Reconnection and transport fallback (WebSocket → HTTP long-polling) are handled by the Socket.IO client automatically
- Authentication failures surface as
connect_errorwith the reason (Invalid token,Your subscription has expired…); token lifetime is unchanged, so mint a new token and reconnect when it expires - All games flow through one subscription — filter by
game_idclient-side if you only need one