Free and open source · MIT

Discord Webhook Tester

Discord Webhook Tester checks that a Discord webhook works and helps you design the message it posts. Use the CLI in scripts and CI, or run the web form to build embeds visually with a live preview. It runs on your own machine, so the webhook URL, which is a credential, never reaches a third-party website.

Discord Webhook Tester embed builder next to a live preview of the message

What Discord Webhook Tester does

Discord Webhook Tester is a free, MIT-licensed CLI and local web form that posts a test message to a Discord webhook URL and builds the embed it sends. It does two things: it proves the webhook is alive, and it shows you what your message will look like before a channel full of people sees it.

Feature What it means
One-command test discord-webhook-tester send posts a ready-made test embed, with no options to fill in.
Embed builder Title, description, colour, author, fields, images, footer and timestamp, as CLI options or in the form, up to 10 embeds per message.
Live preview The form renders your draft the way Discord will, and sent messages land in the mock channel with their delivery status.
Export Copy the same message as a JSON payload, a curl command or a CLI command.
Local validation Discord's limits are checked before anything is sent, so a typo fails instantly instead of after a round trip.
Readable errors Nested Discord error responses become lines like embeds.0.title: Must be 256 or fewer in length.
Threads, forums, files Post into a thread, create a forum post, attach files, or send without notifications.

How do I test a Discord webhook?

Set DISCORD_WEBHOOK_URL to the webhook's URL and run discord-webhook-tester send: it posts a ready-made embed to the channel and prints the status Discord answered with. Nothing has to be installed if you run it with uv:

Terminal
export DISCORD_WEBHOOK_URL='https://discord.com/api/webhooks/<id>/<token>'

uvx --from git+https://github.com/webhooker-eu/discord-webhook-tester \
  discord-webhook-tester send

Or install it as a command:

Terminal
uv tool install git+https://github.com/webhooker-eu/discord-webhook-tester
# or
pipx install git+https://github.com/webhooker-eu/discord-webhook-tester

discord-webhook-tester send

Or run the published image, with nothing else on your machine:

Terminal
# Web form on http://localhost:8080
docker run --rm -p 127.0.0.1:8080:8080 ghcr.io/webhooker-eu/discord-webhook-tester

# Or as the CLI
docker run --rm -e DISCORD_WEBHOOK_URL ghcr.io/webhooker-eu/discord-webhook-tester \
  send --content 'Hello from Docker'

Get the webhook URL in Discord under Server Settings → Integrations → Webhooks → New Webhook → Copy Webhook URL. Prefer the DISCORD_WEBHOOK_URL variable over passing it as an argument: arguments end up in your shell history.

How do I send a Discord embed from the command line?

Every part of a Discord embed has an option, so a deploy notification is one command in your pipeline:

Terminal
discord-webhook-tester send \
  --title 'Build #128 passed' \
  --description 'All **42** tests are green.' \
  --url 'https://ci.example.com/builds/128' \
  --color green \
  --author 'CI' \
  --field 'Branch|main|inline' \
  --field 'Duration|3m 12s|inline' \
  --footer 'ci.example.com' \
  --timestamp now

Colours accept #RRGGBB, a decimal integer or a name such as blurple, green or red. Fields take 'NAME|VALUE|inline' and repeat up to 25 times. A raw payload from a file or stdin works too, with --payload-file, and any other options are layered on top of it.

What are Discord's webhook message limits?

A webhook message is capped at 2000 characters of content and 10 embeds, and all embeds together may not exceed 6000 characters. Discord enforces the rest per embed part, and a message that breaks any of them comes back as a 400 with a nested error body. Discord Webhook Tester checks every one of these locally, before the request leaves your machine, so a too-long field fails instantly instead of after a round trip.

Message part Limit
Message content 2000 characters
Embeds per message 10
All embeds in one message 6000 characters in total
Embed title 256 characters
Embed description 4096 characters
Fields per embed 25
Field name / field value 256 / 1024 characters
Embed footer text 2048 characters
Embed author name 256 characters
Override username 80 characters
File attachments per message 10

The limits come from Discord's own reference: the embed limits and the Execute Webhook endpoint. Rate limits are per webhook and Discord returns the wait in the response, so a short 429 is retried twice, with the number of attempts printed, instead of failing your pipeline step on the first try. The error codes, rate limit headers and the invalid request limit are covered in the Discord webhooks guide.

The web form

discord-webhook-tester serve --open starts a local form on 127.0.0.1:8080. Paste the webhook URL, build the message, press Send message, and read what Discord answered. The draft is kept in your browser's local storage; the webhook URL is stored only if you tick Remember the URL in this browser.

Why run the tester locally instead of pasting the URL into a website?

A Discord webhook URL is a credential: anyone holding it can post to that channel under the webhook's name, and it cannot be rotated without creating a new webhook. A browser-based tester sends that credential to its own server, where it may be logged. Discord Webhook Tester runs on your machine and talks to discord.com directly.

Discord Webhook Tester Browser-based tester
Where the webhook URL goes Your machine, then Discord The website's server, then Discord
Runs in CI Yes, exit codes and --json No, it is a page in a browser
Account needed No Varies by site
Limits checked before sending Yes, all of the table above Usually not: Discord answers with the error
Works offline The embed builder and preview do No

Using it in CI

The CLI is built for scripts: it reads the URL from an environment variable, prints JSON on request, and returns an exit code you can branch on.

Terminal
# Confirm the webhook still exists, without posting anything
discord-webhook-tester info --json || echo 'The Discord webhook is broken'

# See the JSON that would be sent
discord-webhook-tester send --title 'Hello' --color '#5865F2' --dry-run
Exit code Meaning
0 The message was sent, or the webhook is valid.
1 Discord rejected the request, or could not be reached.
2 Invalid input: a bad URL, a payload over Discord's limits, an unreadable file.

Discord webhooks and the rest of your webhook traffic

A Discord webhook is an outgoing notification: your script posts a message and Discord shows it. That is the opposite direction from the webhooks a provider sends you, where a missed request means a missed payment or a missed order. If you also relay provider events into a Discord channel, the fragile part is not the message. It is whether the event reached your code at all.

Webhooker handles that half: one ingest URL receives the provider's events, verifies the signature, stores each one and delivers it to your services with retries and replay. Start with what a webhook is if the two directions still blur together.

Frequently asked questions

How do I test a Discord webhook?

Copy the webhook URL from Server Settings, Integrations, Webhooks, then run discord-webhook-tester send with DISCORD_WEBHOOK_URL set. A ready-made embed is posted to the channel, and the exit code tells you whether Discord accepted it. No message is sent by the info command, which only confirms that the webhook exists and shows its name, channel and server.

Where do I find my Discord webhook URL?

In Discord: Server Settings, then Integrations, then Webhooks, then New Webhook and Copy Webhook URL. It looks like https://discord.com/api/webhooks/<id>/<token>. Treat it as a credential: anyone who has it can post to that channel, so keep it in an environment variable rather than in code or shell history.

Can I build an embed without writing JSON?

Yes. Run discord-webhook-tester serve to open a local web form that looks like a Discord channel: set the title, description, colour, author, fields, images, footer and timestamp, and the preview renders the message as Discord will show it. The JSON, curl and CLI tabs give you the same message in a form you can paste into your code.

Why is Discord rejecting my webhook message?

Usually a limit: 2000 characters of content, 6000 characters across all embeds, 25 fields per embed, 10 embeds per message. The tool checks those locally before sending, and turns Discord's nested error response into one line per problem, such as embeds.0.title: Must be 256 or fewer in length. A 404 means the webhook was deleted; a 401 means the token in the URL is wrong.

Does the webhook URL leave my machine?

Only to Discord. The CLI and the local server parse the URL into an id and a token and rebuild the request from those parts, so nothing is sent anywhere else, and the form stores the URL in your browser only if you tick the box. That is the difference from pasting a webhook URL into a public tester website.

Can I use it in CI?

Yes. It reads the URL from an environment variable, prints machine-readable output with --json, and returns 0 only when Discord accepted the request, so a pipeline step can fail on a broken webhook. Files, threads, forum posts and silent messages are supported for the notification itself.

Further reading

More open-source tools

Everything we publish lives in the webhooker-eu GitHub organisation, and the full list with a short description of each is on the open-source tools page.

When the testing is done, the events still have to arrive.

Webhooker is the hosted side of the same problem: one EU-hosted ingest URL for any provider, signatures verified before a payload is accepted, every event stored, retried and replayable. Free for 10,000 events a month.