You need to send a formatted message to a Discord channel using a webhook, and you want the message to include an embed with rich content like a title, description, color, and fields. Discord webhooks allow external applications to post messages without a bot account, but the built-in Discord JSON body does not automatically create embeds. This article explains how to construct and send a webhook message with an embed using the Python requests library. You will learn the exact JSON payload structure and see a complete working code example.
Key Takeaways: Sending a Discord Webhook Embed in Python
- Webhook URL in Server Settings > Integrations > Webhooks: Every webhook has a unique URL that authenticates your request.
- POST request with JSON payload: Use the
requests.post()method with a dictionary containing"embeds"as a list. - Embed object fields:
title,description,color,fields,footer, andtimestampformat the embed appearance.
Understanding Discord Webhook Embed Structure
A Discord webhook accepts a JSON payload via an HTTP POST request. The payload can contain a content string for plain text and an embeds array for rich embed objects. Each embed object supports several sub-objects that control its layout: title, description, url, color (integer decimal), fields (array of inline or non-inline name-value pairs), footer, image, thumbnail, and author. The color field accepts an integer that represents a hexadecimal color code converted to decimal. For example, hex #00ff00 becomes decimal 65280.
Before writing code, you need a webhook URL. Open Discord and go to Server Settings > Integrations > Webhooks. Create a new webhook or copy the URL of an existing one. The URL looks like https://discord.com/api/webhooks/1234567890/abcdef. Keep this URL private — anyone with it can post to your channel.
The Python requests library handles the HTTP POST. Install it with pip install requests if you have not already. The script will define a JSON dictionary with the embed data, convert it to a JSON string, and send it to the webhook URL. Discord returns a 204 No Content status on success.
Python Code to Send a Webhook With an Embed
The following code sends a webhook message with a single embed that includes a title, description, color, fields, footer, and timestamp. Replace YOUR_WEBHOOK_URL with your actual webhook URL.
- Import the requests library
At the top of your Python script, addimport requests. This gives you access to thepost()method. - Store the webhook URL
Assign the URL to a variable:webhook_url = "https://discord.com/api/webhooks/1234567890/abcdef". Use a string literal. - Build the embed dictionary
Create a dictionary with the embed fields. For example:
embed = {
"title": "Server Status Update",
"description": "All systems are operational as of now.",
"color": 65280,
"fields": [
{
"name": "Uptime",
"value": "99.9%",
"inline": True
},
{
"name": "Active Users",
"value": "1,234",
"inline": True
}
],
"footer": {
"text": "Status Bot"
},
"timestamp": "2025-03-15T12:00:00Z"
}
- Wrap the embed in a payload dictionary
Create the main payload:data = {"embeds": }. Theembedskey must contain a list of embed dictionaries. You can include multiple embeds by adding more dictionaries to the list. - Send the POST request
Callresponse = requests.post(webhook_url, json=data). Thejsonparameter automatically converts the dictionary to JSON and sets theContent-Typeheader toapplication/json. - Check the response status
Print the status code:print(response.status_code). A 204 means success. A 400 indicates a malformed payload. A 404 means the webhook URL is invalid or the webhook was deleted.
Here is the complete script in one block:
import requests
webhook_url = "https://discord.com/api/webhooks/1234567890/abcdef"
embed = {
"title": "Server Status Update",
"description": "All systems are operational as of now.",
"color": 65280,
"fields": [
{
"name": "Uptime",
"value": "99.9%",
"inline": True
},
{
"name": "Active Users",
"value": "1,234",
"inline": True
}
],
"footer": {
"text": "Status Bot"
},
"timestamp": "2025-03-15T12:00:00Z"
}
data = {"embeds": }
response = requests.post(webhook_url, json=data)
print(response.status_code)
Common Mistakes and Limitations
Embed Color Must Be Decimal Integer
A common error is passing a hex string like "#00ff00" or an RGB tuple. Discord expects an integer. Convert hex to decimal with Python: int("00ff00", 16) produces 65280. Use an online converter or the Python expression to get the correct value.
Embed Fields Exceed Discord Limits
Each embed can have up to 25 fields. The total embed character limit is 6000 characters across all fields and description. If your payload exceeds these limits, Discord returns a 400 error. Trim the description or remove unnecessary fields.
Webhook URL Contains a Trailing Slash
If you accidentally include a trailing slash at the end of the webhook URL, the request may fail with a 404. Remove any trailing slash before using the URL in your script.
Timestamp Must Be ISO 8601 Format
The timestamp field expects a string in ISO 8601 format, such as "2025-03-15T12:00:00Z" or "2025-03-15T12:00:00+00:00". Use Python’s datetime.now(timezone.utc).isoformat() to generate a valid timestamp dynamically.
No Support for Attachments in Webhook Embeds
Webhook embeds cannot include file attachments. To send an image, use the image or thumbnail embed fields with a URL pointing to an externally hosted image. Discord will display the image inline in the embed.
Webhook Embed Fields: Required vs Optional
| Field | Required | Description |
|---|---|---|
| title | No | Bold text at the top of the embed |
| description | No | Main body text below the title |
| color | No | Left border color as decimal integer |
| fields | No | Array of name-value pairs with optional inline |
| footer | No | Object with text and optional icon_url |
| timestamp | No | ISO 8601 timestamp string |
| image | No | Object with url for a large image |
| thumbnail | No | Object with url for a small image in top-right |
| author | No | Object with name, url, and icon_url |
You can now send a Discord webhook with an embed in Python. Start by copying the script above and replacing the webhook URL and embed content with your own data. For advanced formatting, add an author object with a name and icon URL, or use image and thumbnail to include visuals. Remember to convert hex colors to integers and keep the total payload under Discord’s character limit.