FiveM

FiveM Cheat Evidence Without Spyware: Screenshots, Logs and Proving a Ban Fairly

FiveM Cheat Evidence Without Spyware: Screenshots, Logs and Proving a Ban Fairly

A moderator drops an image into staff chat at 3:41am with the caption “caught him”. The frame shows a man in a hoodie standing outside a taco truck, doing absolutely nothing. No menu, no ESP boxes, no floating text, just a guy and his tacos. Meanwhile the thing that actually proves the case, a bank balance that climbed by 2.4 million in eleven minutes with no transaction rows to explain it, has been sitting in your database since before anyone reached for the capture button. That is the standard FiveM screenshot anticheat experience: the tool every owner asks for first, producing the weakest item in the folder.

Screenshots do have a place. They are also where a server quietly crosses from defending itself into watching its players, usually by accident. This post covers what a capture really contains, the cheaper evidence that beats it, how to build a case that survives an appeal, and how to hand an admin the capture button without handing them a periscope into other people’s computers.

What a FiveM screenshot anticheat actually captures

The tool nearly everyone runs is screenshot-basic, the Cfx.re resource that grabs the game’s rendered frame and hands it back as an image. On the client you call it with a target URL and a form field name, and most servers point it straight at a Discord webhook:

exports['screenshot-basic']:requestScreenshotUpload(
    'https://discord.com/api/webhooks/...',
    'files[]',
    function(data)
        local resp = json.decode(data)
        -- resp.attachments[1].url is your image
    end
)

There is a server-side export too, so staff can request a capture from a chosen player without that player’s client asking for one. Both do the same job underneath, and that job is narrower than most owners assume. You get a picture of what GTA V drew. You do not get the desktop, the second monitor, the alt-tabbed browser, or the file explorer sitting open on a folder called menu_v4_FINAL_real.

That distinction decides what a capture can prove. An external cheat rendering its menu in a separate always-on-top window is invisible to you, and so is a DMA rig reading memory from a second machine. What lands in the frame is what the game itself draws: an in-game menu, ESP boxes composited into the scene, a modded HUD. Careless cheaters get caught by this. Everyone else waves at the taco truck.

When a screenshot is evidence and when it is theatre

A FiveM screenshot anticheat earns its place as corroboration. You already have a log showing forty headshots landed through walls, and now you have a frame with the boxes visible beside it. It also settles reports that have nothing to do with cheating, like whether a player really is inside a locked interior he swears he never entered. And it catches the bottom tier of cheat user, the one running a free menu with a watermark the size of a bus, who is a bigger share of your problem than the DMA crowd will ever be.

Theatre starts when the capture is the whole case. A single frame carries no chain of custody and no way for anyone downstream to tell a genuine capture from an image somebody dragged into the channel. It has a latency problem too: the request travels to the client, the client renders, encodes and uploads, and a panic key clears a menu comfortably inside that window. Announcing that you screenshot everybody adds a cost, since the only people who change behaviour are the ones who move to an overlay you cannot see.

Sweeping the whole server on a timer tips it over completely. You are then collecting images of people who have done nothing wrong and calling it security, which is surveillance with extra steps.

The evidence that costs nothing and beats a screenshot

Your server already knows more than any picture will tell you, and it knows it in a form you can query, sort and hand to a second reviewer. Start with money and inventory: total what exists, subtract what the server admits creating, and stare at the gap.

SELECT SUM(bank + cash) FROM players;

SELECT source_type, SUM(amount) FROM economy_log
WHERE created_at > NOW() - INTERVAL 24 HOUR
GROUP BY source_type;

When circulation grows by two million while paychecks, jobs and sales account for four hundred thousand, you have found something real, and you found it without asking a client a single question. The rest of the cheap evidence works the same way.

  • Position sampling on the server catches teleports without trusting the client at all. Read coordinates every few seconds, work out metres per second between samples, and flag anything beating a fast car while the player is on foot. Whitelist your own scripted movement by setting a short-lived flag whenever spawn, admin transport or a lift legitimately relocates somebody.
  • Entity creation tells you what appeared and who owned it. The server-side entityCreating event fires before the entity exists and can be cancelled, so you can log the model and the owner and refuse anything outside your allow list, rather than issuing a ban after the tank is parked in Legion Square.
  • Game events hand you weapon damage and explosions with no client script involved. weaponDamageEvent and explosionEvent arrive server side with the source attached, which is how you notice one player producing damage from a weapon your city never hands out.
  • Connection and spawn rows anchor everything to a timeline: identifiers captured at playerConnecting, session start and end, character selected, first spawn coordinates. Deeply boring data, and the reason you can say with confidence which of two accounts was in the seat at 02:19.

All of it is server authoritative, which is the only property that counts. A client can lie about what it sees. It cannot lie about what your server recorded happening. The same discipline that makes server-side validation work is what makes your logs believable in your own staff room.

Build a case file, not a smoking gun

Single-frame culture is what produces bad bans. Replace it with a record per case, written before the ban goes out and stored somewhere staff cannot quietly edit later.

A workable case file holds every identifier you have for the player, the window of time under review, the server-side rows that raised the flag, whatever corroboration you gathered, the name of the person who reviewed it, and the decision with its reason in plain language. Ten minutes of writing, tops. The payoff arrives the first time a banned player argues his case in your Discord in front of an audience, because at that moment you either have the folder or you have a moderator’s memory of a Tuesday.

Two habits keep it honest. Write the case before you issue the ban, so you are never reverse-engineering a justification for something already done. And require a second reviewer on permanent bans, someone who reads the file cold without hearing the story first. If it cannot convince a colleague who was not there, it will not convince the player or the eleven people watching your appeals channel.

Why client-reported detections should never auto-ban on their own

Client-side detection has a structural problem no amount of clever Lua fixes. Your detection code and the cheat share one process, on hardware the cheat user controls. Whoever holds more privilege wins, and that is not your resource. A cheat can hook the function you detect with, feed it clean values, delay your report, or simply never let it fire.

Then there is the direction of travel. If your detection reports home over a net event carrying a player id and a reason string, any client can fire that event too. Without validating source against the payload, you have shipped a remote ban button anybody in the city can point at anybody they dislike, and the logs will look completely legitimate while it happens.

False positives finish the argument. Anything that injects a library into the game process looks identical to a naive detector. ReShade lives inside the process as a graphics hook. OBS game capture injects its own hook library. The Discord, Steam and NVIDIA overlays all do the same. Your best streamer is the most heavily injected person on your server, and a rule based on module presence removes her while leaving the DMA user untouched. That is a scoreboard you do not want to explain in public.

Treat every client-reported detection as a tip. A tip opens a case file, raises the logging level for that source, and puts a human in front of the server-side numbers. It does not, on its own, end anybody’s season.

Who gets to screenshot a player, and who watches them

The moment a capture command exists, somebody on your staff can look at any player’s game window at any time for any reason, and by default nobody will ever know. That is a much larger permission than most owners realise they granted, and it usually ends up sitting in the same ACE group as kick.

Gate it on purpose. Give it its own ACE object granted to a named group rather than folding it into a general staff bundle, and refuse the command unless a reason string is supplied. Log every invocation before the capture happens: who asked, which player, the stated reason, the timestamp, written to a channel or table staff cannot delete from. Log the failures too, because a failed request still means somebody pointed the thing at a person. Rate limit per admin, since a moderator taking thirty captures an hour is doing something other than moderating.

The pattern to watch for is target concentration. Genuine moderation scatters across your player base. When one moderator’s captures keep landing on the same four names, or on the person he argues with in general chat every night, you have found something, and it is not a cheater.

How long to keep screenshots, and what to tell players

Every image you keep can leak, and a Discord channel full of them grows on its own with nobody deciding anything. Webhook URLs get pasted into configs, configs get shared with the new developer, staff leave with role access nobody revoked. A three-year archive of other people’s game windows is a breach waiting for a name.

Pick a retention window and enforce it with a scheduled job rather than good intentions. Tie the number to the longest appeal window you offer, plus a small margin. Captures attached to a live case survive until the case closes and its appeal window expires, captures that produced nothing get deleted on schedule, and nothing at all gets kept because it might be handy one day. Store the files somewhere with real access control instead of a chat channel, and have the case file point at the image rather than pasting the image into six places.

Then tell people, in advance, in writing. One short paragraph in your rules covers it: what you log server side, that staff can capture an image of your game window while you are connected, that staff use of that power is itself logged, how long anything is retained, and how to ask what you hold. Players very rarely object to this when it is disclosed up front. They object to discovering it afterwards. The paragraph sits next to the rest of your FiveM server compliance paperwork, and writing it once saves you the same argument every month.

What you can show a banned player without leaking your detection methods

An appeal lands and two bad instincts show up together. One says paste everything and prove you were right. The other says “we do not discuss our detection methods” and closes the ticket. The first teaches cheaters exactly where your thresholds sit. The second reads as a shrug and gets screenshotted into a rival’s Discord within the hour.

Show outcomes, withhold machinery. Outcomes are what happened: timestamps, deltas, coordinates, the frame itself. Machinery is how you noticed: sample intervals, the number that trips a flag, which heuristic fired, the whitelist of legitimate teleports. A published threshold stops being a detection and becomes a speed limit that careful cheaters drive just underneath.

In practice it is one short paragraph. Between 02:14 and 02:25 your bank balance rose by 2.4 million with no matching transaction. In the same window you moved between Sandy Shores and the docks four times, faster than any vehicle in the city. Here is the capture taken at 02:19. Specific, checkable, and it gives away nothing useful. Redact other players out of whatever you send, because their names have no business in somebody else’s appeal.

Run the whole thing as a process rather than as whoever happens to be awake: a written route in, a reviewer who did not issue the original ban, and a stated turnaround. A published FiveM ban appeals process buys more community trust than the ban ever did, and costs an afternoon.

So build outward from the server. Get money and inventory reconciliation running, log entity creation and position deltas, keep your connection rows, and only then bolt a FiveM screenshot anticheat on top as corroboration for cases that already stand up without it. Gate the capture command behind its own permission, log every use including the failures, delete on a schedule, and write down what you collect before a player has to ask.

Do that and the next 3:41am picture of a man standing outside a taco truck arrives as a footnote in a case file rather than as the case. Which, frankly, is where a picture of a taco truck has always belonged.