Getting started
- Projects: create a project. It holds your scripts and keys.
- Scripts: upload your Luau. Each script gets its own permanent loader link. To ship a new version, press Update next to it: pick the next version or type your own, and the link stays the same.
- Keys: make keys and send them to your players. They add theirs on this dashboard once.
- Players sign in on this site and copy their ready-made loader.
The loader
What players run (the dashboard fills in their key):
script_key = "FAL-XXXX-XXXX-XXXX-XXXX"
loadstring(game:HttpGet("https://<your-site>/files/<loader-id>.lua"))()
Keyless projects drop the first line. The loader verifies the key, downloads your script encrypted for that one load, runs integrity checks, and keeps a heartbeat going while the game runs. Loader links only answer Roblox: browsers get refused.
Keys and players
- Devices: each key has device slots (Max devices). The first run on a PC uses a slot; the same PC never uses a second one.
- Players reset devices from their dashboard, as often as your project allows. You can always reset from Keys → Manage.
- Ban a key with a reason: it stops immediately and running copies are kicked within about 15 seconds.
- Lock down a project to cut off every player at once (and Resume later).
- Full keys are visible to you in Manage; every reveal is logged in Audit.
Project settings
Projects → Settings. Players need a key (off = free script), device reset cooldown (any time to never), and IP lock (leave off: home and mobile IPs change often).
Also on the Settings card: sign script downloads (the loader refuses a changed script; a little slower for big scripts) and auto-ban rules (ban a key after N sharing attempts or N tamper reports in 24 hours; 0 = off).
Key tools and helpers
- First use: tick Timer starts on first use so a dated key only starts counting when it's first run.
- Bulk: tick keys in the list to copy, extend, reset, ban, unban or delete up to 200 at once.
- Import: paste keys from another key system; they keep working as typed.
- Changelog: write what changed when you upload; players see it under their loader.
- Helpers (Projects → Helpers): people you trust to manage keys for one project. They can't touch scripts, settings or webhooks, or delete keys.
Analytics and alerts
Analytics shows loads, failures, devices, executors and security events for the last 7-30 days. For alerts, paste a Discord webhook in Settings and pick events: new device, device limit reached, key banned, auto-ban, or a spike in failed loads.
Inside your script
After a successful load these values are available in getgenv():
Fallacy_Discord_Name / Fallacy_Discord_Id | Who owns the key |
Fallacy_Key_Note | The note you set on the key |
Fallacy_Key_Executions / Fallacy_Script_Executions | Run counters |
Fallacy_Time_Left | Seconds until the key expires (0 = lifetime) |
Fallacy_Script_Name / Fallacy_Script_Version / Fallacy_Project_Name | What's running |
Fallacy_Session_Id / Fallacy_Session_Count | This session, and how many are live in the project |
Fallacy_Announcement | Your project's announcement ("" when none) |
Fallacy_Beta | true when this key got the script's beta version |
Fallacy_Timings | Load timings in ms (loader, verify, download, decrypt, total) |
If a key leaks, press Replace key in Keys → Manage. The old key dies at once; devices, expiry and the note carry over.
These are for display only. Any script can write to getgenv(), so don't use them to decide whether a player is allowed in. If your script is running, the loader already checked. They're cleared at the start of every load.
Webhooks and storage
-- Post to a webhook saved in the Webhooks tab (or the script's default webhook)
Fallacy_SendWebhook({ webhook = "exec-logs", content = "Ran by %Fallacy_Discord_Id%" })
-- Small per-key storage (Private) or shared per-project storage (Public)
local id = Fallacy_WriteDB("settings", HttpService:JSONEncode(cfg), false, "Private")
local value = Fallacy_ReadDB(id)
-- Ban this device yourself when your own checks catch tampering
if tampered then Fallacy_Blacklist() return end
Webhook messages can't ping @everyone or roles. Storage: names up to 64 chars, values up to 16 KB, 100 values per key per project.
Kick codes
When a load fails, the loader kicks the player with Big Brother Saw It Coming... and a short code. Players only see the code and will send it to you. Use this table to find the fix.
| Shown as | Codes | What to do |
|---|---|---|
| Access Denied | E2x-E3x | Something about the key or device. Open Audit and filter by the key: the failed load says why. |
| Session Ended | E5x | The key was banned or its session ended. Running the loader again starts a new one. |
| Connection Lost | E4x-E5x | Network trouble on the player's side. Ask them to run it again. |
| Unavailable | E33 | The project is locked down. Resume it in Projects. |
| Unsupported | E41 | Their executor can't make web requests. |
| Tamper Detected | E0x-E1x | The loader caught interference. If one key keeps doing it, ban it or turn on an auto-ban rule. |
| Error | E99 | Usually your script failed to compile. Audit shows the error. |
Errors inside your script never cause a kick. They show in the executor console as usual.
Load times
After a load, getgenv().Fallacy_Timings holds how long each step took, in milliseconds. To see them, end your script with:
local t = getgenv().Fallacy_Timings
print(("verify %d ms, download %d ms, total %d ms"):format(t.verify, t.download, t.total))
Add getgenv().Fallacy_T0 = tick() above the loader line to include fetching the loader itself. Under about 1.5 seconds total is good.