Your bot works. It answers /ping, it greets new members, and it goes offline the moment you close your laptop. Running a Discord bot 24/7 means running it on a machine that never sleeps, and that machine should not be your PC.
This guide shows how to host a Discord bot 24/7 for free: a discord.js v14 bot, from zero to online around the clock, in about ten minutes. Every step is code or a command, so it still works when the dashboard changes.
What hosting a Discord bot 24/7 actually needs
A Discord bot is a long-running process holding a WebSocket connection to Discord’s gateway. To stay online it needs:
- a process that never stops, so no “sleep after 30 minutes of inactivity” timer;
- a restart when the process crashes or the machine reboots;
- your token stored somewhere safer than the source code.
Free “web” hosts that spin down idle apps are built for websites that wake up on an HTTP request. A Discord bot never receives one, so it falls asleep and stays asleep. That is why the old trick of pinging a Replit URL every five minutes existed. You do not need any of that on a host built for bots.
Step 1: create the application and copy the token
- Open the Discord Developer Portal and click New Application.
- In Bot, click Reset Token and copy it. Discord shows it once.
- In OAuth2 > URL Generator, tick
botandapplications.commands, pick the permissions your bot needs, and open the generated URL to invite the bot to your server.
Treat the token like a password. Anyone who has it controls your bot.
Step 2: write the bot
Create a folder with two files. package.json:
{
"name": "my-bot",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"discord.js": "^14.16.0"
}
} And index.js:
const { Client, Events, GatewayIntentBits } = require('discord.js');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.once(Events.ClientReady, async (c) => {
await c.application.commands.set([
{ name: 'ping', description: 'Replies with the bot latency' }
]);
console.log(`Online as ${c.user.tag}`);
});
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
await interaction.reply(`Pong! ${client.ws.ping} ms`);
}
});
client.login(process.env.DISCORD_TOKEN); Two details matter for hosting:
- The token comes from
process.env.DISCORD_TOKEN. It never sits in a file, so it never ends up on GitHub. Discord scans public repositories and resets any bot token it finds there, which is the most common cause of a TokenInvalid error. - Only the
Guildsintent. Slash commands need nothing more. If you addMessageContentorGuildMemberslater, enable them in the portal first, or you will meet Used disallowed intents.
Test it locally if you like:
npm install
DISCORD_TOKEN=your-token node index.js Do not commit node_modules. Add a .gitignore with node_modules and .env in it.
Step 3: create a free deployment
Sign up on Bot-Hosting.net with Discord. The free plan gives you 256 MB of RAM, which is plenty for a discord.js bot in a few dozen servers, with no card and no sleep timer.
From the dashboard, start a new deployment:
- What are you deploying? Choose Application, then Node.js. The default version is Node 24, which discord.js v14 supports.
- Source: pick Archive and drop a
.zipof your folder (withoutnode_modules), or GitHub if your code is in a repository. The GitHub guide covers that path. - Click Launch deployment. The entry file defaults to
index.js; if your bot starts from another file, change Entry file later in the Startup tab.
On every start, the deployment runs npm install when it finds a package.json, then node index.js. You never upload node_modules yourself.
Step 4: add the token
Open the deployment’s Environment tab, click Add variable, set the key to DISCORD_TOKEN, paste the token as the value and tick Secret. Saving restarts the deployment so the new value reaches your code.
Open Console. You should see npm install the packages, then:
Online as MyBot#1234 Type /ping in your server. Your bot now answers whether your computer is on or not.
Step 5: ship changes without re-uploading
Uploading a new zip for every change gets old fast. Two better options:
From your editor: the Bot-Hosting CLI pushes only the files you changed and restarts the bot.
npm i -g bot-hosting bh login bh link bh deploy --watchFrom GitHub: with Auto-pull at restart on in the deployment’s GitHub tab, push your commit and restart. The deployment fetches the branch before starting.
Keeping it online
- The free plan is renewed by hand every 4 days, with one click on Renew now. It stays free; the renewal only proves someone still uses the bot. Paid plans start at 1 GB of RAM and renew on their own.
- Watch the memory. A bot that caches every member of large servers grows. If the console shows the process was killed for using too much memory, trim the caches with
makeCacheandsweepers, or move to a bigger plan. - Read the crash, do not guess. When the bot stops, the Console shows what went wrong in plain English (bad token, missing intent, missing module, out of memory), and Ask AI can read the logs and propose the fix.
FAQ
Is it really free?
Yes. The free plan has no card, no trial end and no sleep timer. The only condition is the renewal click every 4 days. If you miss it, your deployment is suspended until you renew, and deleted if you do not renew within 3 days.
Can I host more than one bot?
The free plan has one slot. Paid plans share one pool of RAM between all your deployments, from 2 slots on Starter.
Does it work with TypeScript?
Yes. Compile to JavaScript and deploy the output, or pick the Bun runtime, which runs index.ts directly.
Skip the code
Want a full-featured moderation bot instead of writing one? Deploy a tested open-source bot from the template catalogue, then add your token.