CS2 Item Tracker is an automated trading bot for the CSFloat marketplace. It monitors up to 40 CS2 items on a schedule, analyzes their cheapest listing against recent sale data, and fires a BUY signal when a listing is cheap enough to buy, hold through the 8-day trade lock, and resell at a profit.
The bot also supports fully automated buying (Auto-Buy) and automated buy order placement (Buy Orders), both are disabled by default and require you to manually enable them.
Contributions are welcome. If you find a bug or have an idea to improve the bot:
- Open an Issue to report bugs or suggest features
- Open a Pull Request if you want to build something yourself, fork the repo, make your changes, and submit it for review
All skill levels welcome. If you're not sure where to start, open an Issue and describe what you have in mind.
1. Clone the repo
git clone https://github.com/Z1000k/cs2-item-tracker.git
cd cs2-item-tracker
2. Install dependencies
pip install -r requirements.txt
3. Create your .env file
Copy the example and fill in your own keys:
cp .env.example .env
Then open .env and add your values:
CSFLOAT_API_KEY=your_key_here
TELEGRAM_BOT_TOKEN=your_token_here # optional — leave blank if you don't want Telegram alerts
TELEGRAM_CHAT_ID=your_chat_id_here # optional
To get your CSFloat API key: you need a Steam account with Steam Guard enabled. Connect it to csfloat.com via Steam login, then go to Settings → API to generate your key.
4. Run it
python main.py
Opens the dashboard at http://localhost:8000. Start and stop the bot from there using the Start Bot / Stop Bot buttons.
Every CSFloat trade has two fees:
- 2% CSFloat sale fee, deducted from what the buyer pays
- 2% CSFloat withdrawal fee, deducted when you move money out
Combined net multiplier: 0.9604
This means if you sell at $1.00, you actually receive $0.9604 in your pocket after both fees.
Example: Buy at $0.91 → sell at $1.00 → receive $0.9604 → profit = $0.0504 ≈ 5.5%
To break even you need to sell at: buy_price / 0.9604
The dashboard is divided into four tabs across the top:
- CSFloat Market, the main monitoring table
- Trade Journal, track your active positions
- SOLD, closed trade history with P&L
- ITEMS, manage which items the bot monitors
Live CSFloat wallet balance, updated every cycle. Available is what you can spend. Frozen is locked in open buy orders.
Globally enables or disables the auto-buy system. Starting state is OFF. See the Auto-Buy section below for details.
Globally enables or disables the buy order bot. Starting state is OFF. See the Buy Orders section below for details.
Real-time API rate limit consumption:
- Sales API: HIT/MISS counts for the current graph fetch cycle, plus remaining calls out of the 500/day limit.
- Listings API: Remaining calls out of the 200/hour limit, plus time until the hourly window resets.
HIT = response was served from Cloudflare cache (free, uses no quota). MISS = a real API call was made.
Shows the most recent auto-buy attempts with item name, price, and outcome.
Shows all buy orders currently placed by the bot, with item name, price, and when they were placed.
Enter a buy price, quantity, and target profit % → calculates the sell price you need to hit that profit after fees, total P&L in dollars, and True P&L after both fees.
Enter a buy price, sell price, and quantity → calculates your gross received, P&L after 2% sale fee, and True P&L after both the 2% sale and 2% withdrawal fees.
The item name. Clicking it opens CSFloat search for that item filtered to buy-now listings, sorted by lowest price.
Item names are color-coded by their fetch group:
- Cyan, Group A (first half of your active items)
- Orange, Group B (second half)
If you have 20 or fewer active items, all items are Group A and fetched every cycle.
The lowest buy-now price currently listed on CSFloat for this item, fetched live every cycle.
The percentage in brackets compares the listing price to CSFloat's fair value (Ref Price):
- Green (
-2.3%) — listing is below fair value. Good. - Red (
+1.5%) — listing is above fair value. Expensive.
The highest open buy order price for this item on CSFloat, with the number of units at that price in brackets.
Color indicates room to place a competing order:
- Green, the top buy order is below Target Buy, meaning there is room to place a bot order
- Red, the top buy order is at or above Target Buy, no room exists
The exact price the cheapest listing needs to drop to for the signal to fire as BUY.
Calculated as: Effective 24H Sales Avg × (1 − threshold%)
Where threshold depends on the Effective 24H Sales Avg value:
| Effective 24H Avg | Required Discount |
|---|---|
| Under $0.50 | 14% |
| $0.50 and above | 4% |
The most recent completed sale on CSFloat for this item.
Format: $X.XX Xh ago ×N
- Price, what the item actually sold for
- Time ago, how long since that sale
- ×N, if multiple units sold at the same price within 5 minutes of the most recent sale, the count is shown
Updated on every graph fetch cycle. Survives restarts, persisted to latest_sales_cache.json.
The average price of real completed sales on CSFloat in the last 24 hours, plus the number of sales in brackets.
If today has no sales yet, falls back to the most recent previous day that had sales, shown with a "prev" label instead of a sale count.
This value is also the reference the signal uses. See How The Signal Works below.
Resets at midnight UTC.
CSFloat's own estimated fair value for the item (predicted_price or base_price from the listing API response). Purely informational, not used in signal calculations.
Shown with a delta indicating how the cheapest listing compares to it:
-$0.19(green), listing is cheaper than fair value+$0.10(red), listing is more expensive than fair value
Average price of real completed sales over the last 7 days, weighted by volume.
Average price of real completed sales over the last 30 days, weighted by volume. Used as the baseline for the Market Trend calculation.
Whether the item's price is moving up, down, or flat. Uses three data points — 24H, 7D, and 30D averages.
Confirmation logic:
| Structural (7D vs 30D) | Momentum (24H vs 7D) | Result |
|---|---|---|
| 7D > 30D by more than 3% | 24H ≥ 7D | ↑ Rising, trend confirmed |
| 7D > 30D by more than 3% | 24H < 7D | → Stable, momentum fading |
| 7D < 30D by more than 3% | 24H ≤ 7D | ↓ Falling, trend confirmed |
| 7D < 30D by more than 3% | 24H > 7D | → Stable, possible reversal |
| 7D within ±3% of 30D | anything | → Stable |
If no 24H data is available, falls back to 7D vs 30D comparison only.
| Display | Color | Meaning |
|---|---|---|
| ↑ Rising | Green | Confirmed uptrend |
| → Stable | Yellow | Flat or mixed signals |
| ↓ Falling | Red | Confirmed downtrend |
A Falling trend blocks Auto-Buy even if the signal is BUY.
The main output of the bot.
| Signal | Color | Meaning |
|---|---|---|
| BUY | Green | Listing is cheap enough vs Effective 24H Sales Avg |
| PASS | Red | Not a good deal |
Two numbers are shown next to the label:
- Left number (
+5.2%), how far the listing is below the Effective 24H Sales Avg. Green = hits the threshold. Orange = within 70% of threshold. Red = far off. - Right number in brackets (
(4%)) — the threshold required for this item's price tier.
Shows whether this item is currently armed for automatic purchasing.
| Display | Color | Meaning |
|---|---|---|
| ARMED | Green | All conditions met, will auto-buy if global toggle is ON |
| IDLE | Grey | Conditions not met |
An item is ARMED when:
- Signal = BUY
- Market Trend = Rising or Stable
- Use today's 24H Sales Avg if sales exist today
- If today has no sales, fall back to the most recent previous day that had sales
This is the reference price the signal uses — it reflects where the item has actually been trading recently.
| Effective 24H Avg | Required Discount |
|---|---|
| Under $0.50 | 14% |
| $0.50 and above | 4% |
discount = (effective_24h_avg − listing_price) / effective_24h_avg × 100
discount >= threshold→ BUYdiscount < threshold→ PASS
target_buy = effective_24h_avg × (1 − threshold / 100)
This is the dollar price shown in the Target Buy column. If the cheapest listing hits or goes below this price, the signal fires.
With more than 20 active items, the bot splits them into two groups to stay within the API rate limit:
- Group A, first half of your active items (
ceil(n/2)) - Group B, second half
Groups alternate each cycle: even cycle = Group A, odd cycle = Group B. The dashboard always shows all rows, items not in the current group keep their last known values until their group runs again.
With 20 or fewer items, all items are fetched every cycle as a single group.
When enabled, the bot automatically purchases qualifying listings the moment a BUY signal fires during a cycle.
The Auto-Buy button in the header enables or disables auto-buying for all items. Default: OFF.
- Signal = BUY
- Market Trend ≠ Falling
- Live balance ≥ listing price
- Fetches all buy-now listings at or below Target Buy price
- Checks your live balance before each purchase
- Buys up to the quantity limit for the item's price tier
| Effective 24H Avg | Max Units | Delay Between Buys |
|---|---|---|
| Under $1.00 | 50 | 0.5 seconds |
| $1.00 – $4.99 | 20 | 0.2 seconds |
| $5.00+ | 10 | None |
Every auto-buy attempt is logged to auto_buys.csv with timestamp, item, price, market trend, signal, and outcome. A Telegram notification is sent per purchase if configured.
The buy order bot automatically places and manages buy orders on CSFloat.
The Buy Orders button in the header enables or disables the system. Default: OFF.
After every listing cycle, the bot:
- Reads the highest existing buy order for each item
- Sets
desired_price = top_bid + $0.01 - If no competition exists, uses
target_buydirectly - Places a buy order at
desired_priceif it's belowtarget_buy - If
desired_price > target_buy- no room, cancels any existing bot order and skips
- Top bid moved up and left no room below Target Buy
- The desired price changed, old order cancelled, new one placed
Active bot orders are saved to bot_orders.json and survive restarts.
Buy orders use a separate pool - 20 calls per rate window. The bot spaces calls 0.3s apart, which fits within one window.
Manual trade tracker for your active positions.
Fill in Item Name, Quantity, Price Per Item, Date Bought, and Release Date. Press Add Trade.
| Column | Meaning |
|---|---|
| Item | Item name |
| Price Bought | Price paid per unit |
| Total Paid | Price × quantity |
| Date Bought | When you bought it |
| Date Released | When the trade lock expires |
| Tradeable In | Countdown to trade lock expiry |
| Top Buy Order | Highest buy order + P&L if sold at that bid |
| Cheapest Listing | Current cheapest listing + P&L if sold now |
| Item Sold Price | Enter your actual sale price to move to SOLD |
Full history of closed trades.
| Column | Meaning |
|---|---|
| Item | Item name |
| Date Bought | When purchased |
| Date Released | When trade lock expired |
| Date Sold | When you sold |
| Price Bought | Purchase price per unit |
| Item Sold Price | What you actually sold for |
| Received Gross | Sold price after 2% CSFloat sale fee |
| P&L 2% | Profit/loss vs buy price after sale fee only |
| True P&L 4% | Profit/loss vs buy price after both fees (the real number) |
Totals bar at the bottom shows cumulative P&L 2% and True P&L 4% across all sold trades.
Manage which items the bot monitors.
- Max 40 active items enforced
- Changes take effect on the next cycle, no restart needed
- Toggle checkboxes and press Apply to save
- Each item shows its Drop Status (ACTIVE = still dropping in CS2 / DISCONTINUED = retired) and current monitor state
Changes write to cases_enabled.json. If that file doesn't exist, the bot falls back to TARGET_ITEMS in config.py.
| Endpoint | Limit | Usage |
|---|---|---|
/listings |
200 calls/hour | One call per item per cycle |
/history/*/graph |
500 calls/day | One call per item per graph fetch |
/buy-orders (place/cancel) |
20 calls/window | One call per item after each cycle |
Dynamically calculated to stay within the 200/hour listings limit:
interval = (group_size + 5) × 3600 / 200
Where group_size = total items if ≤ 20, or ceil(n/2) if > 20.
With 40 items (20 per group): (20 + 5) × 3600 / 200 = 450 seconds (~7.5 minutes)
Runs after every listing cycle, same cadence as the listing cycle. Fetches both price history and latest sale for every active item. Most responses come back cached from Cloudflare (HIT = free, uses no quota).
All data is stored in sniper.db (SQLite):
| Table | Contents |
|---|---|
price_history |
Every cycle snapshot of fair value and listing price per item |
sales_history |
Daily real sale count + average price per item |
trades |
Manual trade records |
purchases |
Auto-buy history |
active_orders |
Current open buy order records |
| File | Contents |
|---|---|
sniper.db |
Main SQLite database |
latest_sales_cache.json |
Most recent completed sale per item - survives restarts |
bot_orders.json |
Active buy orders placed by the bot |
last_cycle.json |
Cycle counter and timestamps |
fair_delta_cache.json |
Last recorded fair value change per item |
cases_enabled.json |
Active item list |
auto_buys.csv |
Full auto-buy log with outcomes |
[Bot] Cycle #1 | Group A | 20 items | 14:22:01
[Bot] Listings fetched in 4.3s
[Bot] Fetching buy orders (20 items)...
[Bot] Buy orders done in 11.3s | 20/20 populated
[BUY] Dreams & Nightmares Case | CL: $1.31 | TB: $1.34 | BO: $1.30 x3 (+$0.03 room) | +5.2% (thr 4%)
[Bot] Cycle complete in 15.8s | 1 BUY signal(s)
[Bot] Graph fetch done | HIT: 17 MISS: 3 | rem 454/500
[Bot] Next check in 450s.
| Field | Meaning |
|---|---|
| CL | Cheapest listing price |
| TB | Target Buy price |
| BO | Highest buy order price, quantity, and room to your TB |
| Signal | Discount % vs threshold |
When you see BUY:
- Check Market Trend - Rising or Stable is better. Falling means prices are sliding.
- Check the Signal Score - How far above threshold?
+5.2% (4%)barely cleared.+9.0% (4%)is a stronger buy. - Check 24H Sales Avg - Is the listing below today's actual sale average? Confirms it's genuinely cheap right now.
- Check Latest Sales - What did the last sale go for? If it sold for $1.45 an hour ago and this listing is $1.30, that's a real gap.
- Check Top Buy Order - Is it green? If someone else is already hunting this item their order is sitting just below your target.
Best setup: BUY + Rising/Stable trend + listing below 24H avg + recent sales well above listing price + green Top Buy Order.
| Thing | Value |
|---|---|
| Trade lock after purchase | 8 days |
| Fee multiplier | 0.9604 (2% sale + 2% withdrawal) |
| Max active items | 40 |
| Items per group cycle | ceil(n/2) when > 20, all items when ≤ 20 |
| Listing cycle interval | ~450s (~7.5 min) per group |
| Graph + Latest Sales refresh | Every listing cycle |
| Listings rate limit | 200 calls/hour |
| Graph/Sales rate limit | 500 calls/day (shared) |
| Buy orders rate limit | 20 calls/window |
| 24H Avg resets | Midnight UTC |
Last updated: May 2026