Overview: Scopes vs Permissions vs Intents
OAuth Scopes control what your application can do during authorization (e.g., bot
, applications.commands
).
Permissions are per-guild/channel capabilities such as Send Messages, Manage Roles, governed by permission bits and role hierarchy.
Gateway Intents control which realtime events your bot receives via the WebSocket gateway. Some are privileged and require explicit enablement.
Essential OAuth Scopes
- bot: Adds the bot user to a guild with requested permission bits.
- applications.commands: Required for slash commands.
- webhook.incoming: For creating webhooks during OAuth flows (optional, app-specific).
Common Permission Bits (Least-Privilege)
- SendMessages, ReadMessageHistory, UseExternalEmojis
- UseApplicationCommands for slash commands
- ManageMessages only if you really need moderation features
- Avoid Administrator unless absolutely required
Gateway Intents (v10)
Enable only what you consume to reduce payload and improve performance:
- Non-privileged:
Guilds
,GuildMessages
,GuildVoiceStates
,DirectMessages
,MessageContent
(see below),GuildMessageReactions
, etc. - Privileged:
GuildMembers
,GuildPresences
, andMessageContent
for most bots. Privileged intents must be toggled in the Developer Portal and often justified during verification for larger bots.
When You Need Message Content Intent
Slash commands do not require reading raw message content. Request MessageContent
only if you process text from normal messages or need pattern matching. Prefer application commands and context menus when possible.
Example: Discord.js v14 Client with Intents
const { Client, GatewayIntentBits } = require('discord.js');
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent // only if required by your features
]
});
client.login(process.env.DISCORD_TOKEN);
Permission Calculators and Invite URLs
Use the OAuth2 URL Generator in the Developer Portal to build invite links with specific permission bits and scopes. Validate the requested permissions with a calculator before sharing the invite.
Security Checklist
- Avoid Administrator; prefer targeted permissions
- Use role-based permission gating for admin-only commands
- Document which features require each permission/intent
- Review intents periodically and disable unused ones
Privileged Intents in 2025
Guild Members, Guild Presences, and Message Content are privileged. You must explicitly enable them in the Developer Portal. If your bot serves 100+ guilds, Discord may require additional verification and justification for continued access. Expect to document why you need each privileged intent, how you use it, and how you minimize data retention.
- Guild Members: Needed for advanced member syncing, role audits, join/leave flows.
- Guild Presences: Needed for presence-aware features (online/idle/dnd), activity-based automations.
- Message Content: Only request when you truly parse raw message text. Prefer application commands and context menus otherwise.
Enable and Roll Out Safely
- Enable required intents in Developer Portal → Bot → Privileged Gateway Intents.
- Deploy staged: start in a test guild and a staging shard to confirm event volumes and memory impact.
- Use feature flags to toggle intent-driven code paths; fall back to slash commands where possible.
- Continuously audit: remove unused intents to reduce payload size and compliance scope.
Design Without Message Content
You can build most functionality without reading arbitrary messages:
- Slash commands and context menus provide typed parameters and built-in validation.
- Components (buttons, selects, modals) drive structured, low‑friction UX.
- Webhooks handle outbound notifications without a running gateway client.
Intent Footprint and Performance
Each additional intent can increase event traffic. Monitor:
- Gateway event rate per shard
- Memory vs cached structures (members, presences)
- Reconnects and resume success rate
Minimum Examples (discord.js)
const { Client, GatewayIntentBits } = require('discord.js');
// Minimal, command-first bot (no message content)
const clientA = new Client({ intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages // receive create/delete events without content
]});
// Requires Message Content (only if absolutely necessary)
const clientB = new Client({ intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent
]});
Compliance and Data Handling
- Minimize collection: do not store raw content unless essential.
- Retention: expire logs; redact tokens, IDs when possible.
- User requests: build data export/delete flows to honor policies and laws where applicable.