Blog

Website downtime alerts to Discord: webhook setup, useful messages, separate channels and no spam

How to send website downtime alerts to Discord: create a webhook, design messages people can act on, split critical from info channels and keep recoveries from spamming.

To send website downtime alerts to Discord, create a webhook in the target channel, then have your uptime monitor POST a JSON message to that webhook URL whenever a check changes state. A good alert names the failing check, the error, the affected regions and the start time, and links to a runbook. Route outages and informational events to separate channels, and send one message per state change instead of one per failed check.

This guide covers the setup, the message format and the parts most setups get wrong: noisy recoveries, alert floods during a shared outage and critical pings that drown in routine chatter.

How to set up website downtime alerts to Discord, step by step

  1. Create two channels, for example #alerts-critical and #alerts-info.
  2. Create one webhook per channel and store each URL as a secret.
  3. Send a test message with curl to confirm the webhook works.
  4. Define a message format with an embed: title, error, regions, start time and links.
  5. Configure your monitor to notify only on state changes (up to down, down to up).
  6. Decide what pings people: a role mention in the critical channel, no mentions anywhere else.
  7. Set channel notification settings so critical alerts always notify and info alerts stay quiet.

Creating a Discord webhook and testing it

In Discord, open the channel settings (the gear icon next to the channel), go to Integrations, then Webhooks, and click New Webhook. Give it a recognizable name such as "Uptime" and copy the URL. It looks like https://discord.com/api/webhooks/ID/TOKEN.

Treat that URL as a secret. Anyone who has it can post into your channel, including messages that look like real alerts. Keep it in your secret store, not in a public repository. If it leaks, delete the webhook and create a new one.

Test it from a terminal before wiring up any monitoring:

curl -H "Content-Type: application/json" \
  -d '{"content":"Webhook test from the uptime setup"}' \
  "https://discord.com/api/webhooks/ID/TOKEN"

A successful call returns HTTP 204 and the message appears in the channel. If you get HTTP 429, Discord is rate limiting the webhook; the response contains a retry_after value. Rate limits are one more reason to send state changes rather than every check result.

What a useful downtime alert contains

The person reading the alert is often on a phone, half awake or in the middle of something else. The message has to answer five questions without a click:

  • What is down: the monitor name and the exact URL or endpoint.
  • How it failed: status code, timeout, TLS error or DNS failure.
  • Where it fails: how many probe regions see the failure. One of four is a different situation than four of four.
  • Since when: a timestamp, ideally rendered in the reader's local time.
  • What next: a link to the runbook, the dashboard or the status page.

Discord embeds are well suited for this. Fields keep the facts scannable, and the <t:UNIX:R> syntax renders a timestamp as relative time ("5 minutes ago") in each reader's own timezone. Here is a complete payload for a critical alert:

{
  "content": "<@&123456789012345678> Checkout API is down",
  "allowed_mentions": { "roles": ["123456789012345678"] },
  "embeds": [{
    "title": "DOWN: Checkout API",
    "url": "https://monitoring.example.com/monitors/checkout-api",
    "color": 15158332,
    "fields": [
      { "name": "Check", "value": "GET https://api.example.com/health" },
      { "name": "Error", "value": "HTTP 503 after 2 retries", "inline": true },
      { "name": "Regions failing", "value": "4 of 4", "inline": true },
      { "name": "Down since", "value": "<t:1718000000:R>", "inline": true },
      { "name": "Runbook", "value": "https://wiki.example.com/runbooks/checkout" }
    ],
    "timestamp": "2024-06-10T06:13:20Z"
  }]
}

A few details matter here. The color is a decimal integer: 15158332 is red (#E74C3C), 3066993 is green (#2ECC71), 15844367 is yellow (#F1C40F). The role mention sits in content, because mentions inside embeds do not notify anyone. And allowed_mentions restricts pings to that one role, so an error message that happens to contain @everyone cannot ping the whole server.

What to leave out: raw JSON from the monitor, full response bodies and stack traces. Put a link to them instead. Discord caps message content at 2000 characters, and a wall of text slows down the one decision the reader has to make.

Separate channels for critical and info alerts

One channel for everything fails in a predictable way. SSL warnings, latency spikes and staging failures arrive several times a day, people mute the channel, and the real outage lands in a muted channel. Split by required action, not by system: a channel that only receives events someone must act on now can stay loud, everything else goes where it can stay quiet.

A setup that works for most small teams:

  • #alerts-critical: customer-facing production checks are down in multiple regions. Role mention for the on-call group, channel notifications set to "All messages".
  • #alerts-info: certificates expiring in 14 days, elevated response times, single-region failures, recoveries of non-critical checks. No mentions, channel muted by default.
  • #alerts-staging (optional): anything outside production. Nobody gets notified.

For the info channel, send "allowed_mentions": { "parse": [] } with every message so nothing in it can ever ping anyone. Each channel gets its own webhook, so the routing decision lives in your monitoring config, not in Discord.

Avoiding alert spam: state changes, recovery messages and grouping

Alert on state change, not on every failed check

If a check runs every minute and the site is down for 40 minutes, a naive integration posts 40 messages. Send one message when a monitor goes from up to down, and one when it goes from down to up. Combine this with retries and multi-region confirmation so a single dropped packet never becomes a state change; the details are in our guide on reducing false positive alerts with retries and multi-region checks.

Edit the original alert on recovery

Discord webhooks can edit their own messages. Post the down alert with ?wait=true appended to the webhook URL, and Discord returns the created message including its id. Store it. On recovery, patch that message:

curl -X PATCH -H "Content-Type: application/json" \
  -d '{"content":"","embeds":[{"title":"RESOLVED: Checkout API","color":3066993,"description":"Down for 12 minutes, recovered in all regions."}]}' \
  "https://discord.com/api/webhooks/ID/TOKEN/messages/MESSAGE_ID"

Now the channel history shows each incident once, in its final state, instead of a red message followed somewhere later by a green one. Edits do not trigger notifications, though. If people need to know the outage is over, post a short recovery line as well and add "flags": 4096 to send it silently: it shows up in the channel without pushing to phones.

Group related failures

When a shared dependency fails, such as a database, a load balancer or DNS, ten monitors go down within the same minute. Ten red messages with ten role mentions tell the team less than one message saying "10 monitors down, all behind lb-eu-1". Ways to get there:

  • Collect state changes for 30 to 60 seconds before sending and post one message listing all affected checks.
  • Use monitor dependencies or tags, so checks behind a failed parent are suppressed or folded into the parent's alert.
  • Use a forum channel for incidents: the webhook creates a new post via thread_name, and follow-up messages go into it via thread_id. The channel list then shows one entry per incident.

Reminders instead of repeats

A long outage may need a nudge, not a flood. Re-post a reminder after a fixed interval, for example every 30 minutes while still down, and only in the critical channel. Anything more frequent trains people to ignore the channel.

A minimal self-hosted check that posts to Discord

For a side project, a cron job with curl is enough to start. This script keeps the last state in a file and posts only when it changes:

#!/usr/bin/env bash
URL="https://example.com/health"
WEBHOOK="https://discord.com/api/webhooks/ID/TOKEN"
STATE_FILE="/var/tmp/uptime-example.state"

code=$(curl -s -o /dev/null -w '%{http_code}' --max-time 10 "$URL")
if [ "$code" = "200" ]; then new="up"; else new="down"; fi
old=$(cat "$STATE_FILE" 2>/dev/null || echo "up")

if [ "$new" != "$old" ]; then
  if [ "$new" = "down" ]; then
    title="DOWN: example.com"; color=15158332
  else
    title="RECOVERED: example.com"; color=3066993
  fi
  payload=$(printf '{"embeds":[{"title":"%s","description":"HTTP %s from %s","color":%s}]}' \
    "$title" "$code" "$URL" "$color")
  curl -s -H "Content-Type: application/json" -d "$payload" "$WEBHOOK"
  echo "$new" > "$STATE_FILE"
fi

A status of 000 means curl got no HTTP response at all: timeout, DNS failure or refused connection. Know the limits of this approach: it checks from one location, has no retries, and if the machine running it goes down, you get silence instead of an alert. That is fine for a hobby site and a real gap for anything with paying customers.

When Discord alone is not enough

Discord is a good place for the team to see what is happening. It is not a reliable pager. Phones in do-not-disturb mode, muted servers and app notification settings all decide whether a push ever arrives, and none of them are under your control. For outages outside working hours, route critical alerts additionally to a channel built for waking people, such as SMS or a paging service, and to whoever is on call that night. Our article on on-call rotation for small teams covers which alerts deserve a night-time page.

Using a monitoring service instead of a script

A hosted monitor removes the single-location problem and the "who watches the watcher" gap. m0nitor is one option: it checks websites, APIs and servers from probes in several regions and supports Discord as one of its alert channels and integrations, alongside Slack, email, SMS, PagerDuty and others. With alert workflows you can decide per event whether to notify a channel, create an incident or call a webhook, which maps directly to the critical and info split described above. Whatever tool you use, the principles stay the same: state changes only, one message per incident, loud channels kept for real outages.

FAQ

How do I get a Discord webhook URL?

Open the channel settings, go to Integrations, then Webhooks, and create a new webhook. Copy the URL and paste it into your monitoring tool or script. You need the "Manage Webhooks" permission on that channel.

Can a Discord alert ping only the on-call people?

Yes. Create a role such as @oncall, put its mention in the message content as <@&ROLE_ID> and allow only that role in allowed_mentions. Mentions inside embeds do not notify, so the role mention has to be in the content field.

Why do I get so many Discord messages for one outage?

Your monitor is most likely sending a message for every failed check instead of only on state changes, or several monitors behind the same failed dependency each post their own alert. Switch to state-change notifications, add retries and group related failures into one message.

Should recovery messages go to the same channel as the down alert?

Yes, but without a ping. Either edit the original alert to show it as resolved or post a silent message with "flags": 4096. That keeps the incident readable in one place without waking anyone for good news.

Product

  • Pricing
  • Features
  • Integrations
  • Security
  • Free network check

Features

  • Uptime monitoring
  • Status pages
  • Alert workflows
  • Incident management
  • Dependencies
  • AI assistant
  • Global infrastructure
  • On-call schedules
  • Enterprise SSO

Use cases

  • Websites for free
  • Cron jobs
  • SSL certificates
  • Databases
  • IP blacklists
  • GDPR compliance

Resources

  • What is a status page?
  • Documentation
  • API
  • MCP server
  • Monitoring glossary
  • Free tools
  • SLA calculator
  • SSL checker
  • DNS lookup
  • Blog
  • Changelog
  • About
  • Contact

Compare

  • Free uptime monitoring
  • UptimeRobot
  • Better Stack
  • Pingdom
  • StatusCake
  • Uptime Kuma
  • Hyperping
  • Atlassian Statuspage
  • Instatus
  • Cachet
  • Freshping