From nothing to a bot that’s always online
Updated 26 sep 2026. Can’t find it? See the FAQ.
Getting started
Sign in with Discord (there's no password or signup form), then create a bot and pick Python or Node.js. From there it's four steps.
- Create the bot in the dashboard. Python bots get a starter requirements.txt, Node bots a starter package.json.
- Add your code in the Files tab: upload it, or create main.py / index.js and paste the example below.
- Add your token in the Environment tab as DISCORD_TOKEN. Never paste it into your code.
- Press Start and watch the Console. You should see Logged in as ….
import os
import discord
from discord.ext import commands
intents = discord.Intents.default()
intents.message_content = True # needed for !commands; also switch it on in the Developer Portal
bot = commands.Bot(command_prefix="!", intents=intents)
@bot.event
async def on_ready():
print(f"Logged in as {bot.user}")
@bot.command()
async def ping(ctx):
await ctx.send("Pong!")
bot.run(os.environ["DISCORD_TOKEN"])Creating a bot
Your application lives in the Discord developer portal; we only run the code. Create the application there, copy the token, and paste it into a variable here, never into a file.
- Create the application. In the Discord developer portal, New Application → Bot. Name it whatever the server will see.
- Enable the intents you use. Message Content and Server Members are privileged. If your code asks for one, switch it on under Bot in the portal too, or the bot won't connect. Prefix commands like !ping need Message Content.
- Copy the token once. Discord shows it a single time. Paste it straight into a BossHosting variable, not into your repo.
- Invite the bot. Use the OAuth2 URL generator with the bot scope and only the permissions you actually need.
File uploads
The file manager edits your bot's files right in the browser (they live in /home/container). Drag a folder in, or upload a zip and we'll unpack it. Up to 100 MB per file; disk is shared across your bots. Packages install on the server, so don't upload them.
# leave these out of uploads .venv/ venv/ __pycache__/ *.pyc .env
Installed packages live in hidden folders (.local for Python, node_modules for Node) next to your code. The Files tab hides the system ones; “Show hidden folders” brings them back if you need to clear them.
Packages and start command
List your packages in requirements.txt (Python) or package.json (Node) and they install before your bot starts, with the output in the console. They only reinstall when that file changes, so restarts stay fast. If the install fails, the bot doesn't start and the console says why.
# One package per line. They install when your bot starts, # and again only when this file changes. discord.py>=2.4 aiohttp requests==2.32.3
- Python
- Installed with pip install --user -r requirements.txt. Pin a version with == when an update could break your bot. Starts with python main.py.
- Node.js
- npm ci when there is a package-lock.json, otherwise npm install, both without dev dependencies. Starts with node index.js.
Your main file has a different name? Set the start command in the bot’s Settings tab, for example:
python bot.py python -m mybot node src/index.js npm start
Environment variables
Put tokens and settings in the Environment tab, not in your code. They're encrypted at rest and handed to your bot when it starts, so a change applies on the next Restart. Your code reads them by name.
import os
# Required: stops with a KeyError if it isn't set
discord_token = os.environ["DISCORD_TOKEN"]
# Optional, with a default
prefix = os.environ.get("PREFIX", "!")
# ... your bot code ...
bot.run(discord_token) # the variable, not the token in quotesThe name in your code must match the name in the Environment tab exactly, capitals included. Writing the token itself in quotes (bot.run("YOUR_BOT_TOKEN")) sends those words to Discord, which answers “invalid token”.
- DISCORD_TOKEN
- Your bot token. Masked in the dashboard and encrypted at rest. Never print it: anything your bot prints shows up in its console.
- CLIENT_ID
- Application ID - needed to register slash commands.
- DATABASE_URL
- The connection string for an outside database (hosted Postgres, MongoDB Atlas and so on), if you use one; we don't host databases. For SQLite, keep the file in your bot's folder.
- PORT
- Set to 8080 for you. Discord bots don't need a web server; bind to it only if a library starts one.
GitHub deployment
Deploy a bot straight from a GitHub repository, and again on every push. Connect GitHub from a bot's GitHub tab (or Settings, Linked accounts), choose which repositories BossHosting may read, then pick the repo and branch.
- Connect GitHub. You install the BossHosting app on your GitHub account and choose the repositories it may read. It can only read code: it never writes to your repos.
- Pick the repo and branch on the bot’s GitHub tab, and optionally a folder inside the repo if the bot lives in one.
- Push. Each push to that branch deploys: your repo’s files are added or updated, files you deleted from the repo are removed, and files your bot made itself (a database, saved data) are kept. A running bot restarts with the new code, installing packages first if they changed.
- Check the deploy log on the GitHub tab if something looks wrong. You can switch automatic deploys off and use Deploy now instead.
Troubleshooting
The console is the source of truth. Almost everything below shows up there first.
- "Improper token has been passed" or "An invalid token was provided" invalid token
- Your code isn't reading the variable. bot.run("YOUR_BOT_TOKEN") sends those exact words to Discord; use bot.run(os.environ["YOUR_BOT_TOKEN"]) in Python or client.login(process.env.YOUR_BOT_TOKEN) in Node, with the same name you gave it in the Environment tab, then Restart. If it's already like that, reset the token in the Discord Developer Portal and paste the new one.
- Bot starts, then immediately stops exit 1
- Usually the token is wrong or missing. Check DISCORD_TOKEN on the Environment tab, then read the last few lines in the Console: the real error is almost always there, not in the exit code. If you already pressed Start again, the run that failed is still shown above the new one.
- Killed without an error message exit 137
- Your bots ran out of memory and the kernel stopped one. Memory is shared by every bot on your account, so one hungry bot can push another over the limit. Check memory on each bot's Overview tab; if you're close to your plan's limit, cut down what your bots cache or move to a bigger plan. (A bot that ignores Stop is also ended this way, after 10 seconds.)
- Port already in use EADDRINUSE
- Only one process can listen on a port. Discord bots don't need a web server: they connect out to Discord, and nothing on the internet can reach your bot anyway. If a library starts one regardless, bind it to the PORT variable we set (process.env.PORT or os.environ["PORT"]) instead of a hardcoded number.
- Commands respond slowly or not at all rate limit
- Discord is rate limiting your bot, not us. Batch your API calls, cache guild data instead of fetching it again, and avoid editing messages in a loop. Most libraries log a warning when they hit a limit, so search the console for "rate limit".
- Packages won't install install
- Before each start, your requirements.txt or package.json is installed inside the bot's container, and the output is at the top of the console. If the install fails, the bot is stopped rather than started without its packages, and the bot page says why. Check the package names and versions, then press Start. Nothing is reinstalled when the file hasn't changed, so later starts are quick.