Framework hub
Move into the QBCore landing page to compare verified scripts, framework fit, and install-ready products built for modern FiveM servers.
Open QBCore hubUse this guide to narrow the framework decision, then move into the core commercial hubs for verified scripts, curated bundles, and a faster server launch path.
Framework hub
Move into the QBCore landing page to compare verified scripts, framework fit, and install-ready products built for modern FiveM servers.
Open QBCore hubFramework hub
Use the ESX landing page to compare framework-specific resources, launch guidance, and premium products that fit ESX-first servers.
Open ESX hubPremium catalog
Move from research into the main shop to compare real products, framework labels, screenshots, and production-ready quality signals.
Open premium shopLearn how to optimize FiveM server loading times by managing resources, using efficient mods, and choosing the right server host to eliminate annoying delays.
Want to boost your FiveM server population? Let's get you there! So, you've got your FiveM server up and running, that's awesome! But now you're wondering...
Ready to get your FiveM server running like a champ? Dive into our 2025 comparison to find the perfect host that balances unbeatable uptime, lightning‑fast performance, and pocket‑friendly pricing, al
Gate access to your FiveM server with a Discord role-based whitelist. Covers three implementation approaches (pure Discord, identifier-based, hybrid), step-by-step bot setup, working QBCore and ESX examples, common mistakes that break auth, and security hardening.

A Discord whitelist gates access to your FiveM server using Discord roles. Players without the right role can't join, moderators can grant or revoke access from their phone via a role toggle, and every grant is logged in Discord's audit trail.
This guide covers three implementation approaches, step-by-step bot setup, working configurations for both QBCore and ESX, common mistakes that silently break auth, and security hardening for production servers.
Note on versions: The open-source
FAXES/DiscordWhitelistrepo is community-maintained and last updated in 2022. It still works for most servers. Several commercial forks exist with active maintenance and SLA support. This guide covers the free GitHub version and the patterns apply to any Discord-based whitelist.

resources/ and configure server.js.ensure DiscordWhitelist to server.cfg.Before picking an implementation, decide which of these three approaches matches your operational reality:
| Approach | How it works | Pros | Cons | Best for |
|---|---|---|---|---|
| Pure Discord role | Player's Discord role determines access | Simplest setup, dynamic via role assignment, audit trail in Discord | Hard dependency on Discord being up, players must run Discord desktop | Small-to-medium RP servers (under 500 concurrent) |
| Identifier-based (SQL) | Whitelist table of Steam/license/citizenid | No Discord dependency, most secure | Manual list management, no dynamic role-based funnels | High-security servers, VIP-only, invite-only |
| Hybrid (recommended) | Discord role default + identifier allow-list fallback | Discord convenience + break-glass for admins | More complexity, two systems to maintain | Serious RP servers, any server with paying staff |
Most guides only cover the pure Discord approach because it's easiest. For a serious server, the hybrid approach is worth the extra setup — it means a Discord API outage doesn't lock your admins out of their own server.
The trade-off: players must have the Discord desktop app running when they launch FiveM. Without it, FiveM doesn't expose a discord: identifier, and the whitelist check has nothing to match against.
FiveMX Whitelist Bot).bot; permissions: minimal (none beyond joining is fine). Visit the generated URL, add the bot to your guild.Security note: Treat the bot token like a password. Never commit it to Git, never share in screenshots, rotate immediately if leaked. Use an environment variable or a server convar rather than hardcoding.
guildIdBanned)Keep these values handy — you'll paste them into the config next.
GUILD_ID = "123456789012345678"
WHITELIST_ROLE_IDS = ["111111111111111111", "222222222222222222"]
BLACKLIST_ROLE_IDS = ["333333333333333333"]
resources/[discord]/DiscordWhitelist.fxmanifest.lua, server.js, and package.json.server.cfg:# Load after identifier providers, before anything that depends on whitelist
ensure DiscordWhitelist
Open resources/[discord]/DiscordWhitelist/server.js and set the config:
const config = {
botToken: process.env.DISCORD_BOT_TOKEN || "PASTE_TOKEN_HERE",
guildId: "123456789012345678",
// Access granted if player has ANY of these roles
whitelistRoles: [
"111111111111111111", // Whitelisted
"222222222222222222", // Staff
"333333333333333333", // Donator
],
// Immediate block if player has ANY of these roles
blacklistRoles: [
"444444444444444444", // Banned
],
// Cache role data to reduce Discord API calls (seconds)
cacheMaxTime: 60,
messages: {
noDiscord: "Open Discord and rejoin. Your Discord app must be running.",
notWhitelisted: "You are not whitelisted. Apply in #how-to-whitelist — discord.gg/yourinvite",
blacklisted: "Access denied. Contact staff via ticket.",
welcome: "Verified — loading city…",
},
};
Prefer the process.env.DISCORD_BOT_TOKEN pattern so the token never hits Git.
refresh then restart DiscordWhitelist in the server console.If either test fails, jump to the Common Mistakes section below.
Both frameworks expose the Discord identifier the same way (via GetPlayerIdentifierByType), but you may want to add framework-specific follow-up actions after a whitelist check passes.
-- resources/[qb]/qb-core/server/events.lua or your own bridge resource
AddEventHandler('playerConnecting', function(name, setKickReason, deferrals)
local src = source
deferrals.defer()
Wait(0)
local discordId = nil
for _, id in ipairs(GetPlayerIdentifiers(src)) do
if id:sub(1, 8) == 'discord:' then
discordId = id:sub(9)
break
end
end
if not discordId then
deferrals.done('No Discord identifier — run Discord desktop before joining.')
return
end
local hasRole = exports['DiscordWhitelist']:HasWhitelistRole(discordId)
if not hasRole then
deferrals.done('You are not whitelisted. Apply at discord.gg/yourinvite')
return
end
-- Log allowed connection
MySQL.insert(
'INSERT INTO connection_log (citizenid, discord_id, action) VALUES (?, ?, ?)',
{ 'unknown', discordId, 'whitelist_pass' }
)
deferrals.done()
end)
-- Hybrid approach: Discord first, identifier whitelist as fallback
local ADMIN_IDENTIFIERS = {
['license:abc123def456'] = true,
['license:xyz789...'] = true,
}
AddEventHandler('playerConnecting', function(name, setKickReason, deferrals)
local src = source
deferrals.defer()
Wait(0)
-- Extract both identifiers
local license, discordId = nil, nil
for _, id in ipairs(GetPlayerIdentifiers(src)) do
if id:sub(1, 8) == 'license:' then license = id end
if id:sub(1, 8) == 'discord:' then discordId = id:sub(9) end
end
-- Admin fallback: license whitelist always wins
if license and ADMIN_IDENTIFIERS[license] then
deferrals.done()
return
end
-- Normal path: require Discord + role
if not discordId then
deferrals.done('Discord required. Start Discord desktop and rejoin.')
return
end
local hasRole = exports['DiscordWhitelist']:HasWhitelistRole(discordId)
if not hasRole then
deferrals.done('Not whitelisted. Apply at discord.gg/yourinvite')
return
end
deferrals.done()
end)
The identifier fallback is the break-glass mechanism — when Discord's API is down, your admins can still join.
These are the bugs we see most often on FiveM support forums. Each one has a simple fix, but they look like different problems from inside:
Symptom: Token stops working a few days after a public commit.
Cause: Someone scraped your public repo and revoked or abused the token.
Fix: Rotate the token immediately. Move it to an environment variable or setr whitelist_token "..." convar. Add your config file to .gitignore.
Symptom: Admins locked out of their own server when Discord API is down.
Cause: Pure Discord whitelist with no identifier fallback. When Discord API returns 5xx, every whitelist check fails.
Fix: Implement the hybrid approach (ESX example above). Keep a tiny license-based allowlist of admins as break-glass.
Symptom: New applicants approved in Discord still get denied for a few minutes.
Cause: The bot's role cache hasn't refreshed yet.
Fix: Lower cacheMaxTime from the default 90 to 30-60 seconds. For instant updates, implement a webhook on Discord role-change events that invalidates the cache immediately.
Symptom: Bot appears online but says "not a member of guild" when checking roles.
Cause: The guildId in config doesn't match the guild the bot was invited to. Easy mistake when you have multiple Discord servers (main + staff + testing).
Fix: Verify the guild ID by right-clicking the server name in Discord with Developer Mode on.
Symptom: Bot shows as online but returns empty role lists.
Cause: The Privileged Gateway Intent is off. Discord introduced this requirement in 2022 and it catches new setups routinely.
Fix: Developer Portal → Bot tab → Privileged Gateway Intents → enable Server Members Intent → restart the bot.
Symptom: Players stuck on the connecting screen forever.
Cause: Your playerConnecting handler has an early return that skips deferrals.done().
Fix: Every code path in the connecting handler must end with either deferrals.done() (allow) or deferrals.done('reason') (reject). Never leave deferrals dangling.
Symptom: Valid Discord users getting blocked with no-identifier error.
Cause: FiveM sometimes misses the Discord identifier if Discord was launched after FiveM. Also, web-based Discord (browser) doesn't expose the identifier.
Fix: Document the order in your #how-to-whitelist channel: Discord desktop first, wait for full load, then FiveM. Web Discord doesn't work.
The pattern most servers converge on:
| Role | Purpose | Bypass priority |
|---|---|---|
Staff | Always-on access for mods + admins | 1 (always allowed) |
Donator | Paid supporters | 2 |
Whitelisted | Approved applicants | 3 |
Guest | Event/trial access | 4 |
Banned | Immediate block | Blacklist |
Any role in the whitelistRoles array grants access. Any role in the blacklistRoles array immediately blocks, regardless of whitelist status.
Whitelisted role on approval.#how-to-whitelist post with the role requirements, the Discord invite, and clear instructions (Discord desktop first, then FiveM).#mod-logs channel via a webhook. Audit who added whom on a monthly rotation.resources/[discord]/DiscordWhitelist folder — only your sysadmin/devops should be able to edit server.js.allowNotifications setting if your bot supports it (some forks DM players on denial, which creates a DDoS amplification vector).ensure DiscordWhitelist from server.cfg or disable in txAdmin → Resources.resources/ if decommissioning.# Discord integrations (load order matters)
ensure discord_perms
ensure DiscordWhitelist
# Optional: role-synced jobs (load after core framework)
# ensure discordrolesync
Short, actionable messages reduce support tickets:
messages: {
noDiscord: "Open Discord desktop and rejoin. Web Discord does not work.",
notWhitelisted: "Not whitelisted. Apply in #how-to-whitelist → discord.gg/yourinvite",
blacklisted: "Access denied. Contact staff via ticket bot in #support.",
welcome: "Verified — loading city…",
}
Use these internal resources to connect How to Set Up a Discord Whitelist for Your FiveM Server (2026 Guide) with setup, framework, marketplace resources, and server operations.
Discord whitelisting is dynamic (grant access by adding a role, no ACE or DB edits), scalable (moderators can manage access from mobile Discord), and auditable (Discord role history + audit logs show who granted what). The main trade-off vs identifier-based whitelisting is that players must have the Discord desktop app running when connecting, which makes Discord the hard dependency for joining your server.
Pure Discord role check is simplest and best for servers under 500 concurrent players — one Discord role controls everything. Identifier-based (SQL table of allowed Steam/license IDs) is most secure and independent of Discord, at the cost of manual list management. Hybrid combines both: Discord role for most players, identifier whitelist as break-glass for VIPs/admins when Discord API is down. Hybrid is the right answer for serious servers.
Four things: (1) a Discord server where you're admin, (2) a FiveM server with txAdmin or CLI access, (3) players running the Discord desktop app before launching FiveM (so FiveM exposes the discord: identifier), and (4) a bot created in the Discord Developer Portal with the Server Members Intent enabled.
Three causes: wrong bot token in config, bot not actually invited to the guild, or the Server Members Intent wasn't enabled in the Developer Portal. Verify the token starts with the correct prefix, check that the bot appears in your Discord member list (offline is fine, not-present is not), and confirm both Intents in the Bot tab of the Developer Portal: Server Members Intent ON, Presence Intent can stay OFF.
Launch faster
Bundles shorten the path from planning to launch by grouping the highest-leverage scripts into a cleaner commercial starting point.
The most common cause is the Discord desktop app not running when the player launches FiveM — without it, FiveM can't expose a discord: identifier to the script. Have the player restart Discord, wait for it to fully load, then launch FiveM. If that doesn't fix it, the bot's guild-members cache is stale — reduce cacheMaxTime in the config from 90s to 30s.
Yes. Add every role ID to the whitelistRoles array in the config. Access is granted if the player has any one of the listed roles. This is how most servers handle funnel differentiation — one role for approved applicants, another for donators, a third for staff with automatic access.
Two things: lower cacheMaxTime to 30-60 seconds so the bot refreshes role data more often, and if you need instant updates, implement a webhook on the Discord role-change event that invalidates the cache immediately. Without the webhook, players who just received a role will be denied until the next cache refresh — annoying but usually not worth the implementation effort unless you have high applicant churn.
The weak link is the bot token. If it leaks, attackers can impersonate the bot, read your guild member list, and potentially inject themselves into the whitelist. Store the token outside version control (env var or convar), rotate if leaked, and restrict who has write access to the resource folder. For high-value servers, pair Discord whitelisting with an identifier-based fallback — that way even a complete Discord compromise doesn't grant server access.