DEV Community

Cover image for How to protect your FiveM scripts: obfuscate Lua for free
Kasun Hapangama
Kasun Hapangama

Posted on Edited on

How to protect your FiveM scripts: obfuscate Lua for free

Sell FiveM scripts? Then every buyer can open your .lua files and read every line. Copying your logic, removing your credits or patching out a check takes a text editor and five minutes.

Obfuscation makes that much harder: names become noise, control flow gets scrambled, and the code still runs. This guide walks through obfuscating a whole FiveM resource for free, without breaking the exports, events and NUI callbacks other resources rely on, and how to test it before you ship.

First: do you need it?

Be clear on two things before you start:

  • Tebex asset escrow already encrypts escrowed files. If you sell through Tebex with Cfx's asset escrow, the files it encrypts don't need obfuscation (Cfx's own FAQ says so). Obfuscation is for what escrow doesn't cover: files you keep readable with escrow_ignore that still hold logic, and resources you deliver outside escrow (other stores, commissions, private sales).
  • The Cfx.re forum's Releases section doesn't allow third-party obfuscation. If you post a resource there, don't obfuscate that release.

What obfuscation does: renames local variables and scrambles the structure of your code, so reading or editing it is slow and painful, while it still runs the same.

What it doesn't: stop someone determined, or stop a buyer from sharing the resource. It raises the cost of copying your work. For sharing, you need a license key per buyer (more at the end).

An illustration of a server-side check before and after obfuscation

Step 1: Check for Lua 5.4-only syntax

This is the catch that trips most people. FiveM runs Lua 5.4 (lua54 'yes' in your manifest), but Prometheus, the Lua obfuscator used here, reads and writes Lua 5.1. Most FiveM code is 5.1-compatible and works fine. Files that use 5.4-only syntax won't parse:

5.4-only syntax Example
Integer division local half = count // 2
Bitwise operators flags & 4, x >> 1, ~mask, and bitwise or
Variable attributes local id <const> = 5, <close>

Find them before you upload:

grep -rnE '//|<const>|<close>|>>|<<|[^~=<>]~[^=]|[^&]&[^&]' --include='*.lua' .
Enter fullscreen mode Exit fullscreen mode

Expect a few false hits (a // inside a URL string is fine). Any file with real 5.4 syntax goes on the Exclusions list in step 4, so it ships unchanged.

Step 2: Create a free account

I build SunLicense, a licensing service for script and plugin sellers, and its free plan includes 3 obfuscation runs a month. Sign up with Google, GitHub, Discord or email. No credit card.

Step 3: Developers → Obfuscation → Lua

Open Obfuscation under Developers in the sidebar, choose Lua, then Prometheus (Lua / FiveM).

Choose an obfuscator: Prometheus (Lua / FiveM)

Step 4: Zip the resource and upload it

Zip the resource folder (the one with fxmanifest.lua) and drop it in. A single .lua file works too. Zips up to 50 MB.

SunLicense reads your fxmanifest.lua (or the legacy __resource.lua) and obfuscates only the scripts it lists under client_scripts, server_scripts and shared_scripts, with globs like server/*.lua expanded. Everything else ships exactly as it was.

What gets obfuscated: the scripts in your manifest. Left untouched: the manifest, html, stream, data files and exclusions

Because string literals are kept, exports, event names and NUI callbacks keep working: nothing another resource calls by name changes.

Three settings matter:

Setting Use
Protection preset Medium (recommended). Strong protects more but grows and slows the code; Weak and Minify are lighter
Lua version Lua 5.1 for FiveM and RedM (LuaU is for Roblox)
Exclusions Files to leave alone: your 5.4 files from step 1, and files buyers should edit, like config.lua or locales/*.lua

Step 5: Run it and download the result

Choose Obfuscate and watch the live log. It runs as a background task, so you can close the tab and come back; results are kept for 7 days on the History tab. Every output file is syntax-checked (compiled without being run) before you get it, so a broken file never ships silently.

You get a zip with the same layout as yours, plus a short report.

For release scripts, the CLI does the same run:

sunlicense obfuscate dist/my-resource.zip --engine prometheus -o dist/obfuscated/
Enter fullscreen mode Exit fullscreen mode

Step 6: Test it on a real server

Never ship an obfuscated resource you haven't started. Ten minutes on a test server:

  • Drop the obfuscated folder into resources/ and ensure it. No errors in the server console or the F8 client console.
  • Run every command and open every menu or NUI page.
  • Call your exports from another resource, and trigger the events other scripts listen for.
  • restart the resource while players are connected.
  • Watch the resource monitor (resmon) for CPU time compared with the original. If a hot loop got slower, exclude that file or step down a preset.

If something fails, the console error names the file. Add it to Exclusions, or try Weak, and run again.

Obfuscation is half the job

An obfuscated resource that anyone can start is still a resource anyone can share. The other half is a license key per buyer: the server owner puts their key in server.cfg, the resource checks it on start and every few hours, and a refund on Tebex revokes it automatically. A shared key then shows up on too many servers, and you can switch off exactly one buyer.

The free FiveM resource template has all of that ready (Lua 5.4, the license check, keeps running if the license server can't be reached, and a sealed core that only opens with a valid license). For the general picture, see License keys explained.

Licensing, the Tebex integration and obfuscation are all on SunLicense's free plan, with no cut of your sales. See how it works for FiveM scripts.


This article was written with the help of an AI assistant and reviewed by me before publishing.

Top comments (0)