Only show guides for your app
Automatically hand a role to everyone who joins — the two-line join handler, the privileged intent it needs, and the role-order rule that trips people up.
Autorole gives a role to everyone the moment they join — a "Member" role that unlocks channels, or a colour that says "not verified yet". The logic is tiny; the two things that actually matter are enabling the right privileged intent and putting the bot's role in the right place.
| At a glance | |
|---|---|
| You need | a working bot from Host a discord.js bot, and the ID of the role to grant |
| Plan | Free or premium |
| Time | About ten minutes |
Built on the discord.js bot guide. It's the same join event as Welcome new members, so the two combine naturally.
The bot can't act on a join it never hears about, and join events are a privileged intent.
⚠️ Heads up — this is a privileged intent. In the Discord Developer Portal: your application → Bot → Privileged Gateway Intents → turn on Server Members Intent → save. The code requests
GatewayIntentBits.GuildMembers; with the toggle off, the bot crashes at login withUsed disallowed intents.
The complete index.js. Put the role's ID in .env as AUTOROLE_ID (Developer Mode on → right-click the role in Server Settings → Copy Role ID):
require('dotenv').config();
const { Client, Events, GatewayIntentBits } = require('discord.js');
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
],
});
client.once(Events.ClientReady, (c) => {
console.log(`Listening as ${c.user.tag}`);
});
client.on(Events.GuildMemberAdd, async (member) => {
if (member.user.bot) return; // skip other bots if you like
try {
await member.roles.add(process.env.AUTOROLE_ID);
console.log(`Gave the auto-role to ${member.user.tag}`);
} catch (err) {
console.error(`Could not add the role to ${member.user.tag}:`, err.message);
}
});
client.login(process.env.DISCORD_TOKEN);
Your .env:
DISCORD_TOKEN=your-token
AUTOROLE_ID=123456789012345678
Save and restart.
GatewayIntentBits.GuildMembers is why the join event arrives at all — it pairs with the portal toggle above.Events.GuildMemberAdd fires once per join; member.roles.add(id) grants the role.if (member.user.bot) return skips other bots so they don't get the human "Member" role. Delete the line if you want every account to get it.try/catch turns a permission or hierarchy failure into a readable console line instead of an unhandled crash — useful because the two classic failures (missing permission, role too high) both throw here.| Requirement | Detail |
|---|---|
| Server Members Intent | privileged — enable it in the Developer Portal (callout above) |
| Manage Roles permission | the bot's role needs it to assign the role |
| Role position | the bot's highest role must sit above the role it grants |
⚠️ Heads up: The most common autorole failure isn't the code — it's role order. A bot can only grant a role that sits below its own highest role. In Server Settings → Roles, drag the bot's role above the auto-role. If the console logs "Missing Permissions", this is almost always why.
GuildMemberAdd event and the same intent, add member.roles.add(...) to that handler and do both at once.member.roles.add(['id1', 'id2']).GuildMemberAdd only fires for new joins. To backfill existing members, loop over guild.members.fetch() once — but that reads the whole member list, so use it sparingly.Used disallowed intents at startup — the Server Members Intent toggle is off. Turn it on and restart. See Bot appears offline.AUTOROLE_ID is wrong. Re-copy the role ID.