Skip to main content
All articles

Discord Webhook Errors: 400, 401, 403, 404, 429 — Causes & Fixes

Every common Discord webhook error explained: 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Unknown Webhook, and 429 rate limits — with exact causes and fixes.

discord webhook error400 bad request401 unauthorized404 unknown webhookinvalid webhook tokendiscord webhook not working429 rate limit

🇷🇺 Also available in Русский

Discord Webhook Errors: 400, 401, 403, 404, 429 — Causes & Fixes

Discord Webhook Not Working? Start Here

When a webhook fails, Discord returns an HTTP status code and usually a JSON error body with a code and message. Reading those two fields tells you exactly what’s wrong. This guide covers every status you’ll realistically hit, what causes it, and how to fix it.

First, a quick diagnostic. Run this from a terminal to see the raw status and message:

curl -i -H "Content-Type: application/json" \
     -d '{"content": "test"}' \
     "https://discord.com/api/webhooks/ID/TOKEN"
  • 204 No Content or 200 OK → the webhook works.
  • Anything else → match the code to the sections below.

400 — Bad Request (Invalid Form Body)

The most common error. Your JSON is malformed or breaks a Discord rule. The body usually looks like:

{ "message": "Invalid Form Body", "code": 50035, "errors": { ... } }

Causes and fixes:

  • Broken JSON — a trailing comma, single quotes instead of double, or an unescaped quote. Validate the payload in a JSON linter first.
  • Empty message — you must send at least one of content, embeds, or files. An empty {} is rejected with code 50006.
  • content over 2000 characters — split the message or move text into an embed description.
  • Embed limits exceeded — embed title ≤ 256, description ≤ 4096, max 25 fields, and a 6000-character total across all embeds. See the embed limits cheat sheet.
  • color as a hex string — Discord wants a decimal integer (5763719), not "#57F287". See embed colors.
  • Wrong Content-Type — send application/json (or multipart/form-data when uploading files).

The errors object pinpoints the exact field — read it carefully; it names the offending key.

401 — Unauthorized (Invalid Webhook Token)

{ "message": "Invalid Webhook Token", "code": 50027 }

The token portion of your webhook URL is wrong or no longer valid. This happens when:

  • The webhook’s token was regenerated in Discord (Edit Webhook → the URL changed). Old URLs immediately stop working.
  • You copied the URL incompletely or truncated the token.
  • You accidentally sent an Authorization header — webhook URLs authenticate via the token in the URL, so adding a bearer/bot token can cause conflicts. Don’t send one.

Fix: open the webhook in Server Settings → Integrations → Webhooks, click Copy Webhook URL, and use the fresh full URL.

403 — Forbidden

{ "message": "Missing Permissions", "code": 50013 }

The request reached Discord but isn’t allowed. Common causes:

  • IP block — Discord blocks some hosting/datacenter IP ranges (notably Roblox game servers). Your code works locally but fails on the server. Route through a proxy — see sending webhooks from Roblox.
  • Trying to mention @everyone without permission, or pinging in a channel where the webhook lacks rights.
  • Posting to a thread the webhook can’t access, or a forum channel without a thread_name. See threads and forums.

404 — Unknown Webhook

{ "message": "Unknown Webhook", "code": 10015 }

The webhook no longer exists. Unlike 401, this is permanent — there is no token to fix. It happens when:

  • The webhook was deleted in Discord.
  • The channel was deleted, which removes its webhooks.
  • There’s a typo in the webhook ID (the numeric part of the URL).

Fix: create a new webhook and update your application with the new URL.

429 — Too Many Requests (Rate Limited)

{ "message": "You are being rate limited.", "retry_after": 1.5, "global": false }

You exceeded the webhook’s limit — roughly 30 requests per minute per webhook. The response includes retry_after (seconds to wait) and the X-RateLimit-* headers.

Fixes:

  • Honor retry_after — wait that many seconds, then retry. Never hammer in a tight loop.
  • Batch messages — combine many updates into one payload instead of one request each.
  • Spread load — send different event types to separate webhooks in different channels.

Full strategies are in the rate limits guide.

Other Status Codes

CodeMeaningFix
405 Method Not AllowedWrong HTTP verbUse POST to send, PATCH/DELETE to edit/delete
413 Payload Too LargeFile over the upload limitFree webhooks allow 10 MB per request — compress or split
500 / 502 / 503Discord-side outageTransient — retry with backoff; check Discord status

Quick Reference Table

StatusDiscord codeOne-line causeFix
40050035 / 50006Malformed JSON or limits exceededValidate JSON, check embed limits
40150027Invalid/regenerated tokenCopy a fresh webhook URL
40350013IP block or missing permissionUse a proxy / fix permissions
40410015Webhook or channel deletedCreate a new webhook
429Rate limitedHonor retry_after, batch

Preventing Errors Before You Send

The fastest way to avoid 400s entirely is to build and validate your payload visually. The free Discord Webhook Builder enforces every limit as you type and generates guaranteed-valid JSON, so you can copy a payload that’s correct on the first try. For programmatic sends, log the full response body — Discord’s message and code fields almost always name the exact problem.