python bot.py in a terminal is fine while you build. The moment you close the terminal, the bot goes offline. To keep a discord.py bot running 24/7, it needs a machine that never sleeps, restarts it when you push a change, and keeps your token out of the code.
This guide shows how to host a discord.py bot 24/7: it writes a small discord.py 2 bot and puts it online on a free Python deployment. The same steps work for any existing bot.
The bot
Two files. requirements.txt:
discord.py>=2.4 And main.py:
import os
import discord
from discord import app_commands
intents = discord.Intents.default()
client = discord.Client(intents=intents)
tree = app_commands.CommandTree(client)
@tree.command(name="ping", description="Replies with the bot latency")
async def ping(interaction: discord.Interaction):
await interaction.response.send_message(f"Pong! {round(client.latency * 1000)} ms")
@client.event
async def on_ready():
await tree.sync()
print(f"Online as {client.user}", flush=True)
client.run(os.environ["DISCORD_TOKEN"]) Three choices here make hosting painless:
os.environ["DISCORD_TOKEN"]: the token is never in a file you upload or commit. If the variable is missing, Python fails with a clearKeyErrorinstead of a confusing LoginFailure.Intents.default(): no privileged intent, so no Used disallowed intents crash. If you use prefix commands, addintents.message_content = Trueand enable Message Content Intent in the Developer Portal.flush=True: Python buffers output when it is not attached to a terminal, so prints can show up late in a web console. Bot-Hosting already runs Python with-u(unbuffered); the flag keeps the code portable.
Get the token from the Discord Developer Portal: your application, Bot, Reset Token. Invite the bot with the bot and applications.commands scopes from OAuth2 > URL Generator.
Host the discord.py bot on a free Python deployment
Sign in to Bot-Hosting.net with Discord and start a new deployment:
- What are you deploying? Application, then Python. The default is the newest version; if one of your dependencies does not support it yet, pick 3.13.
- Source: Archive with a
.zipof your folder, or GitHub for a repository, public or private. See deploy a Discord bot from GitHub. - Click Launch deployment. The entry file defaults to
main.py; if your bot starts frombot.py, change Entry file in the Startup tab.
On every start, the deployment installs requirements.txt with pip, then runs your entry file. No virtualenv to manage, no pip install to remember.
Add the token and start
In the Environment tab, click Add variable: key DISCORD_TOKEN, value your token, Secret ticked. Saving restarts the deployment.
The Console shows pip, then:
Online as MyBot#1234 Run /ping in Discord. The command can take a few seconds to appear the first time, while Discord registers it.
Things that break discord.py bots on a server
Blocking calls freeze the bot
discord.py runs on asyncio. A time.sleep(10) or a requests.get(...) inside a command blocks the whole event loop: the bot stops answering and Discord logs heartbeat warnings like Shard ID None heartbeat blocked for more than 10 seconds. Use await asyncio.sleep() and aiohttp instead, or push the blocking work to a thread:
import asyncio
result = await asyncio.to_thread(slow_function, arg) SQLite and JSON files
Writing to a local data.json or bot.db works on a deployment: the disk is persistent and survives restarts. Keep in mind:
- files the bot writes exist only on the server, so do not overwrite them with an old copy from your PC;
- for anything serious, use a real database. A MySQL, PostgreSQL, MongoDB or Redis deployment lives in the same account, and backups cover it.
Memory
The free plan has 256 MB of RAM, enough for most small bots. Intents.members with large servers and a full member cache is what usually blows it. If the Console says the app was killed for using more memory than it has, cache less or move to a paid plan from 1 GB.
Updating the bot
- From your editor: the Bot-Hosting CLI syncs the files you changed and restarts.
bh deploy --watchdoes it on every save. - From GitHub: enable Auto-pull at restart in the deployment’s GitHub tab, push, then restart.
Free, with one condition
The free plan has no card and no sleep timer. It is renewed by hand every 4 days with Renew now, which keeps abandoned bots from holding resources forever. Paid plans renew on their own and pool RAM across all your deployments.
Skip the code
Prefer a complete bot? Red is one of the most popular open-source discord.py bots: moderation, mod logs, custom commands, economy, trivia and thousands of community plugins.