Guide

How to make a Discord bot: a beginner's guide

Which language to pick, a working first bot, and how to keep it online. Written for people who have little or no programming experience and want a bot for their own server.

Last updated . Every version number and Discord rule here was checked against the official docs on that date. A lot of the advice that ranks for this question is years out of date, and some of it no longer runs.

The short answer

If you have never programmed, use Python with the discord.py library: it reads closest to plain English and it can do everything a bot for you and your friends needs. If you already know a little JavaScript, use discord.js. Both talk to the same Discord API, so neither one locks you out of anything. The language matters far less than picking one and finishing your first bot.

Python or JavaScript?

"I heard Python is restrictive." It isn't.

That idea dates from August 2021, when discord.py's maintainer announced he was stopping development and a lot of people moved to JavaScript or to Python forks. He came back in March 2022, and discord.py 2.0 added slash commands that August. Today it is on version 2.7.1 and supports slash commands, buttons, select menus, pop-up forms, voice and user-installable apps. Discord's own list of community libraries includes more Python libraries than JavaScript ones.

The one real gap: discord.py can't listen to or record people's voice audio out of the box. discord.js's voice package can, though it warns that Discord doesn't officially document it. Unless you're building a recording bot, you will never notice. Speed isn't a concern either: a bot spends almost all of its time waiting on Discord, and Discord's rate limits cap what any bot can do long before the language matters.

Python

discord.py

Good fit if

You have never programmed before. Python reads closest to plain English, and it is also the language you would use for scripts, automation and data work later.

Watch out for

The library is asynchronous: use await asyncio.sleep(), never time.sleep(), or the whole bot freezes. Install discord.py itself, not the old 'discord' package, and check which library a tutorial uses before copying it, because forks like py-cord use different code.

JavaScript

discord.js

Good fit if

You already know a little JavaScript, or you want the same language for websites later. discord.js has the biggest bot-building community.

Watch out for

The discord.js guide says up front that you need a decent grasp of JavaScript before you start. Many tutorials (and AI answers) still use client.on('ready'), which is deprecated: use Events.ClientReady.

TypeScript

discord.js

Good fit if

You want your editor to catch mistakes before you run the bot. TypeScript is JavaScript with types, and discord.js ships its own type definitions.

Watch out for

Learn JavaScript first; TypeScript adds a layer on top of it. Node 24 can run simple .ts files directly, but bigger TypeScript projects still use a build step.

What if I know a little C++?

There is a maintained C++ library, D++, with ready-made packages for Windows and Raspberry Pi. But setting up a compiler, CMake and linking is a lot of friction when you mostly want a working bot. What you remember of C++ (variables, loops, functions) carries straight over to Python or JavaScript, which let you spend your time on the bot instead of the build. Other languages have solid libraries too: JDA for Java, Discord.Net for C# and Serenity for Rust.

How a Discord bot actually works

Four things that explain most of the confusion beginners run into:

It is a program that has to keep running.

Your code opens a live connection to Discord. While it runs, the bot shows as online and responds. Close the program or let the computer sleep, and the bot goes offline. That is why hosting comes up later.

It uses a bot account, never yours.

You create the bot in Discord's Developer Portal and it gets its own account and a secret token. Automating your own user account (a "self-bot") is against Discord's rules and can get your account banned.

Use slash commands, not "!" commands.

Older tutorials read every message looking for !hello. That needs the privileged Message Content intent (intents are switches for which kinds of events Discord sends your bot) and causes most "my bot doesn't respond" questions. Slash commands like /hello are delivered to your bot directly, appear in Discord's command menu, and need no special permission.

Discord's own tutorial builds a different kind of app.

Discord's Getting Started guide makes an app that receives commands over the web, which needs a public URL and a tool like ngrok. The bots in this guide connect to Discord directly instead, which is simpler for a bot in your own server. If you got stuck on "endpoints" in Discord's tutorial, that is why.

Build your first bot, step by step

By the end you will have a bot in your server that answers /hello. Allow about half an hour once you know the basics. You need a Windows, Mac or Linux computer; this doesn't work on a phone or tablet.

1

Learn just enough of the language

You don't need to master it. A few evenings on the basics (variables, if statements, functions, running a file from the terminal) is enough to follow along and, more importantly, to fix things when they break. For Python, the official Python tutorial covers it. For JavaScript, learn the language before the library: the discord.js guide assumes you already know it.

2

Install Python or Node.js

Python: you want Python 3.14.

  • Windows: on python.org, click Download Python install manager (the main button, not the standalone installer link under it) and run it. The first command in step 5 then installs 3.14.
  • Mac: use the macOS installer from python.org, then open Applications, the Python 3.14 folder, and double-click Install Certificates.command. Skip that and the bot can't connect to Discord, even though everything else installs fine.
  • Linux: python.org only has source code for Linux, so install your distribution's python3.14 package (plus python3.14-venv on Debian or Ubuntu).

Stick with 3.14 even after 3.15 comes out: one of discord.py's dependencies doesn't have ready-made builds for 3.15 yet, so installing can fail on Windows.

JavaScript: install the version marked LTS (long-term support) on nodejs.org: Node 24 today, Node 26 from late October 2026. Either works. Older guides that say Node 16 or 18 point at versions that no longer get security fixes.

3

Create the bot in the Developer Portal

Open the Discord Developer Portal and create a new application. Its name is your bot's name. Every application comes with a bot account built in.

Open the Bot page and click Reset Token. Discord only shows the token once, so copy it straight away and keep it somewhere private, like a password manager, until you paste it into a file in step 5. If you lose it, click Reset Token again. Treat it like a password: anyone who has it controls your bot.

4

Invite it to your server

On the Installation page, leave the install link set to Discord Provided Link. Under Default Install Settings for Guild Install, add the bot scope (the permission that adds your bot to a server) and the Send Messages permission, then click Save Changes. (The applications.commands scope that slash commands use is included with bot; adding it as well does no harm.)

Copy the install link, open it in your browser and choose your server. You need the Manage Server permission there, which you have if it's your server. Want only your friends' server to be able to add it? Make it private.

5

Write the code

Open a terminal. On Windows, use Command Prompt: press Start, type cmd and press Enter. It opens in your user folder, so the commands below create C:\Users\YourName\my-bot. On a Mac, open the Terminal app.

Make files in a code editor. You will create a few files in the my-bot folder. Use a code editor such as VS Code (free): File, Open Folder, pick my-bot, then make each new file there. If you use Notepad, set Save as type to All files before saving .env, or Windows quietly saves it as .env.txt.

Pick the half that matches your language.

Python

Command Prompt (Windows)
py install 3.14
mkdir my-bot
cd my-bot
py -V:3.14 -m venv .venv
.venv\Scripts\python -m pip install -U discord.py python-dotenv

If the first line says the install command is unavailable, an older Python launcher has taken over the py command. Run py -V:3.14 --version: if it prints Python 3.14, skip the first line and run the rest. Otherwise, open Installed apps, uninstall Python Launcher, and start again from the first line.

macOS / Linux
mkdir my-bot
cd my-bot
python3.14 -m venv .venv
.venv/bin/python -m pip install -U discord.py python-dotenv

The .venv folder holds this bot's own copy of discord.py so it can't clash with anything else on your computer. You never need to "activate" it: the commands call its Python directly.

In the my-bot folder, create a file named exactly .env with your token from step 3 (lost it? click Reset Token and use the new one):

.env
DISCORD_TOKEN=paste-your-token-here

Then save this as bot.py. Don't name it discord.py: Python would load your file instead of the library.

bot.py
import os

import discord
from discord import app_commands
from dotenv import load_dotenv

load_dotenv()  # reads DISCORD_TOKEN (and DISCORD_GUILD_ID, if set) from .env

# Optional: your server's ID makes /hello show up instantly while testing.
TEST_GUILD_ID = os.getenv("DISCORD_GUILD_ID")


class MyBot(discord.Client):
    def __init__(self):
        # Default intents: slash commands need no privileged intents.
        super().__init__(intents=discord.Intents.default())
        # The tree holds your slash commands.
        self.tree = app_commands.CommandTree(self)

    async def setup_hook(self):
        # Runs once at startup: tell Discord which commands exist.
        if TEST_GUILD_ID:
            guild = discord.Object(id=int(TEST_GUILD_ID))
            self.tree.copy_global_to(guild=guild)
            await self.tree.sync(guild=guild)  # just your server, instant
            # Remove the every-server copy from earlier runs,
            # so /hello isn't listed twice.
            self.tree.clear_commands(guild=None)
            await self.tree.sync()
        else:
            await self.tree.sync()  # every server the bot is in


bot = MyBot()


@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.event
async def on_ready():
    print(f"Logged in as {bot.user}")


bot.run(os.environ["DISCORD_TOKEN"])

Run it from the my-bot folder:

Command Prompt (Windows)
.venv\Scripts\python bot.py
macOS / Linux
.venv/bin/python bot.py

JavaScript

Command Prompt or Terminal
mkdir my-bot
cd my-bot
npm init -y
npm install discord.js

On Windows, run these in Command Prompt, not PowerShell: PowerShell blocks npm by default with a "running scripts is disabled" error. If you see it, type npm.cmd in place of npm.

In the my-bot folder, create a file named exactly .env with your token from step 3:

.env
DISCORD_TOKEN=paste-your-token-here

Save this as index.js:

index.js
// index.js: a minimal discord.js bot with one slash command, /hello
const { Client, Events, GatewayIntentBits } = require('discord.js');

// The Guilds intent is all a slash-command bot needs.
const client = new Client({ intents: [GatewayIntentBits.Guilds] });

// The commands Discord shows when someone types "/".
const commands = [
  { name: 'hello', description: 'Say hello' },
];

// Optional: your server's ID makes /hello show up instantly while testing.
const testGuildId = process.env.DISCORD_GUILD_ID;

// Runs once, when the bot has logged in.
client.once(Events.ClientReady, async (readyClient) => {
  console.log(`Logged in as ${readyClient.user.tag}`);

  // Tell Discord which commands exist. set() replaces the whole list,
  // so running it on every start updates /hello instead of duplicating it.
  try {
    if (testGuildId) {
      // Just your server, instant.
      await readyClient.application.commands.set(commands, testGuildId);
      // Remove the every-server copy from earlier runs,
      // so /hello isn't listed twice.
      await readyClient.application.commands.set([]);
    } else {
      // Every server the bot is in.
      await readyClient.application.commands.set(commands);
    }
  } catch (error) {
    console.error('Could not register commands:', error);
  }
});

// Runs every time someone uses one of the bot's commands.
client.on(Events.InteractionCreate, async (interaction) => {
  if (!interaction.isChatInputCommand()) return;

  if (interaction.commandName === 'hello') {
    await interaction.reply(`Hello, ${interaction.user.displayName}!`);
  }
});

// Log in with the token from your .env file.
client.login(process.env.DISCORD_TOKEN);

Run it from the my-bot folder. Node reads .env itself, no extra package needed:

Command Prompt or Terminal
node --env-file=.env index.js
6

Try it

The terminal should print Logged in as ... and the bot should appear online in your server. Type /hello.

If the command isn't there yet, restart Discord (Ctrl+R on Windows, Cmd+R on a Mac); a command for every server can take a moment to appear. To make commands show up instantly while you test, turn on Developer Mode (User Settings, then Advanced), right-click your server icon, choose Copy Server ID, and add it to .env as a second line: DISCORD_GUILD_ID=that-id. Both samples then register commands for just your server and remove the every-server copy from your first run.

Your bot only reads its code and .env when it starts, so after any change, stop it with Ctrl+C in its terminal and run it again. If you open a new terminal later, type cd my-bot first, then the run command from step 5.

From here, add a second command, then learn buttons and pop-up forms. The discord.py docs and the discord.js guide are the best next stops.

Keep your token out of Git

If you put your bot on GitHub, add a .gitignore file first so the token and installed packages never get uploaded:

.gitignore
.env
.venv/
node_modules/

Discord works with GitHub to catch leaked tokens: if one is pushed to a public repository, it gets reset, and your bot simply stops logging in. Make a new one with Reset Token.

Keep it private to your friends' server

By default anyone with the install link can add your bot to their server. To lock it down, do these in this order (Discord refuses to make a bot private while it still has an install link):

  1. On the Installation page, set Install Link to None and click Save Changes.
  2. On the Bot page, turn off Public Bot.
  3. Invite it with this link, replacing YOUR_APP_ID with the Application ID from the General Information page (permissions=2048 is Send Messages):
Invite link
https://discord.com/oauth2/authorize?client_id=YOUR_APP_ID&scope=bot&permissions=2048

With Public Bot off, only you (and members of your developer team) can add the bot, and you still need Manage Server in that server. If a friend owns the server, ask them to give you the Manage Server permission while you add it.

A private bot like this never needs Discord's verification, which only applies once a bot grows past 100 servers. And since June 2026, privileged intents such as Message Content only need Discord's approval once a bot reaches 10,000 users; below that you just switch them on in the Developer Portal. Many guides still quote the old 100-server rule.

How to keep your bot online 24/7

Your bot is online only while its program runs, so at some point you will want it running somewhere that never sleeps. Realistic options, with prices as of October 2026:

Your own computer

Free

Perfect while you build. The bot is online exactly as long as the program runs, so it goes offline when you close the terminal or the computer sleeps.

A Raspberry Pi or an old laptop left on

One-time hardware cost

The cheapest way to keep a small bot online all the time. Python and Node.js both run on a Raspberry Pi 3, 4 or 5 with the 64-bit Raspberry Pi OS.

A small paid host

About $5 to $7 a month

Examples: Railway's Hobby plan ($5 a month, including $5 of usage), Heroku Eco ($5 a month, and worker dynos don't sleep), or a small VPS from a provider like Hetzner (about €6 a month plus VAT). A VPS gives you the most control, but you manage Linux yourself.

Free cloud servers

Free, but fiddly

Oracle Cloud's Always Free tier and Google Cloud's e2-micro are real free servers, but setting up a Linux server is a steep step for a first project, and Oracle can reclaim instances that look idle, which a small bot easily does.

Skip anything built on old tricks. Replit's "Always On" was removed in January 2024, free web-hosting tiers like Render's go to sleep after 15 minutes without web traffic (which takes your bot offline with them), and "keep-alive" pinger scripts are unreliable at best. Railway gives new accounts a one-time $5 trial, but its free plan's $1 monthly credit may not cover a bot running all month.

Using ChatGPT or other AI to write it

Plenty of people start this way, and it works, with a catch: AI tools learned from years of old tutorials, so they often write code that no longer runs or asks for permissions you don't need. Watch for:

  • discord.Client() with no intents, which errors on current discord.py.
  • client.on('ready') in JavaScript, which is deprecated. Use Events.ClientReady.
  • Intents.all() or the Message Content intent in a bot that only uses slash commands.
  • pip install discord instead of discord.py, or a Replit "keep_alive" web server.

Ask for current versions by name (discord.py 2.7, discord.js 14), and learn what the token, intents and events are so you can fix what it writes. And never paste your bot token into an AI chat.

When it doesn't work

The problems almost everyone hits, and the fix for each:

The bot shows as offline

Your program isn't running, or it crashed. Check the terminal for an error. A bot is only online while its program runs.

/hello doesn't show up

Restart Discord (Ctrl+R on Windows, Cmd+R on a Mac). For instant updates while testing, add your server's ID as described in step 6.

/hello shows up twice

One copy is registered for every server and another just for your server. Keep DISCORD_GUILD_ID in .env and restart the bot: the code above removes the every-server copy. (Taking the ID out later brings the duplicate back, because your server's copy stays registered.)

"The application did not respond"

Your bot has to answer within 3 seconds. For slow work, acknowledge first and reply after: interaction.response.defer() then interaction.followup.send() in Python, or interaction.deferReply() then interaction.editReply() in JavaScript.

Messages your bot reads arrive empty

Your code isn't asking for the privileged Message Content intent, so Discord blanks out message text (except in DMs and messages that mention your bot). Ask for it in code (discord.py: intents.message_content = True; discord.js: add GatewayIntentBits.GuildMessages and GatewayIntentBits.MessageContent) and switch it on in the Developer Portal's Bot page. Or better, use slash commands, which don't need it.

The bot disconnects with "disallowed intents" (4014)

Your code asks for a privileged intent, such as Message Content, that isn't switched on in the Developer Portal's Bot page. Switch it on there, or remove it from your code if you only use slash commands. discord.py's own quickstart uses a $hello text command that needs this intent, which is why so many people hit it.

KeyError: 'DISCORD_TOKEN', '.env: not found', or an improper/invalid token error

Your .env file is missing, misspelled, or in the wrong place: it must sit in the my-bot folder next to bot.py or index.js, and for JavaScript you must run node from that folder. On Windows, check it isn't really named .env.txt: turn on File name extensions in File Explorer's View menu, then rename it. If the token was reset or leaked, make a new one with Reset Token and paste it in.

"running scripts is disabled on this system" (Windows)

You are in PowerShell, which blocks npm by default. Use Command Prompt instead, or type npm.cmd in place of npm.

CERTIFICATE_VERIFY_FAILED when the bot starts (Mac)

Python from python.org can't make secure connections until you add its certificates. Open Applications, then the Python 3.14 folder, double-click Install Certificates.command, and run the bot again.

Python can't find discord, or says it has no attribute

Make sure your own file isn't named discord.py (Python would import it instead of the library), that you installed into the same .venv you run from, and that py-cord isn't installed too: both use import discord.

FAQ

What is the best language for a Discord bot?

For a complete beginner, Python with the discord.py library: it is the easiest to read and can do everything a typical bot needs. If you already know some JavaScript, use discord.js. Both libraries talk to the same Discord API, so neither locks you out of features. Pick one and finish a first bot; you can always learn the other later.

Is discord.py still maintained?

Yes. Its maintainer paused development in August 2021 and resumed in March 2022, and discord.py 2.0 added slash commands that August. It has been actively developed ever since; version 2.7.1 came out in March 2026.

Can I make a Discord bot with no coding experience?

Yes, but learn the basics of the language first: variables, if statements, functions and running a file. A few evenings is enough to follow this guide. No-code bot builders exist and are fine for standard features like welcome messages, but anything custom needs code.

Does it cost anything to make a Discord bot?

Creating a bot is free, and so are Python, Node.js, discord.py and discord.js. The only possible cost is hosting: running it on your own computer is free, and an always-on host typically costs about $5 to $7 a month.

Can I host a Discord bot 24/7 for free?

Yes, with trade-offs. Your own computer works for free while it stays on, and a Raspberry Pi or old laptop left running costs only the hardware. Free cloud servers from Oracle and Google exist but need Linux skills, and Oracle can reclaim instances that look idle. A reliable always-on host costs about $5 to $7 a month. Avoid guides built on Replit's Always On (removed in 2024) or keep-alive pinger tricks.

Can I use ChatGPT to make a Discord bot?

Yes, but check what it writes. AI tools learned from old tutorials and often produce outdated code, such as discord.Client() without intents or client.on('ready') in JavaScript, or ask for permissions a slash-command bot doesn't need. Ask for current versions by name (discord.py 2.7, discord.js 14) and never paste your bot token into an AI chat.

Can I make a music bot for my friends?

You can, with two warnings. Since March 1, 2026 Discord only allows end-to-end encrypted voice, so you need discord.py 2.7 or newer with its voice extra, or a current @discordjs/voice; older tutorials will not connect. And playing music from YouTube breaks YouTube's terms of service: Groovy and Rythm, two of the biggest music bots, shut down in 2021 after YouTube cracked down.

Can I use TypeScript for a Discord bot?

Yes. discord.js includes its own TypeScript types, and Node 24 can run simple TypeScript files directly. TypeScript is JavaScript with types, so learn JavaScript first if you have never programmed.

Can I make my own Discord account reply automatically?

No. Automating your own user account (a self-bot) is against Discord's rules and can get your account banned. Create a bot account in the Developer Portal instead; it is free and takes a minute.

When it's ready for more than your friends

If your bot turns into something other servers would want, the next steps are getting it in front of them and making it stand out. We wrote guides on where to post your Discord bot and how to make it popular.

Last reviewed October 1, 2026 against discord.py 2.7.1, discord.js 14.27.0, Python 3.14, Node.js 24 LTS and Discord's developer documentation. Prices and platform rules change, so check each provider's current terms. Discord, Python, Node.js and the libraries and hosts mentioned are trademarks of their owners; BotBoard is not affiliated with any of them or with Discord Inc. Canonical URL: https://www.botboard.gg/guides/how-to-make-a-discord-bot