Making your first Discord bot feels like a big deal until you've done it once. Then it clicks, and you realize most of the work is just clicking buttons in a portal and copying a token into your code. This guide walks you from an empty page to a bot that actually responds to you, with working examples in both Python and JavaScript.
Create the application and the bot
Everything starts at the Discord developer portal. Head to discord.com/developers/applications and log in with your normal Discord account. Click New Application in the top right, give it a name, and accept the terms. The name here is the application name, not necessarily what your bot will be called in servers, though it's easiest to keep them the same for now.
Once the application exists, look at the menu on the left and click Bot. Older versions of the portal made you press an "Add Bot" button. Newer ones create the bot user for you automatically. Either way, you'll land on a page where you can set the bot's username and avatar. This bot user is the account that will show up in your server with a little APP tag next to its name.
That's genuinely the hard part done. You now have an application and a bot. Two more small steps and you can write code.
Get the token and keep it secret
On that same Bot page there's a Token section with a Reset Token button. Click it, confirm, and Discord shows you a long string of letters and numbers. Copy it now, because the portal will not show it again. If you lose it, you just reset it and get a new one.
Here's the thing nobody stresses enough when you're starting out. That token is the password to your bot. Anyone who has it can run code as your bot, spam servers, get you banned, and there's no recovery beyond resetting the token. So treat it like a password, because that's exactly what it is.
A quick warning: never paste your token into a public chat, a screenshot, a GitHub repo, or a forum post asking for help. People scrape GitHub for leaked tokens within minutes. If you ever think a token has been seen by someone else, reset it straight away. We'll put the token in a separate file in the examples below so it never sits inside your actual code.
Turn on the right gateway intents
Intents are Discord's way of letting you opt in to the kinds of events your bot wants to receive. They cut down on traffic and protect user privacy. For a first bot you mostly care about one of them.
Still on the Bot page, scroll to Privileged Gateway Intents. You'll see three toggles:
- Presence Intent, for seeing when users go online or offline. You can leave this off for now.
- Server Members Intent, for member join and leave events. Also fine to leave off at first.
- Message Content Intent, which lets your bot read the text of messages. If you want a classic command that reacts to someone typing
!ping, you need this one on.
Flip on Message Content Intent and save. Once your bot is in more than around 100 servers you'll have to verify your application to keep these enabled, but you're miles away from that, so don't worry about it today.
Invite the bot to your server
Your bot exists, but it isn't anywhere yet. To add it to a server you build an OAuth2 invite link that says who the bot is, what scopes it needs, and which permissions it should have.
Click OAuth2 in the left menu, then find the URL Generator. Under Scopes, tick bot. If you plan to add slash commands later, also tick applications.commands. A permissions box appears under the scopes once you select bot.
For a simple bot, the permissions you usually want are Send Messages, Read Message History, and View Channels. Pick only what your bot needs. Granting Administrator is tempting because it makes everything "just work," but it's a bad habit and a real risk if your token ever leaks. Least privilege is the right call here.
Copy the generated URL at the bottom, paste it into your browser, choose a server you own or manage, and authorize. Your bot will appear in the member list, offline for now because nothing is running it yet.
A minimal bot in discord.py
If you like Python, discord.py is the standard library. Make a folder, then install the dependencies. Using a virtual environment is good practice but optional for a first try.
python -m venv venv
source venv/bin/activate
pip install discord.py python-dotenv
On Windows the activate line is venv\Scripts\activate instead. Now create a file called .env next to your code with one line in it:
DISCORD_TOKEN=paste_your_token_here
Then make bot.py:
import os
import discord
from dotenv import load_dotenv
load_dotenv()
intents = discord.Intents.default()
intents.message_content = True
client = discord.Client(intents=intents)
@client.event
async def on_ready():
print(f"Logged in as {client.user}")
@client.event
async def on_message(message):
if message.author == client.user:
return
if message.content == "!ping":
await message.channel.send("pong")
client.run(os.getenv("DISCORD_TOKEN"))
Run it with python bot.py. Once you see the "Logged in as" line in your terminal, the bot goes online in your server. Type !ping in a channel it can see and it should reply with pong. The check against client.user stops the bot replying to its own messages, which would loop forever otherwise.
The same bot in discord.js
Prefer JavaScript? discord.js does the same job. You'll need Node installed, version 18 or newer. Set up the project and install the two packages:
npm init -y
npm install discord.js dotenv
Make a .env file just like before with your DISCORD_TOKEN line. Then create index.js:
require("dotenv").config();
const { Client, GatewayIntentBits } = require("discord.js");
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
],
});
client.once("ready", () => {
console.log(`Logged in as ${client.user.tag}`);
});
client.on("messageCreate", (message) => {
if (message.author.bot) return;
if (message.content === "!ping") {
message.channel.send("pong");
}
});
client.login(process.env.DISCORD_TOKEN);
Start it with node index.js. Same result. The bot logs in, and !ping gets you a pong. Notice the intents are listed explicitly in the client options. If you forget MessageContent here, the bot will run fine but never see what people type, which trips up a lot of beginners.
Don't commit your.env
Both examples keep the token out of your source code, which is the right pattern. But your .env file still holds the secret, so make sure it never ends up in version control. If you're using git, add a .gitignore file with a single line:
.env
Do this before your first commit, not after. Once a token has been pushed to a public repo, even for a second, you should consider it compromised and reset it.
Running it and where to go next
Right now your bot only runs while that terminal window is open. Close the terminal or shut down your computer and it goes offline. That's fine for testing. For a bot you actually want to keep online, you need it running somewhere that stays on.
The common next step is a small always on server. On a Linux box, people keep a Python bot alive with systemd or a JavaScript bot with pm2, both of which restart the bot automatically if it crashes. If you don't want to manage a whole machine, a managed Discord bot host handles the uptime for you. That's one of the things we run at Bytte.cloud, with a free starter plan so you can test before paying for anything.
Once your bot is online and stable, here are the things worth learning next, roughly in order:
- Slash commands. The
!pingstyle still works, but slash commands are the modern way and they show users what your bot can do. Look atapp_commandsin discord.py andSlashCommandBuilderin discord.js. - Embeds. Nicely formatted message boxes with titles, fields, and colors. They make a bot look far more finished.
- Storing data. When you want your bot to remember things, start with a simple file or SQLite, then move to a real database if you grow.
- Error handling. Wrap risky calls so one bad command doesn't take the whole bot down.
That's the whole loop. You made an application, protected its token, set an intent, invited the bot, and got it talking back to you in either language. The first bot is always the slowest because you're learning the portal at the same time as the code. The second one takes about ten minutes. Start small, get !ping working, and build from there.



