screenshot-basic is the free Cfx.re resource that takes a picture of a player’s game screen, so other scripts like report menus, ban logs and anticheats can attach it as evidence. When it stops working, the cause is usually the install, the start order or the upload address. This guide walks through each fix, then covers keeping the images safe and when a different setup makes more sense.
What screenshot-basic does
It adds three functions that other resources call through exports. On the client, requestScreenshot hands the image back as text (a data URI) and requestScreenshotUpload sends it to a web address. On the server, requestClientScreenshot asks a player’s game for a picture and has it uploaded straight back to your server. It has no commands of its own. If no script calls it, nothing happens.
Install checklist
- Download it from the official citizenfx/screenshot-basic repository on GitHub. Skip zips from reupload sites, since they are a common way backdoors arrive.
- Put it in your resources folder under the exact name screenshot-basic. Other scripts call it as exports['screenshot-basic'], so a renamed folder breaks them.
- Keep the yarn and webpack resources that come with cfx-server-data. The manifest lists both as dependencies, and screenshot-basic builds itself with them on first start.
- Start it before every resource that uses it by placing ensure screenshot-basic above them in server.cfg.
- Give the first start time. It downloads packages and builds, and the server console shows each step.
- Versions: the README asks for client build 1129160 or newer and server pipeline 1011 or newer for the server export. Any server updated in recent years is well past that.
Check your resources for backdoors
Common failures and fixes
The repository’s issue tracker is turned off, so reports land as pull requests. These are the problems that show up there and in the code itself.
Build or install errors on first start. Several of the older pull requests are install errors. Read the first error in the console, not the last one. It is usually yarn failing to download a package or webpack failing to build. Check that the server can reach the internet and that the yarn and webpack resources are present and current.
A Buffer() warning on every upload. Node prints a DEP0005 deprecation warning each time a screenshot arrives. It comes from an old upload library bundled with the resource. It is a warning and uploads still go through. Open pull requests #43 and #44 patch it if the console noise bothers you.
The callback never runs. The server export waits for an upload and has no timeout. If the player leaves, crashes or the upload fails, your code waits forever. Add your own timer and log “no screenshot” as its own outcome.
Uploads never reach the server. With the server export, the player’s game uploads the image to the same server address it joined, under /screenshot-basic/upload/. If players connect through a proxy or an address that doesn’t forward those HTTP requests to your server, the image has nowhere to go.
Uploads to Discord fail. requestScreenshotUpload sends the file as a form field, and the field name must match what the receiving side expects. Discord’s webhook docs name file fields files[n]. The next two sections explain why this upload shouldn’t start on the client anyway.
Use the server export so players can’t send fake images
The README warns against sending a screenshot from requestScreenshot through a server event. A player’s client can send any image through an event, so your server would trust whatever arrives.
requestClientScreenshot works the other way round. Your server starts the request, creates a one-time upload token and only accepts the file that comes back with it. If you pass fileName, the server saves the image to that path and the player’s game never learns where it went. A modified client still controls what its own game draws, so treat a screenshot as one piece of evidence next to what the player was caught doing.
Keep webhook URLs off the client
Client scripts are downloaded to every player’s PC. A Discord webhook URL inside a client file can be read by anyone who joins. Discord’s docs say webhooks need no bot user or authentication, and the token in the URL is enough to post to your channel or delete the webhook.
Keep the URL on the server. Take the picture with the server export, then post it to Discord from a server script with PerformHttpRequest. Store the URL in a server convar and limit who can read it with add_convar_permission. Our Discord ban log guide covers the full setup.
Set up Discord ban logs safely
Store images somewhere that outlives Discord
Discord’s docs say attachment links on its CDN are signed and expire. The Discord app refreshes them for people reading the channel, but a link you copied into a ban note or a database can stop working. An appeal can arrive weeks after the ban.
Save the file yourself. The fileName option writes it to disk on your server. From there, back it up or copy it to storage you control, and keep the path with the ban record.
What good screenshot evidence looks like
Your options
screenshot-basic is a sound choice when you have a developer and need screenshots for one or two scripts. If you want evidence on every ban without wiring it up yourself, an anticheat that captures its own is the other route.
- screenshot-basic: free, open source and published by Cfx.re. You wire it into each script, handle failures and timeouts, keep webhooks private and store the files.
- An anticheat with built-in capture: a paid product. The screenshot is taken when a protection fires and attached to the ban for you, with nothing extra to install.
Daddy Shield takes the second route. It captures the player’s screen itself at the moment of detection, attaches it to the ban in the panel and doesn’t need screenshot-basic. It costs €24.99 a month, or from €19.99 a month on a six-month plan, with a 7-day refund.
How evidence works on every ban
FAQ
Is screenshot-basic still maintained? The repository’s last push was in February 2023, and recent fixes sit in open pull requests. Expect to patch small things yourself.
Can I rename the folder? Only if you also update every script that calls exports['screenshot-basic'].
Do I need screenshot-basic with Daddy Shield? No, the anticheat captures its own screenshots. Keep screenshot-basic installed if other scripts, like a report menu, still use it.