Skip to content

How to Host a Discord Bot 24/7 (discord.js & discord.py, 2026)

Keep a discord.js or discord.py bot online 24/7: deploy it with one command, keep the token secret and add the health check that stops it going offline.

Published
Reading time
6 min
On this page

Key takeaways

  • A Discord bot keeps a permanent connection to Discord, so it needs a host that never sleeps: use an always-on plan.
  • Store your bot token as an environment variable (DISCORD_TOKEN), never in your code or repository.
  • Add a tiny HTTP server on PORT so the platform can see your bot is alive; it's 6 lines in Node.js or Python.

To host a Discord bot 24/7, run it on a server that never sleeps, not on your own computer. A bot keeps an open connection to Discord's gateway, so if the process stops, the bot goes offline. On DockHosting, deploy a discord.js or discord.py bot with dock deploy, store the token in a DISCORD_TOKEN environment variable, and use the Hobby plan ($4/month), which is always on. The Free plan works for testing, but Free apps sleep after 1 hour without web visits, and Discord messages don't count as visits.

This guide deploys a discord.js (Node.js) or discord.py (Python) bot to DockHosting with one command. It covers the two things most guides skip: keeping the token secret and the health check that keeps the bot running.

Can you host a Discord bot for free?

A website only needs to be awake when someone visits it. A Discord bot is different: it holds an open connection to Discord's gateway and receives events (messages, slash commands, joins) through it. If the process stops, the bot shows as offline.

That's why hosts that sleep idle apps aren't a good fit for production bots. On DockHosting, Free-plan apps sleep after 1 hour without web visits, and messages on Discord don't count as visits. Hobby ($4/month) is always on, which is what a 24/7 bot needs. Free is still fine for building and testing.

1. Create the bot and get a token

  1. Open the Discord Developer Portal and click New Application.
  2. Under Bot, copy the token. Treat it like a password.
  3. Under OAuth2 → URL Generator, select the bot and applications.commands scopes, pick permissions, and open the generated URL to invite the bot to your server.

2a. A discord.js bot (Node.js)

bash
npm init -y
npm install discord.js
js
// index.js
import { createServer } from "node:http";
import { Client, Events, GatewayIntentBits } from "discord.js";
 
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
 
client.once(Events.ClientReady, (c) => console.log(`Logged in as ${c.user.tag}`));
 
client.on(Events.InteractionCreate, async (interaction) => {
  if (interaction.isChatInputCommand() && interaction.commandName === "ping") {
    await interaction.reply("Pong!");
  }
});
 
client.login(process.env.DISCORD_TOKEN);
 
// Health check: the platform checks that the app answers on PORT.
createServer((_, res) => res.end(client.isReady() ? "ok" : "starting"))
  .listen(process.env.PORT || 3000);

Add "type": "module" and a start script to package.json:

json
{
  "type": "module",
  "scripts": { "start": "node index.js" }
}

Register the /ping command (once)

Slash commands have to be registered with Discord before they show up. Copy the Application ID from the portal's General Information page, then run this script once (and again whenever you change your commands):

js
// register-commands.js: node register-commands.js
import { REST, Routes, SlashCommandBuilder } from "discord.js";
 
const commands = [new SlashCommandBuilder().setName("ping").setDescription("Replies with Pong!").toJSON()];
 
const rest = new REST().setToken(process.env.DISCORD_TOKEN);
await rest.put(Routes.applicationCommands(process.env.DISCORD_CLIENT_ID), { body: commands });
console.log("Registered /ping");

Global commands can take a few minutes to appear in your server.

2b. A discord.py bot (Python)

text
# requirements.txt
discord.py
aiohttp
python
# bot.py
import os
import discord
from aiohttp import web
 
async def health(request):
    return web.Response(text="ok")
 
class Bot(discord.Client):
    async def setup_hook(self):
        # Runs once at startup (on_ready can fire again after reconnects).
        # Health check: the platform checks that the app answers on PORT.
        app = web.Application()
        app.router.add_get("/", health)
        runner = web.AppRunner(app)
        await runner.setup()
        await web.TCPSite(runner, "0.0.0.0", int(os.environ.get("PORT", 8080))).start()
 
    async def on_ready(self):
        print(f"Logged in as {self.user}")
 
Bot(intents=discord.Intents.default()).run(os.environ["DISCORD_TOKEN"])

Python projects are detected from requirements.txt. Set the start command to python bot.py in the project settings.

3. Why the health check matters

A bot doesn't need a web server for Discord, but the hosting platform needs a way to tell that your process is alive. DockHosting expects an app to answer on the PORT it provides. Apps that never listen are treated as failed starts, and slow apps get up to 5 minutes. The 6-line server above answers that check, and it doubles as a quick status page for you.

4. Deploy

bash
# macOS / Linux
curl -fsSL https://cli.dockhosting.dev/install.sh | sh
# Windows: irm https://cli.dockhosting.dev/install.ps1 | iex
 
dock login
dock deploy

Then add DISCORD_TOKEN in the project's environment variables and restart:

bash
dock restart
dock logs     # look for "Logged in as …"

The bot shows as online in your server. To deploy on every push instead, connect your GitHub repository from the dashboard.

5. Keep it online and healthy

  • Use Hobby or higher so the app never sleeps.
  • Watch the logs with dock logs. A supervisor restarts the process if it crashes.
  • Store data properly. Attach managed PostgreSQL, MongoDB or Redis instead of writing JSON files, because the container's disk isn't the place for long-lived data.
  • Register slash commands once, not on every start, to avoid hitting Discord's rate limits.

Common problems

SymptomFix
TokenInvalid / LoginFailureDISCORD_TOKEN is missing or wrong. Check the variable and restart.
Bot online, but ignores messagesEnable the intents you use in the portal (e.g. Message Content) and in code.
Deploy marked as failedNothing is listening on PORT. Add the health check.
Bot goes offline after a whileThe app is on the Free plan and slept. Move to Hobby.

Building something bigger? Read what a PaaS is and when to use one, or add a database with DATABASE_URL.

Related: Free backend hosting: which hosts sleep · Host a Telegram bot for free

Frequently asked questions

Can I host a Discord bot for free?

You can deploy and test it on DockHosting's Free plan, but Free apps sleep after 1 hour without web visits. A bot gets its messages over a connection to Discord, not web visits, so it would go offline. For a bot that stays online 24/7, use Hobby at $4/month, which is always on.

Why does my bot go offline when I close my laptop?

The bot is a program that has to keep running to stay connected to Discord. When your computer sleeps, the program stops. Hosting it on a server keeps it running all the time.

Where do I put my Discord bot token?

In an environment variable such as DISCORD_TOKEN, set in your project's environment variables in the dashboard. Read it with process.env.DISCORD_TOKEN or os.environ['DISCORD_TOKEN']. If a token is ever committed or leaked, reset it in the Discord Developer Portal.

Can my bot use a database?

Yes. Attach a managed PostgreSQL, MongoDB or Redis database to the project and read DATABASE_URL, MONGODB_URI or REDIS_URL from the environment.

  • Discord bot
  • Node.js
  • Python
  • Hosting
  • Tutorial

Written by Doughmi ILYAS

Doughmi builds DockHosting, the developer-first platform behind dock deploy: the build system, the managed databases and the dashboard. On this blog: guides to shipping apps without running servers, written with the commands the platform actually ships.

Summarize with

Share

All posts

Create an account, run dock deploy, and get a live HTTPS URL in minutes.