Discord Verification Bot in Python: a Button and a Question Before Joining
A verification bot keeps newcomers in a single channel until they click a button and answer a question; then it gives them a role and they see the rest of the server. It stops automated spam accounts without asking for anything outside Discord. Here it is in full, in Python with discord.py, plus how to keep it online.
Before the bot: what Discord already has
Every Discord server has a verification level in its settings. According to Discord's documentation there are five: none; verified email; account older than 5 minutes; member of your server for more than 10 minutes; and verified phone. Raise it first: it costs nothing and stops a lot of spam.
Community servers can also require members to accept the rules before talking. Until they do, Discord marks them as “pending”, and Discord's documentation says a pending member can't use buttons or commands. If you have it on, the order is: first they accept the rules, then they click your bot's button.
The bot adds what Discord doesn't: a question an automated account won't answer, and a role that only opens the channels to whoever answered it.
Rather not set it up yourself? Discord bot hosting from €1.50 a month, no contract and a full refund within 72 hours. Or create a free Discord bot, no card needed.
1. Set up the server: one role and one channel
Create the “Verified” role
In Server Settings → “Roles”, create a “Verified” role with the “View Channels” permission. Take “View Channels” away from @everyone: that way, without the role nothing is visible.
Create the verification channel
A text channel, for example #verification, that @everyone can see (in “Edit Channel” → “Permissions”, “View Channel” allowed for @everyone and “Send Messages” denied: only the button is needed).
Copy the role ID
Turn on Developer Mode (User Settings → “Advanced”), right-click the “Verified” role and “Copy Role ID”. It goes in the .env file.
2. Invite the bot with “Manage Roles”
If you don't have the application and the token yet, follow the first step of the Python Discord bot guide. For this bot, tick “bot” and “applications.commands” in the invite link and the permissions “View Channels”, “Send Messages” and “Manage Roles”. The bot permissions calculator builds the link for you.
What fails most: a bot can only give roles that are below its own. In “Roles”, drag the bot's role (it has the bot's name) above “Verified”. It needs no privileged intent: it doesn't read messages, it only handles the button.
3. The full code
Three files. The button never expires (timeout=None and a fixed custom_id) and setup_hook registers it again at startup, so the message you post keeps working after every restart. The question is a sum that changes every time, in a Discord pop-up, and the replies are only seen by whoever clicked (ephemeral).
discord.py
python-dotenvDISCORD_TOKEN=paste-your-token-here
VERIFIED_ROLE=the-role-idimport os
import random
import discord
from discord import app_commands
from dotenv import load_dotenv
load_dotenv()
VERIFIED_ROLE = int(os.environ["VERIFIED_ROLE"]) # the ID of the role that gives access
class Question(discord.ui.Modal, title="A quick question"):
def __init__(self):
super().__init__()
# A new sum every time someone clicks the button
self.a, self.b = random.randint(2, 9), random.randint(2, 9)
self.answer = discord.ui.TextInput(label=f"What is {self.a} + {self.b}?", max_length=3)
self.add_item(self.answer)
async def on_submit(self, interaction: discord.Interaction):
if self.answer.value.strip() != str(self.a + self.b):
await interaction.response.send_message("That's not right. Click the button and try again.", ephemeral=True)
return
role = interaction.guild.get_role(VERIFIED_ROLE)
await interaction.user.add_roles(role, reason="Passed verification")
await interaction.response.send_message("Done! You can now see the rest of the server.", ephemeral=True)
class Verify(discord.ui.View):
def __init__(self):
super().__init__(timeout=None) # never expires: the button always works
@discord.ui.button(label="Verify me", style=discord.ButtonStyle.success, custom_id="verification:button")
async def verify(self, interaction: discord.Interaction, button: discord.ui.Button):
if interaction.user.get_role(VERIFIED_ROLE):
await interaction.response.send_message("You're already verified.", ephemeral=True)
return
await interaction.response.send_modal(Question())
class MyBot(discord.Client):
def __init__(self):
super().__init__(intents=discord.Intents.default())
self.tree = app_commands.CommandTree(self)
async def setup_hook(self):
# Listen again to the buttons posted before the restart
self.add_view(Verify())
await self.tree.sync()
client = MyBot()
@client.tree.command(name="post-verification", description="Posts the message with the verification button")
@app_commands.default_permissions(administrator=True)
@app_commands.guild_only()
async def post(interaction: discord.Interaction):
await interaction.channel.send(
"👋 Welcome! Click “Verify me” and answer one question to see the rest of the server.",
view=Verify(),
)
await interaction.response.send_message("Posted.", ephemeral=True)
client.run(os.environ["DISCORD_TOKEN"])Watch out for fake “verification bots”
There are scams dressed up as verification: a bot or a link that, to “verify” you, asks you to scan a QR code, log in on a site that isn't discord.com or run something in your browser. That's how they take over your account session. On GitHub there are even repositories that say so in their own description.
The verification in this guide never leaves Discord: a button, a Discord pop-up with a question and a role. If you copy a verification bot from the internet, read the code before giving it your token, and never ask for anything other than clicking a button. And if your token has ever been public, change it in the developer portal (“Reset Token”).
Keeping it online all the time
This bot has to be online around the clock: if it's offline when someone joins, the button fails and that person is left outside. On your computer that means leaving it on day and night; hosting it is better. Free and paid options, compared, in where to host your Discord bot.
NapNodes has a free 256 MB bot that isn't turned off for being idle; you renew it every 7 days with “Start” (its catches, in this guide). Create it, switch it to Python in “Settings” → “Language”, upload the three files in “Files” and click “Start”: the libraries in requirements.txt install themselves and app.py is the startup file already set. So you don't have to renew it, the Mini plan (512 MB) stays online all the time.
Frequently asked questions
How do I make a verification bot on Discord?
With a “Verified” role that opens the channels, a channel everyone can see and a bot that gives that role when someone clicks a button and answers a question. In discord.py it's about 60 lines: a View with timeout=None, a Modal with the question and member.add_roles.
Why can't my bot give the verified role?
Because it lacks “Manage Roles” or because its role is below the one it's trying to give. A bot only gives roles below its own: move it up in “Roles”.
Why did the verification button stop working when the bot restarted?
Because the button wasn't registered again at startup. Use a View with timeout=None, a fixed custom_id and client.add_view() in setup_hook.
Is a verification bot that asks you to scan a QR code safe?
No. A real verification never asks you to scan a QR code or log in with your account on another site: that's how Discord accounts get stolen.
Shall we set it up for you?
Discord bot hosting from €1.50 a month, never oversold: your RAM is yours alone. And if you'd rather start without paying, there's a free Discord bot, no card needed.
Free tool: Discord bot permissions calculator. Tick your bot's permissions and get the number and the invite link; or paste a number and see which permissions it grants.
Keep reading
- Discord Role Bot: Buttons So Everyone Picks Their Own Roles (Python and JavaScript)
Make your own Discord self-role bot in Python or JavaScript: a message with buttons to add and remove roles, no database and no reaction roles needed.
- Discord Giveaway Bot in Python: Enter Button, Random Winners and Rerolls
Build your own Discord giveaway bot in Python: /giveaway with an enter button, countdown, random winners and /reroll. Full code, no ads.
- How to Make a Discord Bot in Python (discord.py), Step by Step
Make your first Discord bot in Python with discord.py: create the application, get the token, add slash commands (/hello) and keep it online for free.