The Browser Game Anti-Cheat Problem
Desktop games like Valorant or CS2 can install kernel-level anti-cheat drivers that monitor client processes. Browser games have no such option — JavaScript runs in a sandboxed browser environment that we can't monitor at the OS level, and we wouldn't have permission to do so anyway.
This means all VvW anti-cheat is server-side. Every action a player takes passes through our API. If we do our job right, what happens on the client is irrelevant — the server will reject invalid actions regardless of what the client sends.
Layer 1: Server-Side State Authority
The most fundamental anti-cheat principle: the server owns all game state. The client displays what the server says exists. The client can never grant itself resources, XP, gold, or abilities — it can only request actions from the server, and the server validates whether those actions are legal.
Examples of what this means in practice:
- A player can't modify their browser to show 10,000 AP — their actual AP is stored server-side and validated before any AP-consuming action executes
- A player can't inject JavaScript to add gold to their account — the gold balance is computed from server-side transaction records
- A player can't modify their combat stats client-side — combat calculations run entirely on the server using database character records
This seems obvious but it's not universal — many older browser games stored game state in browser cookies or localStorage that could be edited. We store nothing authoritative client-side.
Layer 2: Rate Limiting by Action Type
The most common cheating attempt in browser MMOs is action flooding: a bot that sends hundreds of hunt/attack/quest-complete requests per minute, far faster than a human can click. Rate limiting per action type is our second defense layer.
We maintain separate rate limit buckets per user per action category:
- Hunt requests: Max 20/minute per account (a human clicking fast might hit 8–10/min)
- Battle initiations: Max 5/minute (combat takes time to read and process)
- Auction House actions: Max 30/minute (listing browsing is faster)
- API requests overall: Max 200/minute hard cap before temporary lockout
Rate limits are stored in Redis with sliding window counters. A player hitting a rate limit gets an HTTP 429 with a Retry-After header — normal slowdown, not a ban. Repeated and sustained rate limit violations trigger the behavioral analysis layer.
Layer 3: Behavioral Analysis
Bots have distinctive behavioral patterns that humans don't. Our behavioral analysis module runs as a background job analyzing player action logs:
Timing regularity: Humans have variable action intervals — 3.2s, 7.8s, 2.1s. Bots are more regular — 4.0s, 4.0s, 4.0s. We compute the coefficient of variation for each player's action timing distribution. Suspiciously low variation (CV < 0.15) flags an account for review.
Session hours: Human players sleep. A player who runs exactly 480 hunt requests between 2am and 6am local time without a single break is statistically anomalous. Our session analysis identifies accounts with continuous 24-hour activity patterns.
Action sequences: Humans explore the game. Bots repeat the optimal sequence. An account that has performed the identical hunt→quest→hunt→quest sequence 10,000 times without any deviation is algorithmically suspicious.
Layer 4: Contextual Validation
Beyond timing, we validate game-contextual logic:
- Can this player complete this dungeon? Their stats must be high enough. Attempts on dungeons far above their tier with inconsistent success rates flag botted accounts (scripts that don't adapt to their character's actual power)
- Is this economic activity plausible? Listing 500 rare items in 10 minutes when the account has 20 hours of total playtime isn't possible through normal play
- Is this IP/device fingerprint associated with previous banned accounts? Persistent cheaters return under new accounts — device and network fingerprinting catches most of these
What We Don't Do (And Why)
We intentionally don't use CAPTCHAs on regular gameplay actions — they punish legitimate players more than bots (which increasingly solve CAPTCHAs automatically). We use CAPTCHAs only on account registration and password reset, where the friction is acceptable.
We don't auto-ban on first detection. Our system generates suspicion scores. Accounts above threshold go to a manual review queue. A human makes the ban decision. False positives — banning real players — are worse for the game than letting a bot run an extra 24 hours while we verify.
⚙️ Anti-Cheat Stack Summary
- Server-side authority: FastAPI + PostgreSQL — all game state server-side, no authoritative client state
- Rate limiting: Redis sliding window counters, per-action-type buckets
- Behavioral analysis: Python background job, timing CV + session analysis + sequence repetition scoring
- Device fingerprinting: FingerprintJS Pro (server-side validation) + IP reputation
- Manual review queue: Internal admin panel, human decision on bans
Results So Far
Since launching the behavioral analysis layer in Q1 2026, we've identified and banned 340 bot accounts. More importantly, the presence of effective anti-cheat has reduced the incentive to cheat — our Auction House economy is stable, leaderboards are credible, and real players don't feel like they're competing against automation. That's the outcome that matters.