On this page
This tutorial builds a small but real Discord bot in Python with discord.py: two slash commands, /hello and /add, and a message that welcomes new members. You test it on your own computer, then put it on a free Torchlite Bot server so it stays online without your computer.
You need Python 3.12 or newer and a Discord account. No earlier bot experience is needed.
Create the bot in Discord
- Open the Discord Developer Portal and click New Application. The name you give it is the bot's name.
- Open Bot in the left menu and click Reset Token. Copy the token and keep it somewhere private.
- Further down on the same page, switch on Server Members Intent. The welcome message needs it; the slash commands do not.
- Open OAuth2, then URL Generator. Tick bot and applications.commands, and under Bot Permissions tick Send Messages.
- Open the generated URL, pick your Discord server and click Authorize.
Set up the project
Make a folder for the bot with two files. The first is requirements.txt, the list of packages:
discord.pyInstall it once on your computer:
pip install -r requirements.txtWrite the bot
The second file is bot.py:
import os
import discord
from discord import app_commands
class Bot(discord.Client):
def __init__(self):
intents = discord.Intents.default()
intents.members = True # for on_member_join; switched on in the portal
super().__init__(intents=intents)
self.tree = app_commands.CommandTree(self)
async def setup_hook(self):
# Sends the slash commands to Discord once, at startup.
await self.tree.sync()
bot = Bot()
@bot.event
async def on_ready():
print(f"Online as {bot.user} in {len(bot.guilds)} server(s).")
@bot.tree.command(name="hello", description="Say hello")
async def hello(interaction: discord.Interaction):
await interaction.response.send_message(f"Hello, {interaction.user.mention}!")
@bot.tree.command(name="add", description="Add two numbers")
@app_commands.describe(a="The first number", b="The second number")
async def add(interaction: discord.Interaction, a: int, b: int):
await interaction.response.send_message(f"{a} + {b} = {a + b}")
@bot.event
async def on_member_join(member: discord.Member):
channel = member.guild.system_channel
if channel is not None:
await channel.send(f"Welcome to {member.guild.name}, {member.mention}!")
bot.run(os.environ["DISCORD_TOKEN"])What each part does:
- Intents tell Discord which events the bot wants. The defaults cover slash commands;
membersadds join events. CommandTreeholds the slash commands, andtree.sync()registers them with Discord when the bot starts.@bot.tree.commandturns a function into a slash command. The type hints,a: int, become the command's options, and Discord checks the input for you.on_member_joinruns when someone joins and writes in the server's system channel, the one set under Server Settings, Overview.- The token comes from the
DISCORD_TOKENenvironment variable, never from the code.
Run it on your computer
Set the token for this terminal session, then start the bot. On macOS or Linux:
export DISCORD_TOKEN="paste-your-token-here"
python bot.pyOn Windows PowerShell:
$env:DISCORD_TOKEN="paste-your-token-here"
python bot.pyThe terminal prints Online as YourBot#1234 in 1 server(s). Type / in your Discord server and the two commands appear. The first time, slash commands can take a few minutes to show up.
Host it for free on Torchlite
Your bot is offline as soon as you close the terminal. To keep it running:
- On Create your server, pick the Bot plan and Discord bot (Python).
- In the panel, open Startup and paste the token into Bot token.
- Open Files, delete the starter bot's files, and upload your
bot.pyandrequirements.txt. Check that Main file under Startup isbot.py. - Press Start in the Console. The server installs
discord.pyfromrequirements.txtand starts your bot.
To deploy from GitHub instead, so a push and a restart is your whole deploy, follow the Discord bot guide. The Bot plan gives 512 MB of RAM and asks for a Renew once every 24 hours; Discord bot hosting has the details.
Keep it healthy
A few habits save most of the trouble once real people use the bot:
- Answer within 3 seconds. Discord shows "The application did not respond" if a command is not acknowledged in time. For anything slow, such as a web request or a database query, call
await interaction.response.defer()first, then send the result withawait interaction.followup.send(...). - Catch errors per command. Wrap risky code in
tryandexcept, and reply with a short message instead of letting the command fail silently. Print the error, so it shows up in the panel's Console. - Keep data on disk, not in memory. Everything in Python variables is lost when the bot restarts, and on a free server it restarts whenever a renew is missed. Store anything that matters in the MySQL database or an SQLite file.
- Do not flood channels. Sending many messages in a loop runs into Discord's rate limits; discord.py waits them out, but your bot looks frozen in the meantime. Batch the text into one message instead.
- Watch the memory. 512 MB is plenty, but caching every member of a big server adds up. Only switch on the intents you actually use.
Where to go next
- More commands: copy the
addblock.str,int,float,bool,discord.Memberanddiscord.Roleall work as option types. - Commands only you can use: add
@app_commands.default_permissions(administrator=True)above a command. - A database: your Bot server includes a MySQL database, or keep it simple with an SQLite file next to
bot.py. - Split it up: when the file grows, move commands into separate files with discord.py's extensions and cogs.
Common problems
KeyError: 'DISCORD_TOKEN'
The environment variable is not set in this terminal, or on Torchlite the Bot token field is empty. Set it and start again.
PrivilegedIntentsRequired
The code asks for the members intent, but Server Members Intent is off in the Developer Portal. Switch it on, or remove the intents.members = True line and the welcome message.
The slash commands do not appear
Wait a few minutes after the first start, and check that the invite URL included applications.commands. Restart the bot once.
Stuck on a step?
Ask on the forum. Your question links back to this guide, so whoever answers knows where you are.
About the author
Torchlite team
The people who run Torchlite
We build and run the Torchlite panel and the nodes. Every guide is checked on our own servers before it goes up, and updated when the panel changes.

