DWEEB
Reference · Limits & rate limits

Discord Webhook Limits: Rate, Size and Components

Webhook failures usually trace back to one of three separate ceilings: the size of a single message, the speed you call one webhook, and how fast one channel accepts webhook deliveries. Knowing which ceiling you hit turns a mystery 400 or 429 into a five-minute fix.

Message size and component ceilings

The numbers below are the ones DWEEB validates against before send; the Components V2 rows are generated from the same constants the editor uses, so this table cannot drift from the product.

Message size and component ceilings
WhatLimitApplies to
Plain message content2,000 characterscontent field (legacy messages)
Combined embed text6,000 characters across all embedsLegacy embeds (max 10 per message, 25 fields each)
Components V2 text budget4,000 characters across all text-bearing fieldsEvery Text Display, label and option together
Total components40 (max 10 top-level)Includes every nested component
Buttons per Action Row5A select menu takes the whole row
Select menu options25String select options per menu
Media Gallery items10Images/media per gallery
Button label80 charactersLonger labels are rejected, not truncated
Webhook username override80 charactersPer-message username field

Rate limits and HTTP 429

Discord applies route and global rate limits. Responses can include X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset-After and X-RateLimit-Bucket headers. An HTTP 429 response supplies Retry-After or retry_after in seconds. Read the values returned for your request instead of hardcoding a requests-per-second figure.

A rate limit is a delivery problem, not a reason to shorten valid message text. In DWEEB, stop retrying while the send countdown is active. If another tool uses the same webhook, coordinate its sending too. Use the webhook error guide when the failure has a different HTTP status or a field-specific validation error.

HTTP/1.1 429 Too Many Requests
Retry-After: 1
X-RateLimit-Remaining: 0

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

Staying under the limits

  • Send one rich Components V2 message instead of a burst of small ones — layout blocks replace the multi-message pattern.
  • Queue sends to a single webhook serially and sleep for retry_after (seconds) on any 429 before retrying.
  • Never fan a loop out over one webhook URL in parallel; the bucket is shared and every request after the first few will 429.
  • Schedule non-urgent posts instead of firing them together at the top of the hour.
  • Split genuinely long announcements by design (a follow-up message) rather than letting truncation decide.

How DWEEB enforces this before send

The editor tracks the character budget and component ceilings live, itemizes violations in the issue list, and blocks send on error-severity problems — so a 400 invalid form body for an oversized payload is caught before the request exists. The full nesting rules live in the Components V2 guide.

Put the guide into practice

Open the exact workflow in DWEEB. Nothing posts until you review and confirm it.

Validate a message against the limits →

Primary sources

Keep learning