Guides

Anti Cheat Explained

Howdy,

Today you will learn about The West's anti cheat measure, method and demonstration.
Check the end of the article to see a video demonstrating how the anti-cheat is getting custom scripts at runtime.
The West's anti-cheat system employs a 3-layer detection method that monitors your game client in real-time. Every login, the system scans for:

All detection data is permanently logged to a database and linked to your account.

Layer 1: Global Variable Detection

How it works?
Every time you log in, the game captures a snapshot of all global variables in your browser:

JavaScript
Copied!
js
		
// Game's detection code (simplified):
var initVarPos = Object.keys(window).length;  // Initial count

// Later, after scripts load:
var keys = Object.keys(window);
if (keys.length > initVarPos) {
    var newVars = keys.slice(initVarPos);     // Get NEW variables
    Chat.Request.VarDec(newVars);              // Send to server
    
    // Also log to Grafana monitoring:
    newVars.forEach(varName => {
        faro.api.pushLog(['script', varName], {level: 'info'});
    });
}
        
	

What Gets Detected
BAD - Creates global variables:

JavaScript
Copied!
js
		
// These are IMMEDIATELY detected:
GJ = { version: '1.15' };           // ← Detected
window.MyScript = {};               // ← Detected
MyHelper = function() { };          // ← Detected
        
	

GOOD - Uses local scope:

JavaScript
Copied!
js
		
// This is invisible to detection:
(function() {
    'use strict';
    var GJ = { version: '1.15' };   // ← NOT detected (local variable)
    var MyScript = {};               // ← NOT detected
})();
        
	

Example Detection
Script: Gold Jobs Finder v1.15
Detected Variables:

  • GJ (main object)
  • GJlang (language settings)
  • scriptRequest (boolean flag)
  • scriptUp (update checker)
  • sI (setInterval ID for scriptUp loader)

Result: 5 global variables logged => Script identified as "Gold Jobs Finder"

The first 4 variables are found in the main script.
The 5th variable is present in an external script called by the main script (sUp.js).
The game automatically logs ALL global variables to their database, but cannot automatically identify which script they belong to. This is where the admin's script database comes in.
Admin Script Database: Admins maintain a reference database that maps variable signatures to known scripts:
Below you can see an example of a record they have of a script called "TW Gold Jobs Finder".
Important! This is not the exact same structure but something close to it based on their front-end logic.

Json
Copied!
json
		
{
  "Script-1": {
    "name": "TW Gold Jobs Finder",
    "source_url": "https://greasyfork.org/scripts/7226",
    "severity": "HIGH",
    "variables": ["GJ", "GJlang", "scriptRequest", "scriptUp"],
    "css_selectors": ["div#CC_pin_items"],
    "description": "Shows all gold and silver jobs on the map"
  }
}
        
	

The Detection Process:

  • Automatic Collection: When you log in, the game captures all your global variables
  • Pattern Matching: Admins search the database for users whose variables match known script signatures
  • Identification: If your variables match the signature => Script identified

Important Notes:

  • The system cannot automatically know what a variable like GJ means
  • Admins must manually add scripts to their reference database
  • Unknown/new scripts won't be identified until admins add them
  • Scripts with unique variable names are easier to identify

What it means?

  • Popular scripts (Gold Jobs Finder, Duel Warner, etc.) are already in their database
  • Your variables ARE being logged, even if not yet identified
  • Admins can retroactively identify you once they add a script to their database
  • Having generic variable names (like app, helper) makes identification harder


Layer 2: CSS Stylesheet Detection

How it works?
The game monitors document.styleSheets for any new CSS added after page load:

JavaScript
Copied!
js
		
// Game's CSS detection code (simplified):
var styleList = new Set();  // Initial stylesheets

var pushStyles = function() {
    const diff = (new Set(document.styleSheets)).difference(styleList);
    if (!diff.size) return;
    
    const styles = Array.from(diff).slice(0, 4).map(function(sheet) {
        if (sheet.href) {
            // External stylesheet
            return [null, null, null, sheet.href];
        }
        
        // Inline stylesheet - extract rules
        const rules = sheet.cssRules;
        const firstItem = rules.item(0);
        const lastItem = rules.item(rules.length - 1);
        
        return [
            rules.length,                                    // Number of rules
            firstItem ? firstItem.selectorText : null,      // First selector
            lastItem ? lastItem.selectorText : null,        // Last selector
            null
        ];
    });
    
    Chat.Request.StyleDec(styles);  // Send to server
};
        
	

!What Gets Detected
Any CSS you inject is logged:

CSS
Copied!
css
		

        
	

Logged Data:

JavaScript
Copied!
js
		
{
    type: 'inline',
    ruleCount: 3,
    firstSelector: 'div#CC_pin_items',    // ← Unique fingerprint!
    lastSelector: '.goldwindow'
}
        
	

Why CSS Detection Matters:

  • CSS is required for UI scripts - You can't add custom panels/buttons without CSS
  • Unique fingerprints - Class names like .goldenJobs or #CC_pin_items uniquely identify scripts
  • Hard to bypass - CSS must be in the DOM to work, making it unavoidable
  • Even 1 rule = detected - Any injected CSS triggers logging

Example Detection
Script: Gold Jobs Finder (via update script)
Detected CSS:

CSS
Copied!
css
		

        
	

Result: CSS fingerprint #CC_pin_items logged => Matched to Gold Jobs Finder database entry



Layer 3: WebDriver Detection (Python/Selenium)

How it works?
The game sends your WebDriver status directly to their anti-cheat server on every page load:

JavaScript
Copied!
js
		
// From game's initialization code:
Ajax.remoteCall('anti_cheat', 'record_fp', {
    fp: "browser_fingerprint_hash",
    gv: undefined,
    wd: navigator.webdriver  // ← Sent to server!
});
        
	

What Gets Logged:

JavaScript
Copied!
js
		
{
    user_id: 12345,
    timestamp: "2026-01-10 14:30:00",
    browser_fingerprint: "a1b2c3d4e5f6...",
    webdriver: true,  // ← YOU ARE FLAGGED
    
    // Additional fingerprint data:
    canvas_fp: "...",
    webgl_fp: "...",
    screen_resolution: [1920, 1080],
    timezone: -300,
    fonts: [...],
    // ~30 other browser characteristics
}
        
	

Detection accuracy:

  • true = Selenium/Playwright/Puppeteer => DETECTED
  • undefined = Normal browser => Clean
  • false = Rare (some browsers) => Probably clean / false alert

Important Notes:

This is separate from fingerprinting

  • The browser fingerprint (`fp`) identifies your specific browser
  • The WebDriver flag (`wd`) identifies automation
  • Both are sent together to the server
  • Admins can search: "Show all users with `wd: true`

They use Fingerprint2 library

  • Creates a unique hash from ~30 browser characteristics
  • This means they can track you even if you:
    • Clear cookies
    • Use incognito mode
    • Change IP address
  • The fingerprint stays mostly the same unless you change hardware/browser

Python/Selenium Bypass Methods:
The game checks `navigator.webdriver` on line load. To bypass:

Method 1: Undetected ChromeDriver (Easiest):

Python
Copied!
py
		
import undetected_chromedriver as uc

driver = uc.Chrome()
# Sets navigator.webdriver = undefined
# Bypasses many other detection methods
        
	

Method 2: Chrome DevTools Protocol (Before Page Load)

Python
Copied!
py
		
from selenium import webdriver

driver = webdriver.Chrome()

# Execute BEFORE navigating to the page
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        Object.defineProperty(navigator, 'webdriver', {
            get: () => undefined
        })
    '''
})

driver.get("https://the-west.net")
# WebDriver hidden before game's check
        
	

Method 3: Selenium Stealth

Python
Copied!
py
		
from selenium import webdriver
from selenium_stealth import stealth

driver = webdriver.Chrome()

stealth(driver,
    languages=["en-US", "en"],
    vendor="Google Inc.",
    platform="Win32",
    webgl_vendor="Intel Inc.",
    renderer="Intel Iris OpenGL Engine",
    fix_hairline=True
)
        
	


Video demonstration