Start here: what the Message Content intent does
The Message Content intent is a privileged Gateway intent (MESSAGE_CONTENT, 1 << 15) that lets your Discord bot read the content, embeds, attachments, components and poll fields of messages. Without it, your bot still receives message events, but those fields arrive empty - so prefix commands like !help silently never match. To use it, toggle Message Content Intent on the Bot page of the Developer Portal and request it in your code, then restart the bot.
Last verified: November 2026 against Discord's Gateway documentation, the Privileged Intent Review guide and the developer change log.
Two facts trip up most developers. First, it is not tied to any event: per Discord's Gateway docs, it "isn't directly associated with any Gateway events. Instead, access to MESSAGE_CONTENT permits your app to receive message content data across the APIs." That includes REST responses, not just the Gateway. Second, missing it does not produce an error. Your bot connects, shows online, receives MESSAGE_CREATE, and reads an empty string.
| Situation | What you observe |
|---|---|
| Intent off in portal, not requested in code | Bot online; message.content is "" in servers |
| Intent requested in code, off in portal | Connection closed with 4014 Disallowed intent(s) |
| Intent on in portal, not requested in code | Bot online; content still empty |
| On in portal and requested in code | Content populated |
What changed in 2026: 10,000 users replaces the 100-server rule
Most guides still say you can toggle privileged intents freely until your bot reaches 100 servers. That stopped being true on June 10, 2026. Discord's change log and the Privileged Intent Review guide describe the new rules:
- The review threshold is users, not servers. If your app is accessible to fewer than 10,000 unique users across all its servers, you can turn privileged intents on and off in the Developer Portal with no application. Once it passes 10,000 users, you must apply for access. Discord's own example: a bot in 50 large servers can hit the threshold while a bot in 200 small servers may not.
- A 90-day window. When an app crosses the threshold with a privileged intent enabled, the owner is notified (system DM and/or email, plus a callout in the portal) and has 90 days to apply. Miss the window and existing access is removed, though you can apply again any time.
- Annual reapplication. Apps already granted access must reapply once a year, again with a 90-day window after the notice.
- Bots keep working during review. An app under review continues to use the intents it requested and can keep joining servers.
- Verification and intent review are now separate processes. The Gateway docs still describe verification as "required for apps in 100+ guilds", but it no longer doubles as your intent review.
Practical meaning: a small bot does not need permission from anyone, but you should still build with the minimum set of intents, because growth later forces you to justify each one in writing.
When you get content without the intent
The intent is not needed in several situations, which is why a bot can "work in DMs but not in the server" or "respond when pinged but ignore everything else". Discord's docs list these exceptions:
- Messages your app sends.
- Direct messages sent to your app.
- Messages that @mention your app.
- The target message of a message context menu command (right-click a message, Apps, your command).
- Replies to your app's messages made with Discord's reply feature with "ping on reply" enabled. Discord's You Might Not Need a Privileged Intent guide notes this does not apply to replies to slash command responses.
If your feature can be designed around those - mention the bot, DM the bot, or use a context menu - you do not need the intent at all. That is not a workaround; it is what Discord explicitly recommends: "If your app's functionality can be built to work with this access, you should not request the Message Content intent."
Note what the intent does not gate: it does not stop you receiving MESSAGE_CREATE (that is GUILD_MESSAGES and DIRECT_MESSAGES), and it does not affect message IDs, authors, timestamps or channel IDs. A bot that only needs to know that someone posted - activity counters, XP systems based on message count - works without it.
Enabling it in the Developer Portal
- Open
discord.com/developers/applicationsand select your app. - Go to the Bot page in the left sidebar.
- Scroll to Privileged Gateway Intents.
- Toggle Message Content Intent on and save the change.
- Restart the bot. Discord's review guide is explicit: intent changes only take effect on a new Gateway connection, so a running bot will not pick them up until it reconnects.
If the toggle is locked, your app is over the 10,000-user threshold and needs approved access; apply from the same page. The other two privileged intents live in the same section: Presence Intent (GUILD_PRESENCES) and Server Members Intent (GUILD_MEMBERS). Do not enable them "just in case" - each one is something you will have to justify if the bot grows.
Requesting it in code: discord.js, discord.py and raw Gateway
Since Gateway API v8, every intent you want must be listed when you identify. The portal toggle grants permission; your code has to ask for it.
discord.js (v14)
import { Client, GatewayIntentBits, Events } from "discord.js";
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages, // receive MESSAGE_CREATE in servers
GatewayIntentBits.MessageContent, // privileged: populate message.content
],
});
client.on(Events.MessageCreate, (msg) => {
if (msg.author.bot) return;
if (msg.content === "!ping") msg.reply("pong");
});
client.login(process.env.DISCORD_TOKEN);
MessageContent without GuildMessages is a common half-fix: you are allowed to read content, but you never receive the server messages that would contain it. Add GatewayIntentBits.DirectMessages (and the Partials.Channel partial) if you also handle DMs.
discord.py (2.x)
import os, discord
from discord.ext import commands
intents = discord.Intents.default()
intents.message_content = True # privileged
bot = commands.Bot(command_prefix="!", intents=intents)
@bot.command()
async def ping(ctx):
await ctx.send("pong")
bot.run(os.environ["DISCORD_TOKEN"])
Intents.default() deliberately leaves out the privileged intents, so prefix commands in commands.Bot do nothing in servers until you set message_content = True.
Raw Gateway identify
If you speak to the Gateway directly, add the bit to your intents integer. GUILDS (1 << 0) + GUILD_MESSAGES (1 << 9) + MESSAGE_CONTENT (1 << 15) = 1 + 512 + 32768 = 33281:
{
"op": 2,
"d": {
"token": "YOUR_BOT_TOKEN",
"intents": 33281,
"properties": { "os": "linux", "browser": "my_bot", "device": "my_bot" }
}
}
A wrongly calculated value that includes undefined bits closes the connection with 4013 Invalid intent(s), which is different from 4014.
Close code 4014: Disallowed intent(s)
Discord's close code table defines 4014 as: "You sent a disallowed intent for a Gateway Intent. You may have tried to specify an intent that you have not enabled or are not approved for." It is marked as not reconnectable - retrying the same identify will fail the same way, so libraries stop and raise. What each library prints:
| Library | What you see |
|---|---|
| discord.js / @discordjs/ws | Error: Used disallowed intents |
| discord.py | discord.errors.PrivilegedIntentsRequired: Shard ID None is requesting privileged intents that have not been explicitly enabled in the developer portal... |
| Raw WebSocket | Close frame with code 4014 right after identify |
The fix is always one of three:
- Toggle is off. Turn on the matching intent on the Bot page. Check all three privileged intents, not just Message Content - requesting
GuildMembersorGuildPresenceswithout the toggle triggers the same code. - Wrong application. The token in your environment belongs to a different app (often a dev copy) than the one you toggled.
- Access removed or not granted. Over the 10,000-user threshold, without approved access, or past a missed 90-day window. Apply in the portal, or remove the intent from your code.
The reverse mismatch - enabled in the portal, not requested in code - never errors. It just leaves content empty, which is why "my bot is online and ignores commands" is the more common report. Our Discord bot not responding guide covers the other causes of a silent bot once intents are ruled out.
REST responses, and writing an intent application that gets approved
The intent applies to REST too
Developers often assume that if the Gateway hides content, fetching the message over HTTP will reveal it. It will not. Discord's Gateway docs state that privileged intents also affect the HTTP API, and that those HTTP restrictions are "independent of Gateway restrictions, and are unaffected by which intents your app passes in the intents parameter". In other words, for REST the portal toggle (and approval, if you are over the threshold) is what counts. Fetching channel history without access gives you message objects with empty content fields, and some endpoints require the intent outright: the Search Guild Messages endpoint Discord documented in March 2026 needs both the READ_MESSAGE_HISTORY permission and MESSAGE_CONTENT.
If you have to apply
Over 10,000 users, access is a written application. Discord's review guide is direct about what gets denied: requests that do not show the use case requires access (for example, because it could be built with interactions), and submissions that are unclear or incomplete. Its advice, condensed:
- Be specific. "My bot needs message content" is not a justification; describe the feature, what data it reads and why a slash command, context menu or modal cannot replace it.
- Request only what you use. Asking for Presence or Server Members alongside Message Content without a matching feature hurts the submission.
- Explain data handling. Say whether you store message content, for how long and how it is secured - or that you process it in memory and discard it.
- Show it working. Discord suggests including evidence such as screenshots or video of the feature.
- Plan for the annual renewal. Keep the write-up somewhere you can update; you will resubmit it every year.
For moderation bots, Discord adds a pointed check: does the feature go beyond what the AutoMod API already supports? Replicating AutoMod is "generally not considered a compelling use case for access."
The alternative Discord wants you to use: slash commands
Discord's review guide calls text-to-slash migration "the most common reason developers request the Message Content privileged intent" and recommends slash commands as the replacement. They need no privileged intent at all, and they bring things a prefix parser never had:
| Need | Prefix command + Message Content | Interaction-based alternative |
|---|---|---|
| Run a command with arguments | Parse !cmd arg from content | Slash command with typed options (string, integer, user, channel, role, attachment...) |
| Act on a specific message (translate, report, save) | Read every message | Message context menu command - you receive the target message's content |
| Collect free text from a user | Wait for their next message | Modal with text inputs |
| Let users pick from choices | React or type a number | Buttons or select menus |
Slash commands also handle discovery (users see them in the / picker), argument validation and autocomplete. Keep Message Content only when the feature genuinely requires reading free-form conversation - for example AI assistants that join a channel conversation or moderation beyond what AutoMod covers - and write down why, because over 10,000 users that explanation becomes your application.
If you are building a support or FAQ bot and would rather not run Gateway code at all, Conferbot's Discord integration handles the connection side so you can design the conversation instead.
Debug checklist for empty message content
- Log
message.contentlength andmessage.guild. Empty only in servers, but fine in DMs or when mentioned? It is the intent. - Check the Bot page: Message Content Intent toggled on for this application ID.
- Check your client constructor:
MessageContent/message_contentplusGuildMessagesrequested. - Restart the process after any portal change.
- If the connection closes immediately, read the close code: 4014 means a privileged intent mismatch, 4013 a malformed bitfield, 4004 a bad token.
- If content arrives but the bot still cannot answer, it is permissions: see 50013 Missing Permissions and check channel overwrites with the permissions calculator.
Every code mentioned here has its own page in the Discord error code directory, and platform quotas are summarized on the Discord limits page.
Was this article helpful?
Build and deploy in 10 minutes. No coding needed.
Discord Message Content Intent FAQ
Everything you need to know about chatbots for discord message content intent.
About the Author
The Conferbot team writes about building, deploying, and improving AI chatbots.
View all articlesRelated Articles
From the reference shelf
Fact-checked reference pages and free tools for the platform this article covers.