Anti Cheats - Where Do I Start?

Thank you to everyone who contributed to the post! It was kinda hard to decide who to give the solution to: my final picks was CodedJer’s and Ihaveash0rtname’s posts but it eventually came down to Ihaveash0rtname’s posts

For any future readers, I found a really nice post by Reapimus

:bangbang: VERY IMPORTANT :bangbang: Can anyone tell me how I’d actually start making the anti-cheat and if that’s how top games would make an anti-cheat. If you’re answering this specific question, you can quote this (btw thank you for everyone who has already contributed :sunglasses::v:)


As the title suggests, how would I start developing a good SERVER SIDED anti cheat? Many others have asked this question too so I guess I’m also speaking on their behalf.

I know that people who do know how to develop effective anti-cheats don’t usually share their knowledge. And that’s why as someone with no experience; it’s pretty damn dang confusing and practically impossible to create a good anti-cheat.


Now obviously anti cheats depend on the game. Like in [Roblox] Bedwars, their anti-cheat targets stuff like flying, no-clipping, and other stuff that another game’s anti-cheat wouldn’t be focused on.

I’ve seen a whole bunch of posts that provide basic insight into the topic; but none really have helped me understand the topic much.

And before someone asks, yes I’m aware and actively use server sanity checks.


I’m thinking about making a FPS game in the future so that’s what I’ll base the below with. So here’s what I’m kinda needing help with:

List of things I need someone to help explain:

  • Help explaining handshakes
  • How to start creating the anti-cheat
  • How to detect no-clipping
  • How to detect position tampering (like flying)
  • How to go about detecting an injection
  • Pretty dumb question but: would the anti-cheat be in a module script? And if yes, would it be in “OOP style”?
  • More advanced techniques that the big games use

Other stuff:

  • What stuff to give network ownership to the client and what stuff to give to the server

Links to DevForum posts, code snippets, and or explanations (simplify them if you can :smiley:) are the most helpful!

But any sort of insight or help is very much appreciated by me!


Thank you to everyone who shares something :blush::pray:

Are you confident in your “anti-cheat making skills”?

  • Yes
  • No
  • I don’t know

0 voters


Things I’ve learned from this topic so far that I didn’t know before:

  • Handshakes :handshake: (they can yield a lot of false positives if the player lags and it doesn’t ping the server but still should ping every interval of 60 seconds)
  • Dealing with position tampering :round_pushpin:
  • Hacker bait remotes :man_technologist::dollar::x:
  • How to start the anti-cheat (the main goal of the post overall)
10 Likes

Hard to say anything about this without getting jumped by 20 people telling you, you can’t stop hackers. I guess hackers have a fan club now. I would just start with a basic test system. Something that tests values vs what they should be.

7 Likes

My biggest tip: Never rely on the client.

8 Likes

That’s true. I’m not really expecting to keep up with the latest bypasses from the big guys (Synapse X, Krnl, etc).

Just to keep those “NEW EASY INFINITE CASH EXPLOIT WORKING 2023 ROBLOX” people out.

Edit: I said I didn’t want to keep up much, that doesn’t necessarily mean that I didn’t want to protect my future game from Synapse users. Just not all the time

3 Likes

Mhm. I don’t really know what else to say but; yeah this is an essential.

5 Likes

If an exploiter wants to delete any of local scripts you may use 2 local scripts (1 may be used with any in-game mechanics) and the second. When any of the script deleted (any of 2) The method :Destroying will trigger and Kick an exploiter. I don’t know if it would work but it’s as a suggestion.
P.S. It any of 2 should detect script injection.

3 Likes

Correction.

.Destroying is an event and not a method, so use the dot syntax

4 Likes

all ways check the roblox version and kick people using the microsoft version its or a serverside checker, checking every second to see any difference without a remote or any system being runned( this is my thought on this topic)

3 Likes

something like this would stop that in it’s tracks

local transactionCooldown = {}

local function validateTransaction(player, amount)
    if typeof(amount) == "number" and amount >= 0 then
        local currentTime = tick()
        local lastTransactionTime = transactionCooldown[player.UserId] or 0
        if currentTime - lastTransactionTime >= 5 then
            transactionCooldown[player.UserId] = currentTime
            player.Currency = player.Currency + amount
            player:SendNotification("Currency updated: " .. player.Currency)
        else
            warn("Transaction rate limit exceeded for player: " .. player.Name)
        end
    else
        warn("Invalid transaction for player: " .. player.Name)
    end
end

game:GetService("ReplicatedStorage").ValidateTransaction.OnServerEvent:Connect(function(player, amount)
    validateTransaction(player, amount)
end)

Checked out a few videos on this to see what you were talking about. Seem this always comes down to force firing a remote that was set up off a menu (GUI).

Restricted Area
local LockedRoom = game.Workspace.LockedRoom
local RequiredItemName = "Key"

LockedRoom.Touched:Connect(function(hit)
    local character = hit.Parent
    local player = game.Players:GetPlayerFromCharacter(character)

    if player then
        if not hasRequiredItem(player) then
            player:Kick("You need a key to enter this room.")
        end
    end
end)

function hasRequiredItem(player)
    local character = player.Character
    if character then
        local backpack = player.Backpack
        local characterItems = character:GetChildren()
        for _, item in pairs(characterItems) do
            if item.Name == RequiredItemName then
                return true
            end
        end
        if backpack then
            local backpackItems = backpack:GetChildren()
            for _, item in pairs(backpackItems) do
                if item.Name == RequiredItemName then
                    return true
                end
            end
        end
    end
    return false
end

Different cash trap
local MaxScoreIncreasePerSecond = 100

local function detectSuspiciousScoreIncrease(player)
    local lastScore = player.leavingScore or 0
    local currentTime = tick()
    local timeElapsed = currentTime - player.joinTime

    if timeElapsed > 0 and (player.Score - lastScore) / timeElapsed > MaxScoreIncreasePerSecond then
        player:Kick("Suspicious behavior detected.")
    end

    player.leavingScore = player.Score
end

game.Players.PlayerAdded:Connect(function(player)
    player.joinTime = tick()
end)

game.Players.PlayerRemoving:Connect(function(player)
    detectSuspiciousScoreIncrease(player)
end)

Speed trap
local MaxMovementSpeed = 100

local function detectSuspiciousMovement(player)
    local character = player.Character
    if character then
        local humanoid = character:FindFirstChild("Humanoid")
        if humanoid then
            local currentSpeed = humanoid.WalkSpeed

            if currentSpeed > MaxMovementSpeed then
                player:Kick("Suspicious behavior detected.")
            end
        end
    end
end

game.Players.PlayerAdded:Connect(function(player)
    player.CharacterAdded:Connect(function(character)
        detectSuspiciousMovement(player)
    end)
end)

Hacker bait remote
-- Server-side script

local BaitRemote = Instance.new("RemoteFunction")
BaitRemote.Name = "AddCoins"
BaitRemote.Parent = game.ServerScriptService

local function checkForBan(player)
    local shouldBan = false 

    if shouldBan then
        player:Kick("You have been banned for unauthorized actions.")
    end
end

BaitRemote.OnServerInvoke = function(player)
    checkForBan(player)
end
Basic outline to a ban datastore
-- Server-side script

local DataStoreService = game:GetService("DataStoreService")
local BanDataStore = DataStoreService:GetDataStore("BanDataStore")

local function isPlayerBanned(player)
    local success, banData = pcall(function()
        return BanDataStore:GetAsync(tostring(player.UserId))
    end)

    if success and banData then
        return true
    else
        return false
    end
end

local function banPlayerByName(playerName)

    local playerToBan = game.Players:FindFirstChild(playerName)
    if playerToBan then
        local success, error = pcall(function()
            BanDataStore:SetAsync(tostring(playerToBan.UserId), true)
        end)
        if not success then
            warn("Failed to ban player: " .. error)
        end
        playerToBan:Kick("You have been banned from this game.")
    else
        warn("Player with name " .. playerName .. " not found.")
    end
end

game.Players.PlayerAdded:Connect(function(player)
    if isPlayerBanned(player) then
        player:Kick("You are banned from this game.")
    end
end)

-- Example: Ban a player by name
local playerNameToBan = "UsernameToBan"
banPlayerByName(playerNameToBan)

These are all sever side scripts that do checks for hacking.
Each one of these I would add to permeant ban list.

4 Likes

Protip: don’t trust people who say “don’t rely on client”, these people are not professional and do not see the potential of client anti-cheats when used properly.

2 Likes

Their potential? Their only potential is to stop unexperienced exploiters. If your game is small and gets no visits then sure rely on a client-sided anti-cheat… however, once your game gets big people will bypass it and upload the script for others to use.

1 Like

You could do a lot on a client, and I do support @weakroblox35’s comment.

You could use a remote event client & server and if the client is deleted then the server brings a copy from server storage to the player that doesn’t have the script. You could also camo the script name so it could look like a built in Roblox player script. And you could obviously protect your anti cheat remote event. Clients do have potential.

1 Like

It has potential only as long as it isn’t bypassed, which it will. Maybe won’t get bypassed if your game is very very small, but if it is moderate then it’s a waiting game until a bypass gets released somewhere.

Client-sided anti-cheats is a game of mouse and cat. They bypass it, you patch, and they bypass it again… not a good thing for big games huh

Generally, if you are okay with wasting your time on a client-sided anticheat when you could’ve made a reliable server-sided one, go for a client one.

Could be bypassed in a matter of minutes. There are a lot of methods to protect your client sided anti-cheat since I’ve myself used one for a long time and maintained one (and more, I used to work on anti-cheats for bigger games than mine), but ever since creating my own server one I stand with my opinion and experience

1 Like

But my client idea I suggested would also work well with an independent server anti cheat. As when the exploiter tries to delete the anti-cheat in player scripts it’s going to keep coming back and you can’t do anything about it because it would be recloned on server and there’s not a lot you could do. But of course, protect the remote event as well.

This script would not take long at all. I suggest on top of this you could put a simple alt detection as well. And another addon to the client system that checks if the screengui of a player is being tampered with, also banning the names of Orion which is a popular script hub I’m pretty sure some exploiters use. And the banning of any screengui named Dex. Or anything similar.

There is a lot you can do here. But clients should still be considered as a plan B. And not thrown in the garbage acting as clients can’t do anything.

1 Like

“Never trust devforum membes, they’re just cloested v3rm members”

3 Likes

a DescendantAdded-based function can automatically delete those

Remote-spy, figure out what the remote does, then use that knowledge to bypass it

Good point, I use that for my anti-cheats as well.

Yeah this is definitely handy and something server cannot do, however it can still be sadly bypassed. I did use this but believe me that having to patch a bypass every moment gets tiring.

Agree, it is effective against exploiters that cannot script and don’t have a big knowledge. But they can figure out a bypass by googling for it (if it exists)

But plan A should always be server sided :+1:

2 Likes

?? :joy: really dude

I already guessed you would link that thread to the reply, but read what I said first.

2 Likes

remote spy doesnt work on actors btw do research before you start blabbering

2 Likes

He was talking about remotes, read what he said first.

Also, a simple google:

Cough cough, research before you start blabbering

1 Like

So, I shouldn’t trust what you have to say? I don’t get this message.

2 Likes