How to Build a CS2 Marketplace Comparison Site
Updated
Build a CS2 marketplace comparison site by using cs2.sh's
GET /v1/schemaas the item catalog andGET /v1/prices/latestas a backend-cached price table keyed by the samemarket_hash_name. Render current asks, bids, order counts, freshness, and liquidity for BUFF, Youpin, CSFloat, Skinport, Steam, and C5Game. Keep the API key and full snapshots on the server.
Scope: This is a broad, high-level v0 guide, not a complete application. cs2.sh is designed as a flexible market-data layer for whatever you want to build on top of it, so adapt the implementation to your own product, strategy, and integrations.
This architecture supports searchable item pages, cheapest-listing tables, marketplace comparisons, variant pages, and filters for wear, rarity, collection, price, and liquidity without maintaining a separate identifier map for every source.
Use one catalog identity
GET /v1/schema returns the item catalog keyed by market_hash_name, including display metadata, images, wears, float limits, collections, rarities, marketplace ids, tradability, and variants. Store the returned generation_id with your local catalog and replace the catalog when that identifier changes.
Use market_hash_name as the internal join key and stable variant version codes for Doppler, Gamma Doppler, and Case Hardened pages. Marketplace ids are attributes of the catalog record, not primary keys for your application.
This removes a common source of broken comparisons: joining a BUFF id, a Youpin id, and a marketplace display name that refer to different wears or variants.
Cache the price snapshot on the backend
GET /v1/prices/latest returns every tracked item across all six marketplaces. Fetch and decompress it from a scheduled backend worker, validate the response, and atomically replace the last good local snapshot. Serve item pages and search results from that local copy instead of requesting the upstream API during every page view.
Most prices update about every five minutes, depending on the source. Polling faster does not make a marketplace update faster. Use the updated_at and collected_at inside each source object to show freshness; response_time describes the assembled API response, not the age of every price in it.
Keep the previous valid snapshot when a refresh fails. A transient 503 should make the site show older data with its real timestamps, not clear every price or replace it with zero. GET /health can support an operator status view, but source timestamps remain the evidence shown to users.
Design one truthful comparison row
For each marketplace, display only fields it actually supplies:
| Source | Sell listings | Buy orders | Extra context |
|---|---|---|---|
| BUFF | ask, ask_volume |
bid, bid_volume |
Variant prices and separate float/fade ranges |
| Youpin | ask, ask_volume |
bid, bid_volume |
Variant prices |
| CSFloat | ask, ask_volume |
bid |
No generic bid_volume |
| Skinport | ask, ask_volume |
None | max_ask, mean_ask, median_ask, rolling sale windows |
| Steam | ask, ask_volume |
bid, bid_volume |
Steam Wallet value, no variants |
| C5Game | ask, ask_volume |
bid |
No bid_volume |
The default buy ranking can sort non-stale cash-market asks from low to high. The default sell ranking can sort non-stale cash-market bids from high to low. Keep those rankings separate. An ask and a bid answer different questions, and the lowest ask is not automatically the best landed price after marketplace fees or payment costs.
Steam belongs in its own settlement context because its balance is Steam Wallet funds. A user can still compare Steam activity with cash marketplaces, but the interface should not label one Steam dollar as one withdrawable dollar.
Handle variants as separate markets
Current-price base items have dense source objects: once an item has data, all six source keys can be present with unavailable fields set to null. Variant maps are sparse: only sources with data for that exact phase or tier appear.
Build variant routes from the schema rather than inventing them from price data. On a Phase 2 page, render only Phase 2 source values. Falling back to the base Doppler price produces a complete-looking table that compares different products.
Steam should not appear as a phase-level source. The Steam Community Market does not distinguish Doppler or Case Hardened variants.
Add liquidity to search and ranking
Fetch GET /v1/liquidity/items daily and join it to the catalog. The response supplies a liquidity bucket and estimated sale time for each covered item and supported variant.
Useful product features include:
- filtering out
unknownor illiquid items from a default arbitrage view; - sorting two similarly priced skins by likely sale time;
- labeling a cheap listing on a thin market with its liquidity context;
- letting users browse a variant independently from its base item's activity.
Do not present estimated sale time as a promise. It assumes a competitive listing price and reflects a daily classification based on recent sale activity.
Separate market data from marketplace actions
A comparison page needs destination links or account integrations to turn a row into an action. cs2.sh provides normalized market data and marketplace ids where available; it does not authenticate users with each marketplace, purchase an asset, list an item, expose account balances, or calculate account-specific fees.
Build outbound marketplace links and trade actions through the relevant official or authorized interface. Recheck the exact listing before sending a user to buy because a snapshot's lowest listing may already have changed.
Minimum production data model
Keep three independently replaceable datasets:
catalog: generation_id, market_hash_name, metadata, marketplace_ids, variants
prices: market_hash_name, variant_version, source, ask, bid, volumes, timestamps
liquidity: run_date, market_hash_name, variant_version, bucket, estimated_sale_timeThis split prevents a price refresh from rewriting the catalog and prevents a daily liquidity update from making current prices look newly collected. It also gives each page a clear failure mode: catalog unavailable, price source stale, or liquidity temporarily missing.
References: schema, latest prices, liquidity, health, and cross-market comparison rules.