Discord webhooks let you send automated messages to a text channel without using a full bot. By default, a webhook uses a fixed name and avatar set when it is created. But you may want each message to show a different username and profile picture, such as for a multi-brand announcement bot or a roleplay system. This article explains how to build a Discord webhook that sends each message with a custom avatar and username using the webhook API. You will learn the payload structure, the required permissions, and how to test the webhook with curl or a simple script.
Key Takeaways: How to Use the Discord Webhook API for Per-Message Avatars
- Webhook URL from Server Settings > Integrations > Webhooks: Create a webhook and copy its URL to send messages via POST requests.
- JSON payload fields “username” and “avatar_url”: Set these in each request to override the default name and profile picture for that message only.
- Content-Type header application/json: Required in all POST requests to the webhook URL for the custom avatar feature to work.
How Discord Webhooks Handle Avatars
A Discord webhook is a simple HTTP endpoint that accepts JSON payloads. When you create a webhook in a channel, Discord assigns it a default name and avatar. You can change these defaults in the webhook settings, but that changes the identity for every message sent through that webhook.
The webhook API, however, supports two optional fields in the JSON body: username and avatar_url. When you include these fields in a single POST request, Discord displays that message with the specified username and avatar image. The webhook itself retains its original defaults for the next message. This per-message override is the core feature you need to build a webhook that sends each message with a custom avatar.
The avatar_url must point to a publicly accessible image file. Discord accepts JPEG, PNG, GIF, and WebP formats. The image does not need to be hosted on a specific service, but it must be reachable by Discord servers. The username field accepts a string of up to 32 characters. If you omit either field, Discord uses the webhook default.
Prerequisites
Before you start, you need a Discord server where you have the Manage Webhooks permission. This permission is granted by default to server administrators and to roles with the Manage Server permission. You also need a tool to send HTTP POST requests. You can use curl, Postman, or a programming language like Python or JavaScript.
Steps to Create a Discord Webhook With Per-Message Custom Avatars
- Open Server Settings and Create a Webhook
Open Discord and navigate to your server. Click the server name at the top left, then select Server Settings from the dropdown. In the left sidebar, click Integrations. Under Webhooks, click Create Webhook. Give it a name and choose the target channel. Click Copy Webhook URL and save it securely. You do not need to set a custom avatar here unless you want a fallback. - Prepare Your Custom Avatar Images
Upload each avatar image to a public hosting service. Discord does not host images for you, so you need a URL that ends with an image extension. Services like Imgur, Cloudinary, or your own web server work. Copy the direct image URL for each avatar you plan to use. Make sure the URL does not require authentication. - Build the JSON Payload
Create a JSON object with at least thecontentfield for the message text. Add theusernamefield with the display name you want for this message. Add theavatar_urlfield with the direct image URL. A complete payload looks like this:{
"content": "Hello from a custom avatar!",
"username": "Assistant Bot",
"avatar_url": "https://example.com/avatar.png"
} - Send the POST Request Using curl
Open a terminal and run the following command, replacingWEBHOOK_URLwith your copied URL and the JSON with your payload:curl -X POST -H "Content-Type: application/json" -d '{"content":"Hello from a custom avatar!","username":"Assistant Bot","avatar_url":"https://example.com/avatar.png"}' WEBHOOK_URL
Press Enter. If successful, Discord returns a 204 No Content status and the message appears in the channel with your custom avatar and username. - Send Multiple Messages With Different Avatars
Repeat step 4 with a differentusernameandavatar_urlfor each message. Each request is independent. You can automate this with a script that loops through a list of users and avatars.
Automate With a Python Script
For repeated use, write a short Python script. Install the requests library with pip install requests. Then use the following code:
import requests
webhook_url = "YOUR_WEBHOOK_URL"
payload = {
"content": "This message has a custom avatar!",
"username": "Custom User",
"avatar_url": "https://example.com/avatar.png"
}
response = requests.post(webhook_url, json=payload)
print(response.status_code)
Run the script. The message appears in the channel. Change the username and avatar_url values in the dictionary to send different avatars.
If the Custom Avatar Does Not Appear
Avatar URL Returns a 404 or Redirect
Discord requires a direct image URL that returns a 200 status and an image MIME type. If the URL redirects or requires a login, Discord ignores the avatar_url field and uses the webhook default. Test the URL in a browser. If it redirects, use the final destination URL. If the image is on Imgur, use the direct link ending in .png or .jpg.
Content-Type Header Missing or Wrong
The Content-Type header must be application/json. If you send the payload as form data or omit the header, Discord ignores the username and avatar_url fields. Always set the header explicitly in your request.
Webhook URL Is Invalid or Expired
Webhook URLs do not expire, but they can be deleted or regenerated. If you get a 404 response, the webhook may have been deleted. Go back to Server Settings > Integrations and confirm the webhook still exists. If not, create a new one.
Discord Webhook Payload Fields: Fixed vs Per-Message
| Field | Webhook Default (Fixed) | Per-Message Override |
|---|---|---|
| Username | Set when webhook is created or edited | Set in JSON payload with username field |
| Avatar | Set when webhook is created or edited | Set in JSON payload with avatar_url field |
| Content | Not applicable | Set in JSON payload with content field |
| Embeds | Not applicable | Set in JSON payload with embeds array |
This table shows which fields are controlled by the webhook configuration and which can be overridden per message. Only username and avatar_url support per-message overrides. All other fields, such as the channel destination, are fixed.
You can now build a Discord webhook that sends each message with a custom avatar and username. Use the JSON payload fields username and avatar_url in every POST request. For automation, write a script that cycles through a list of avatars and names. Remember that the avatar URL must be a direct, public image link. Test your payload with curl before integrating it into a larger system. For advanced use, add embeds to your payload to include rich content alongside the custom avatar.