Most bots only connect out to Discord and never need this. If yours has to receive something (a vote webhook from a bot list, a GitHub webhook, a small status page), your server already has a public port for it.
Your address and port
Open Network in the panel. The address and port there are reachable from the internet. Your program gets the port as the SERVER_PORT environment variable, so it never needs typing into your code.
Listen on it
Listen on 0.0.0.0 (every interface) and SERVER_PORT. Not the address shown on the Network page: inside the server that address does not exist, and binding to it fails.
# Python, aiohttp, next to a discord.py bot
import os
from aiohttp import web
async def vote(request):
data = await request.json()
print("vote from", data.get("user"))
return web.Response(text="ok")
async def start_web():
app = web.Application()
app.router.add_post("/vote", vote)
runner = web.AppRunner(app)
await runner.setup()
await web.TCPSite(runner, "0.0.0.0", int(os.environ["SERVER_PORT"])).start()
# call `await start_web()` from your bot's setup_hook
// JavaScript, Node's own http module, next to a discord.js bot
const http = require("node:http");
http.createServer((req, res) => {
if (req.method === "POST" && req.url === "/vote") {
let body = "";
req.on("data", (chunk) => (body += chunk));
req.on("end", () => { console.log("vote:", body); res.end("ok"); });
} else {
res.statusCode = 404;
res.end();
}
}).listen(Number(process.env.SERVER_PORT), "0.0.0.0");
Run the web server in the same process as the bot, as above. A second program in the same server needs your start script to launch both.
Then give the other service the address: http://, the address and port from the Network page, and your path, for example http://203.0.113.10:25570/vote.
What you do not get
- HTTPS. The port speaks whatever your program speaks, which is plain HTTP in the examples above. Most bot list webhooks accept an
http://URL. Services that insist on HTTPS need a tunnel: a Cloudflare Tunnel run from inside your bot (cloudflaredconnects out, so nothing else is needed) gives you an HTTPS address on a domain you own. - A domain name. The address is an IP and a port. Pointing your own domain at it works for HTTP, as long as the port is part of the URL.
- Ports 80 and 443. You get the one port on the Network page.
Check the sender
Anyone who finds the address can send requests to it. Bot lists and GitHub let you set a secret that is sent with each webhook: check it before trusting what arrived, and reply 401 when it does not match.
Something here wrong or out of date? Tell us and it gets fixed.