Discord bot starter code library (Python, Node.js, TypeScript)
Three tested starter bots you can copy and paste: Python (discord.py), Node.js (discord.js) and TypeScript. Each one logs in and answers two slash commands. Then put it online 24/7 on ESN.
Which starter should I use? #
- Python (discord.py): the easiest to read if you are new to coding. Great for most bots.
- Node.js (discord.js): the most popular library, with the biggest set of examples online.
- TypeScript (discord.js): discord.js with types, so your editor catches mistakes before you run the bot.
All three do the same thing: log in, register two slash commands (/ping and /hello) and answer them. Not sure? Read discord.py vs discord.js.
Before you start #
- Create a bot in the Discord Developer Portal, copy its token and invite it to your server with the
botandapplications.commandsscopes. Step by step: create a bot and get its token. - Put the token in a file called
.env, never in your code:
DISCORD_TOKEN=paste-your-token-hereNever share .env or post it in a screenshot. Anyone with the token controls your bot.
Python starter (discord.py) #
requirements.txt
discord.py
python-dotenvmain.py
import os
import discord
from discord.ext import commands
from dotenv import load_dotenv
load_dotenv() # reads DISCORD_TOKEN from the .env file
TOKEN = os.getenv("DISCORD_TOKEN")
intents = discord.Intents.default()
# intents.message_content = True # only if you read normal messages (turn it on in the Developer Portal too)
class StarterBot(commands.Bot):
async def setup_hook(self):
synced = await self.tree.sync() # registers your slash commands
print(f"Synced {len(synced)} slash command(s)")
bot = StarterBot(command_prefix="!", intents=intents)
@bot.event
async def on_ready():
print(f"Logged in as {bot.user} (ID: {bot.user.id})")
@bot.tree.command(name="ping", description="Check that the bot is alive")
async def ping(interaction: discord.Interaction):
await interaction.response.send_message(f"Pong! {round(bot.latency * 1000)} ms")
@bot.tree.command(name="hello", description="Say hello")
async def hello(interaction: discord.Interaction):
await interaction.response.send_message(f"Hi {interaction.user.mention}!")
bot.run(TOKEN)Run it on your computer with pip install -r requirements.txt then python main.py. Slash commands can take a minute to show up the first time. If they don't, see slash commands not showing.
Node.js starter (discord.js) #
package.json
{
"name": "my-discord-bot",
"version": "1.0.0",
"main": "index.js",
"dependencies": { "discord.js": "^14.16.0", "dotenv": "^16.4.0" }
}index.js
require("dotenv").config();
const { Client, Events, GatewayIntentBits, REST, Routes, SlashCommandBuilder } = require("discord.js");
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
const commands = [
new SlashCommandBuilder().setName("ping").setDescription("Check that the bot is alive"),
new SlashCommandBuilder().setName("hello").setDescription("Say hello"),
].map((command) => command.toJSON());
client.once(Events.ClientReady, async (readyClient) => {
console.log(`Logged in as ${readyClient.user.tag}`);
const rest = new REST().setToken(process.env.DISCORD_TOKEN);
await rest.put(Routes.applicationCommands(readyClient.user.id), { body: commands });
console.log(`Registered ${commands.length} slash commands`);
});
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === "ping") {
await interaction.reply(`Pong! ${client.ws.ping} ms`);
} else if (interaction.commandName === "hello") {
await interaction.reply(`Hi ${interaction.user}!`);
}
});
client.login(process.env.DISCORD_TOKEN);Run it with npm install then node index.js.
TypeScript starter (discord.js) #
package.json
{
"name": "my-ts-bot",
"version": "1.0.0",
"main": "dist/index.js",
"scripts": { "build": "tsc", "start": "node dist/index.js" },
"dependencies": { "discord.js": "^14.16.0", "dotenv": "^16.4.0" },
"devDependencies": { "typescript": "^5.6.0", "@types/node": "^22.0.0" }
}tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "CommonJS",
"outDir": "dist",
"rootDir": "src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
}
}src/index.ts
import "dotenv/config";
import {
ChatInputCommandInteraction,
Client,
Events,
GatewayIntentBits,
REST,
Routes,
SlashCommandBuilder,
} from "discord.js";
const token = process.env.DISCORD_TOKEN;
if (!token) throw new Error("DISCORD_TOKEN is missing from .env");
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
const commands = [
new SlashCommandBuilder().setName("ping").setDescription("Check that the bot is alive"),
new SlashCommandBuilder().setName("hello").setDescription("Say hello"),
].map((command) => command.toJSON());
async function handle(interaction: ChatInputCommandInteraction): Promise<void> {
if (interaction.commandName === "ping") {
await interaction.reply(`Pong! ${client.ws.ping} ms`);
} else if (interaction.commandName === "hello") {
await interaction.reply(`Hi ${interaction.user}!`);
}
}
client.once(Events.ClientReady, async (readyClient) => {
console.log(`Logged in as ${readyClient.user.tag}`);
const rest = new REST().setToken(token);
await rest.put(Routes.applicationCommands(readyClient.user.id), { body: commands });
});
client.on(Events.InteractionCreate, async (interaction) => {
if (interaction.isChatInputCommand()) await handle(interaction);
});
client.login(token);Build it with npm install then npm run build. That makes dist/index.js, which is the file you run.
Deploy it on ESN (24/7) #
- Get a bot plan. Pick one on the plans page. Bot hosting starts at $0.50/month and the server is set up right after checkout. Choose Discord bot (Python) or Discord bot (Node.js) to match your starter.
- Upload the files. In Files, upload your code,
.envandrequirements.txtorpackage.jsonto the top folder. Skipnode_modulesandvenv. See uploading files. - Set the start file. In Startup: Python uses
main.pyby default. Node.js usesindex.js. For TypeScript, upload thedistfolder and set Main JavaScript File todist/index.js. - Press Start. The server installs your packages on every start, then runs your bot. Look for the "Logged in as" line in the Console.
Full guides: host a Python bot, host a Node.js bot, host a TypeScript bot.
Next steps #
- Learn step by step: the free first Discord bot course (Python, 5 parts).
- Save data: add a SQLite database.
- Want a finished bot instead? See Discord bot templates.
- Got an error? Look it up in error fixes A–Z.
FAQ #
Are these starters free to use? #
Yes. Copy them, change them and use them in any bot you like.
Why is message_content commented out? #
Slash commands work without it. Only turn on the Message Content intent if your bot reads normal chat messages, and switch it on in the Developer Portal too, or the bot will not log in.
Which plan does a starter bot need? #
A small bot like this runs fine on the smallest bot plan. Bot hosting starts at $0.50/month, and you can move up later.
Will my bot stay online when my PC is off? #
Yes. On ESN Hosting the bot runs on our servers, not your computer, so it stays online 24/7.
Host your bot from $0.50/month →
Still stuck? Use the live chat on the panel or ask in the ESN Systems Discord. Last updated November 4, 2026.