CS2 ESP wallhack showing enemy positions through walls

CS2 ESP & Wallhack Development — Complete 2026 Tutorial

March 18, 2026 · Counter Strike

ESP (Extra Sensory Perception) is the most popular cheat type in CS2 — and often the first feature new cheat developers build. This tutorial walks through the complete process of creating a CS2 ESP from reading the entity list to rendering boxes on screen.

CS2 ESP development with entity overlay

Understanding Source 2's Entity System

CS2 uses a handle-based entity system. The key difference from CS:GO is that player data is split between two entities:

  • CCSPlayerController — Contains player metadata: name, team, connected state, and the pawn handle
  • CCSPlayerPawn — The physical player in the world: position, health, bones, weapons

Walking the Entity List

struct PlayerInfo {
    Vector3 position;
    Vector3 headPosition;
    int health;
    int armor;
    int team;
    std::string name;
    bool isAlive;
};

std::vector<PlayerInfo> GetPlayers() {
    std::vector<PlayerInfo> players;
    uintptr_t entityList = mem.Read<uintptr_t>(client + offsets::dwEntityList);

    for (int i = 1; i < 64; i++) {
        // Get controller from entity list
        uintptr_t listEntry = mem.Read<uintptr_t>(entityList + 0x8 * (i >> 9) + 0x10);
        if (!listEntry) continue;

        uintptr_t controller = mem.Read<uintptr_t>(listEntry + 0x78 * (i & 0x1FF));
        if (!controller) continue;

        // Read team and pawn handle
        int team = mem.Read<int>(controller + offsets::m_iTeamNum);

        // Resolve pawn
        uint32_t pawnHandle = mem.Read<uint32_t>(controller + offsets::m_hPlayerPawn);
        uintptr_t pawnEntry = mem.Read<uintptr_t>(
            entityList + 0x8 * ((pawnHandle & 0x7FFF) >> 9) + 0x10);
        if (!pawnEntry) continue;

        uintptr_t pawn = mem.Read<uintptr_t>(pawnEntry + 0x78 * (pawnHandle & 0x1FF));
        if (!pawn) continue;

        int health = mem.Read<int>(pawn + offsets::m_iHealth);
        if (health <= 0) continue;

        // Get position from game scene node
        uintptr_t sceneNode = mem.Read<uintptr_t>(pawn + offsets::m_pGameSceneNode);
        Vector3 pos = mem.Read<Vector3>(sceneNode + offsets::m_vecAbsOrigin);

        // Get head bone position
        uintptr_t boneArray = mem.Read<uintptr_t>(sceneNode + offsets::m_modelState + 0x80);
        Vector3 headPos = mem.Read<Vector3>(boneArray + 6 * 32);

        players.push_back({ pos, headPos, health,
            mem.Read<int>(pawn + offsets::m_ArmorValue), team, "", true });
    }
    return players;
}

World to Screen Conversion

To draw ESP boxes, you need to convert 3D world coordinates to 2D screen positions using the view matrix:

// View matrix is at client.dll + dwViewMatrix
float viewMatrix[16];
mem.Read(client + offsets::dwViewMatrix, viewMatrix, sizeof(viewMatrix));

bool WorldToScreen(const Vector3& world, Vector2& screen) {
    float w = viewMatrix[12] * world.x + viewMatrix[13] * world.y
            + viewMatrix[14] * world.z + viewMatrix[15];

    if (w < 0.001f) return false;

    float invW = 1.0f / w;
    screen.x = (screenWidth / 2.0f) + (viewMatrix[0] * world.x + viewMatrix[1] * world.y
              + viewMatrix[2] * world.z + viewMatrix[3]) * invW * (screenWidth / 2.0f);
    screen.y = (screenHeight / 2.0f) - (viewMatrix[4] * world.x + viewMatrix[5] * world.y
              + viewMatrix[6] * world.z + viewMatrix[7]) * invW * (screenHeight / 2.0f);

    return true;
}
CS2 ESP box rendering with WorldToScreen projection

Drawing Box ESP

The most common ESP type — a 2D box around each player calculated from their feet and head positions:

void DrawPlayerESP(const PlayerInfo& player) {
    Vector2 screenFeet, screenHead;

    if (!WorldToScreen(player.position, screenFeet)) return;
    if (!WorldToScreen(player.headPosition, screenHead)) return;

    float height = screenFeet.y - screenHead.y;
    float width = height / 2.4f;  // CS2 player aspect ratio

    // Color based on team (CT = blue, T = red)
    Color boxColor = (player.team == 3) ? Color::Blue : Color::Red;

    // 2D cornered box (less obvious than full box)
    float cornerLen = height * 0.2f;
    DrawCornerBox(screenHead.x - width / 2, screenHead.y, width, height, cornerLen, boxColor);

    // Health bar (left side)
    float healthFrac = player.health / 100.0f;
    Color healthColor = LerpColor(Color::Red, Color::Green, healthFrac);
    DrawFilledRect(screenHead.x - width / 2 - 5, screenHead.y + height * (1.0f - healthFrac),
                   3, height * healthFrac, healthColor);
}

Glow Wallhack (Internal Only)

CS2 has a built-in glow system you can abuse. By modifying m_Glow properties on the player pawn, you can enable Valve's own glow rendering:

// Enable glow on enemy pawns (internal cheat only)
// m_Glow is a component on CCSPlayerPawn
mem.Write<int>(pawn + offsets::m_Glow + offsets::m_iGlowType, 3);
mem.Write<int>(pawn + offsets::m_Glow + offsets::m_glowColorOverride, 0x000000FF); // Red ABGR
mem.Write<bool>(pawn + offsets::m_Glow + offsets::m_bGlowing, true);
💡 External vs Internal: External ESPs read memory from a separate process and draw using an overlay (DirectX/GDI). Internal ESPs inject into cs2.exe and hook the rendering pipeline. External is safer but has slight delay; internal is instant but higher detection risk.

Skeleton ESP

For maximum information, draw lines between bones to show the exact player pose:

// CS2 skeleton bone connections
const int BONE_CONNECTIONS[][2] = {
    {0, 2},    // pelvis -> spine
    {2, 4},    // spine -> spine1
    {4, 5},    // spine1 -> neck
    {5, 6},    // neck -> head
    {4, 8},    // spine1 -> left shoulder
    {8, 9},    // left shoulder -> left elbow
    {9, 11},   // left elbow -> left hand
    {4, 13},   // spine1 -> right shoulder
    {13, 14},  // right shoulder -> right elbow
    {14, 16},  // right elbow -> right hand
    {0, 22},   // pelvis -> left hip
    {22, 23},  // left hip -> left knee
    {23, 24},  // left knee -> left ankle
    {0, 25},   // pelvis -> right hip
    {25, 26},  // right hip -> right knee
    {26, 27},  // right knee -> right ankle
};

void DrawSkeleton(uintptr_t boneArray) {
    for (auto& [from, to] : BONE_CONNECTIONS) {
        Vector3 boneFrom = mem.Read<Vector3>(boneArray + from * 32);
        Vector3 boneTo = mem.Read<Vector3>(boneArray + to * 32);
        Vector2 screenFrom, screenTo;
        if (WorldToScreen(boneFrom, screenFrom) && WorldToScreen(boneTo, screenTo))
            DrawLine(screenFrom, screenTo, Color::White, 1);
    }
}

🎯 Ready to Dominate CS2?

Browse verified, undetected CS2 cheats from trusted developers on CheatBay. Every cheat comes with reviews, virus scans, and money-back guarantee.

Browse CS2 Cheats →

Anti-Detection Tips for ESP Development

  • Limit render distance — Don't draw ESP for players 200+ meters away
  • Use visible-only mode — Change color when enemy is actually visible vs behind wall
  • Stream-proof overlay — Use window flags that OBS/shadowplay won't capture
  • Randomize draw order — Don't always process entities in the same order

💰 Turn Your CS2 Skills Into Income

Are you a developer who knows Source 2 inside out? CheatBay lets you sell your cheats directly to players — with built-in license verification, automatic crypto payments, and a growing community of buyers.

Sellers on CheatBay earn $500–$5,000+/month from subscriptions alone. No middlemen, no revenue share on your first $1,000.

Start Selling Your Cheats →

Ready to Level Up?

Browse verified, undetected cheats on CheatBay — or start selling your own and earn crypto.

Browse Cheats Start Selling

Related Guides