The least-loved moment for a growing Discord server is when dozens of fake accounts flood in within minutes and bury the channels under invite links and slurs. A well-built discord anti raid system is exactly what stops this: it catches mass joins, link spam and coordinated attacks in seconds, without waiting for a human to react. In this guide we build a layered anti-raid setup from scratch with discord.js v14 — from an account-age filter to an automatic lockdown mode.
What does a raid look like? (Threat model)
Before writing defenses, be clear about what you're defending against. A typical raid carries at least one of three signals:
- A join surge: A large number of accounts joining the server within seconds.
- New/templated accounts: Users created a few hours ago, no avatar, with a shared naming pattern.
- Content spam: The same invite link (
discord.gg/...) or malicious URL pouring into channels.
A good defense watches these three signals separately and tightens as they accumulate. Relying on a single rule is a mistake: look only at account age and you punish genuine newcomers; look only at message spam and the wave is already inside.
Required intents and permissions
An anti-raid bot must see both join events and message content. In the Discord Developer Portal, enable the Server Members Intent and Message Content Intent privileged intents, and grant the bot's role Kick Members, Ban Members and Moderate Members permissions.
const { Client, GatewayIntentBits } = require('discord.js');
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
],
});
The bot's role must sit above the roles of the members it will moderate; otherwise kick and ban calls fail silently.
First layer: the account-age filter
Most raid bots are freshly mass-produced accounts. In the guildMemberAdd event, look at the account's creation time and automatically handle anyone below a chosen threshold. Keep the threshold reasonable — a value that's too aggressive turns away genuine new users at the door.
const MIN_ACCOUNT_AGE = 7 * 24 * 60 * 60 * 1000; // 7 days
client.on('guildMemberAdd', async (member) => {
const age = Date.now() - member.user.createdTimestamp;
if (age < MIN_ACCOUNT_AGE) {
await member.kick('Account too new (anti-raid)').catch(() => {});
}
});
Preferring a kick over an automatic ban is safer: in a false-positive case the user can simply rejoin. For a gentler approach, instead of kicking, assign new members to a "quarantine" role and leave them for manual approval.
Second layer: catching the join surge
This is where the real discord anti raid logic lives: even when individual accounts look normal, a burst of joins in a short window is the raid. Measure the join rate with a sliding window, and lock the server down automatically once the threshold is crossed. Raising Discord's verification level is the fastest lockdown — it instantly prevents new accounts from posting.
const { GuildVerificationLevel } = require('discord.js');
const joins = [];
const WINDOW = 10_000; // 10 seconds
const THRESHOLD = 5; // 5+ joins in 10s = raid
client.on('guildMemberAdd', async (member) => {
const now = Date.now();
joins.push(now);
while (joins.length && now - joins[0] > WINDOW) joins.shift();
if (joins.length >= THRESHOLD) {
await member.guild.setVerificationLevel(
GuildVerificationLevel.High,
'Anti-raid: sudden join surge',
).catch(() => {});
// notify moderators, lock channels, etc.
}
});
You can set a timer to lift the lockdown automatically (e.g. revert after 10 minutes), but in serious attacks it's safer to have moderators lift it manually. Calibrate the thresholds to your server's normal join rate: five joins in ten seconds is a clear anomaly in a small community but may be perfectly normal in a large one.
Third layer: stopping link and invite spam
Even when accounts slip through, the real damage arrives in messages: advertising invites and malicious links. In the messageCreate event, catch invite links with a simple regex, delete the message and timeout the sender temporarily.
const inviteRegex = /(discord\.gg|discord(?:app)?\.com\/invite)\/\w+/i;
client.on('messageCreate', async (message) => {
if (message.author.bot || !message.inGuild()) return;
if (inviteRegex.test(message.content)) {
await message.delete().catch(() => {});
await message.member.timeout(10 * 60 * 1000, 'Invite spam').catch(() => {});
}
});
Apply the same approach to message rate: if a user sends 5+ messages in 5 seconds, that's a spam signal too. Keep each user's recent message timestamps in a Map and apply a timeout when the threshold is crossed. Don't forget to whitelist trusted roles — having moderators muted by your own bot is an unwanted comedy.
Discord's built-in weapons: AutoMod and verification
You don't have to put all the weight on the bot. Discord's AutoMod lets you define keyword, spam and invite-blocking rules from server settings (or the API) without writing code; these rules run before a message is sent, so spam is blocked before your bot even sees the event. Complement it with these built-in settings:
- Verification level: At least "Medium" (5+ minutes of membership) automatically filters most raid bots.
- Rules screening: Forces new members to accept the rules, weeding out simple bots.
- Membership screening / gatekeeper bot: A one-click verification role slows down automated accounts.
The most robust setup is layered: AutoMod and built-in verification are the first sieve, while your custom bot adds the signals Discord doesn't watch on its own, such as join rate and account age.
Frequently asked questions
Auto-ban, kick, or a quarantine role?
It depends on context. A permanent ban suits only clear-cut attacks; given the false-positive risk, a kick is more forgiving. The most flexible method is a quarantine role: it isolates the suspect from every channel but keeps them inside, so a moderator can make the final call.
How do I make sure I don't wrongly punish genuine new members?
Calibrate thresholds to your own server's normal traffic and log every automatic action to a log channel. Watching the logs for a few weeks and spotting false positives, then tuning the values, is the safest way to find the right balance. When in doubt, prefer a timeout or quarantine over an outright ban.
If I have AutoMod, why do I need a separate bot?
AutoMod is excellent at message content, but it doesn't measure join rate, doesn't look at account age, and doesn't auto-lock during a surge. A custom bot fills exactly those gaps; used together, the defense is far stronger.
Want a layered anti-raid system for your server? Let's plan a setup with an account-age filter, automatic lockdown, link/spam protection and a log panel — get in touch.