Validating weapons and damage on the server
Treat everything the client says as a claim. Give weapons only from server code, check with GetSelectedPedWeapon on the server that the weapon a player holds is one their inventory says they own, and use the server events weaponDamageEvent, giveWeaponEvent and explosionEvent to inspect and CancelEvent() suspicious actions. Log first, punish later: lag and scripts can create false positives.
Every FiveM cheat menu can spawn weapons, add ammo and fake damage on the client. You cannot stop a player controlling their own game — but you can make sure the server never believes them. Good weapon protection is not one magic anticheat resource; it is a handful of server-side rules that make cheating pointless and easy to catch.

#The one rule: the client only makes requests
The classic hole is a server event like TriggerServerEvent('shop:giveWeapon', 'WEAPON_RPG') that does whatever the client asks. A cheater can trigger any event with any arguments. Every event must re-check on the server: is the player near the shop, do they have the money, are they allowed this weapon? Only then does the server add the item.
local SHOP = vec3(22.0, -1107.0, 29.8)
local PRICES = { WEAPON_PISTOL = 2500 }
RegisterNetEvent('shop:buy', function(weapon)
local src = source
local price = PRICES[weapon]
if not price then return end
local ped = GetPlayerPed(src)
if #(GetEntityCoords(ped) - SHOP) > 10.0 then
print(('[shop] %s tried to buy away from the shop'):format(GetPlayerName(src)))
return
end
-- take money and add the item through your framework here
end)The same pattern applies to every event: see secure server events for the general version.
#Checking the weapon in hand
With OneSync the server can read the weapon a player is holding. Compare it periodically with what your inventory says they own. A weapon in hand that the inventory does not know about was spawned by the client.
local UNARMED = `WEAPON_UNARMED`
local function ownsWeapon(src, hash)
-- ask your inventory: ox_inventory, qb-inventory, ESX loadout...
return true
end
CreateThread(function()
while true do
Wait(5000)
for _, id in ipairs(GetPlayers()) do
local src = tonumber(id)
local hash = GetSelectedPedWeapon(GetPlayerPed(src))
if hash ~= 0 and hash ~= UNARMED and not ownsWeapon(src, hash) then
print(('[weapons] %s holds %s without owning it'):format(GetPlayerName(src), hash))
end
end
end
end)#The server-side game events
FiveM forwards certain game actions to the server as events before they are applied for other players. Calling CancelEvent() inside the handler blocks them.
| Event | Fires when | Useful fields |
|---|---|---|
weaponDamageEvent | A player damages an entity with a weapon | weaponType, weaponDamage, hitGlobalId, willKill, hitComponent |
giveWeaponEvent | A client tries to give a weapon to a networked ped | pedId, weaponType, ammo |
removeWeaponEvent / removeAllWeaponsEvent | A client removes weapons from a ped | pedId, weaponType |
explosionEvent | A client creates an explosion | explosionType, posX, posY, posZ, ownerNetId |
local BLOCKED = {
[`WEAPON_RAILGUN`] = true,
[`WEAPON_RPG`] = true,
[`WEAPON_MINIGUN`] = true,
}
AddEventHandler('weaponDamageEvent', function(sender, data)
if BLOCKED[data.weaponType] then
CancelEvent()
print(('[weapons] %s did damage with a blocked weapon'):format(GetPlayerName(sender)))
end
end)
AddEventHandler('giveWeaponEvent', function(sender, data)
CancelEvent() -- clients may not hand weapons to other peds
end)
AddEventHandler('explosionEvent', function(sender, ev)
if ev.explosionType == 4 or ev.explosionType == 5 then -- ROCKET, TANKSHELL
CancelEvent()
end
end)#Stopping spawned props and vehicles
sv_entityLockdown controls which entities clients may create. relaxed blocks entities created by client scripts (ambient traffic and peds still work); strict blocks every client-created entity. Either way, your own scripts must then spawn vehicles and objects on the server (for example with CreateVehicleServerSetter), so test it in development first.
set sv_entityLockdown relaxed # or strict once every script spawns server-side#Damage sanity checks
- Hits from a distance the weapon cannot reach (a pistol “hitting” someone 400 m away).
willKillon a full-health, armoured target with one pistol round.- More hits per second than the weapon’s fire rate allows.
- Damage while the attacker is dead, in a vehicle without drive-by, or in another routing bucket.
Each of these produces false positives under lag, so score them rather than banning on one event. Balanced damage settings themselves are covered in the damage modifier guide and headshot settings.
#Logging and punishment
- Log every detection with player identifiers, weapon hash and coordinates (a Discord webhook is common).
- Review patterns for a week and tune thresholds.
- Automate only the checks with zero false positives (for example a blocked weapon hash dealing damage).
- Keep ban evidence — appeals are easier when you can show the log.
Questions
Can I stop cheaters spawning weapons in FiveM?
GetSelectedPedWeapon) and cancel damage from them in weaponDamageEvent.What is weaponDamageEvent?
CancelEvent().Does GetSelectedPedWeapon work on the server?
GetPlayerPed(source).What does sv_entityLockdown do?
relaxed blocks client-script entities, strict blocks all client-created entities. Server scripts then spawn vehicles and objects.Should I auto-ban on detections?
Ready to pick a map?
Twelve themes on three base map styles, $8 each, instant download.
Relevant to what you just read
The tool for this
Twenty theme pairs for ox_lib and ox_inventory From $15, built in the browser, exported as a drop-in resource.
Look it up while you work
The reference tables this guide leans on, free and without an account.
- All 21,631 object model namesEvery model CreateObject accepts, with its hash and a flag for the LOD and proxy names that spawn invisible.
- All 921 vehicle spawn namesEvery vanilla model with a picture, its display name, its class and the hash CreateVehicle takes.
- The same tables as JSON and CSVFree downloads, CORS open, no account and no API key — ship the list inside your own resource instead of scraping a page.