How to Send a Discord Webhook With an Embed in Python
🔍 WiseChecker

How to Send a Discord Webhook With an Embed in Python

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, and timestamp format 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.

  1. Import the requests library
    At the top of your Python script, add import requests. This gives you access to the post() method.
  2. Store the webhook URL
    Assign the URL to a variable: webhook_url = "https://discord.com/api/webhooks/1234567890/abcdef". Use a string literal.
  3. 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"
}
  1. Wrap the embed in a payload dictionary
    Create the main payload: data = {"embeds": }. The embeds key must contain a list of embed dictionaries. You can include multiple embeds by adding more dictionaries to the list.
  2. Send the POST request
    Call response = requests.post(webhook_url, json=data). The json parameter automatically converts the dictionary to JSON and sets the Content-Type header to application/json.
  3. 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.