typedef@hakkionur_

CS2 Smurf Detection (Faceit)

Smurfing is when a strong player jumps on a new account and farms lower lobbies. This project pulls Faceit CS2 stats and recent matches, then outputs a simple Smurf Score (0–100) with the receipts: per-metric bars and plain-English flags. It’s a lightweight API.

Goal

Build a fast system that helps spot suspicious accounts using real match data.

  • Fetch player + match data from Faceit
  • Derive a few readable signals
  • Combine them into a stable 0–100 score
  • Explain the score with flags

Architecture

API (Cloudflare Worker and FACEIT API)
Nickname → player_id, fetch stats + recent matches, compute features, return JSON.

Frontend
Calls the API and renders score, metrics, flags, and a recent matches table.

Pipeline


GET /api/analyze?player=<nickname>

1) resolve player id
2) fetch lifetime stats (FACEIT CS2)
3) fetch recent matches (last ~20)
4) fetch per-match stats (subset for features)
5) compute signals → score + flags
6) return JSON

Signals

v1 is intentionally boring: a weighted sum of interpretable signals. Boring is good.

Low match count: fresh account suspicion
K/D and win rate: dominance signals
Headshot %: mechanical skill signal
Win streak: short-term domination
Recent spike: recent performance above lifetime baseline

Scoring

Each rule adds points. The total is clamped to 0–100. Nothing hidden, nothing mystical.


// sketch
score = 10

if matches_played < 50: score += 25
if kd >= 1.30:          score += 30
if win_rate >= 60:      score += 20
if headshot_pct >= 55:  score += 15

if winstreak >= 5:      score += 15
if recent_kd - lifetime_kd >= 0.30: score += 20

score = clamp(score, 0, 100)

Output

The API returns UI-ready JSON: headline score, raw stats, normalized metric bars, and flags that explain the result.


{
  "smurf_score": 72,
  "win_rate": 61.4,
  "kd_ratio": 1.42,
  "matches_played": 38,
  "metrics": { "headshot": {"raw":"58%","norm":85} },
  "flags": [
    {"level":"high","title":"Low Match Count","description":"Fresh account + strong stats."}
  ]
}

How to Read a High Score

Example
• Matches: 38
• Lifetime K/D: 1.42
• Recent K/D spike
• Win streak: 6

Interpretation: small sample + consistent dominance + spike = suspicious.

Validation

  • Sanity: legit high-level accounts shouldn’t always score high
  • Edge cases: low matches but average stats should stay moderate
  • Stability: score shouldn’t swing wildly between runs
  • Explainability: flags should match what a human would point at

Visuals

Since v1 is rules, visuals are about insight: score distribution, feature contributions, and recent vs lifetime comparisons.

Smurf Score
Fig 1. Account Banned from FACEIT for Smurfing vs Smurfing Score

Smurf Score
Fig 2. My account (not smurfing ofc) vs Smurfing Score

Wrap-up

This is a practical baseline: fast, cheap, explainable. If it’s wrong, it’s wrong in a way you can actually fix.

View Source on GitHub