Engineering
Protecting a FiveM server against cheaters
The layers of FiveM cheat protection: server-authoritative scripts, secure events, entity lockdown, game event filtering (explosions, weapons, ped tasks), player identifiers and tokens for bans, honeypot events, logging, and what commercial anticheats can and cannot do.
Overview
There is no anticheat you can install that makes a badly written server safe. Cheat menus run inside the player’s game, so anything the client decides can be faked. Real protection is layered: scripts that trust the server, events that validate, game events that are filtered, and bans that stick.
The layers
| Layer | Stops | Guide |
|---|---|---|
| Server authority | Money/item/reward exploits | Secure server events |
| Entity lockdown | Spawned cars, props, peds | Server-side entities |
| Game event filters | Explosions, weapon abuse, kicking players out of cars | Below |
| Weapon validation | Spawned weapons, blocked guns | Weapon anticheat |
| Bans that stick | Returning cheaters | Below |
| Client anticheat | Menus, injectors (partially) | Commercial tools |
Filtering game events
OneSync sends some game actions to the server as events you can inspect and cancel with CancelEvent().
AddEventHandler('explosionEvent', function(sender, ev)
if ev.explosionType == 4 or ev.explosionType == 5 then -- rocket, tank shell
CancelEvent()
print(('[ac] %s explosion type %d'):format(GetPlayerName(sender), ev.explosionType))
end
end)
AddEventHandler('clearPedTasksEvent', function(sender, data)
-- used by menus to throw players out of vehicles
local ped = NetworkGetEntityFromNetworkId(data.pedId)
if IsPedAPlayer(ped) and NetworkGetEntityOwner(ped) ~= sender then
CancelEvent()
end
end)Bans that stick
Cheaters make new accounts. Store every identifier a player has (GetPlayerIdentifiers(src): license, license2, discord, fivem, steam, xbl, live, ip) and every token (GetNumPlayerTokens / GetPlayerToken), and refuse connection if any of them match a ban. Tokens are server-specific hardware-derived values, which makes ban evasion much harder than with the licence alone.
AddEventHandler('playerConnecting', function(name, setKickReason, deferrals)
local src = source
local tokens = {}
for i = 0, GetNumPlayerTokens(src) - 1 do
tokens[#tokens + 1] = GetPlayerToken(src, i)
end
local ids = GetPlayerIdentifiers(src)
-- compare ids and tokens with your ban table here
end)txAdmin’s built-in ban system already checks identifiers and hardware IDs; many servers use it rather than writing their own — see txAdmin permissions.
Honeypot events
Cheat menus fire well-known event names from old or popular scripts. Register a few of those names that your server does not use, and flag anyone who triggers them — no honest client ever will.
local TRAPS = { 'esx_society:withdrawMoney_old', 'admin:giveAllWeapons' }
for _, name in ipairs(TRAPS) do
RegisterNetEvent(name, function()
local src = source
print(('[ac] honeypot %s triggered by %s'):format(name, GetPlayerName(src)))
-- ban or flag here
end)
endClient files are public
Every client script is downloaded to the player’s PC. Anything in it — webhook URLs, API keys, admin lists, “secret” event names — is readable. Keep secrets in server files and convars. Asset escrow protects code from copying, not from being executed or observed.
What commercial anticheats add
Paid anticheats add client-side detection of menus, injected code and suspicious behaviour, plus shared ban lists. They are a useful extra layer — but an exploitable fishing:sell event stays exploitable no matter which anticheat runs next to it.
Frequently asked questions
What is the best FiveM anticheat?
Layers matter more than one product: server-authoritative scripts, validated events, entity lockdown, event filters and good bans. A commercial anticheat adds client detection on top.
How do I stop modders spawning cars?
Spawn vehicles server-side and enable sv_entityLockdown (relaxed or strict).
How do I stop ban evasion?
Ban on all identifiers and on player tokens from GetPlayerToken, not only the licence.
Can cheaters read my client scripts?
Yes. Client files are downloaded to their PC. Keep secrets on the server.
Need this built, not just explained?
Ten years of FiveM work, from Lua to NUI
Custom resources, React NUI, ESX / QBCore / Qbox integration, OneSync performance audits and security reviews — plus the websites and SEO around your server brand.
Related guides
- EngineeringWriting server events that cannot be abusedAny client can call any event you registered with RegisterNetEvent, with any arguments. In each handler: copy source into a local, check argument types and ranges, re-derive everything from server state (prices, amounts, rewards), verify the player can do this now (distance, job, item, cooldown), and log refusals. Events only other server scripts should use are registered with AddEventHandler alone, so clients cannot trigger them.
- EngineeringServer-side entity spawning in FiveMOn the server, create vehicles with CreateVehicleServerSetter(model, type, x, y, z, heading) — it is more reliable than the RPC-based CreateVehicle. Wait for DoesEntityExist, set plate and state, put the player in with SetPedIntoVehicle, and send the network ID to the client if it needs to do more. Delete with DeleteEntity. Once all scripts spawn server-side, enable sv_entityLockdown.
- EngineeringEntity ownership, handles and network IDs in FiveMEntity handles are local to each client and to the server; never send them over events. Convert to a network ID with NetworkGetNetworkIdFromEntity, send the ID, and convert back with NetworkGetEntityFromNetworkId (or NetToVeh/NetToPed/NetToObj on the client). Each networked entity has an owner that simulates it; other clients must request control before changing it, and ownership migrates when the owner leaves.
- EngineeringEvents in FiveM: how resources and players talkHandle events with AddEventHandler(name, fn); add RegisterNetEvent(name) (or use RegisterNetEvent(name, fn)) to allow the event to arrive over the network. TriggerEvent fires locally on the same side, TriggerServerEvent sends from a client to the server, and TriggerClientEvent(name, target, ...) sends from the server to one player (target = player ID) or everyone (-1). On the server, source is the sending player.