Как отправить Discord Webhook с помощью Python
Практическое руководство по отправке сообщений через Discord webhook на Python. Обычный текст, embed-сообщения и файлы с библиотекой requests.
Что такое Discord Webhook?
Discord webhook — это простой способ отправлять сообщения в канал Discord из внешних приложений. В отличие от бота, webhook не требует постоянного соединения или аутентификации с токеном — вы просто отправляете HTTP POST запрос на URL, и сообщение появляется в канале.
Webhook идеально подходит для:
- Уведомлений — CI/CD пайплайны, мониторинг серверов, алерты об ошибках
- Интеграций — подключение сторонних сервисов к Discord
- Автоматизации — запланированные сообщения, обновления статуса, каналы данных
Требования
Вам понадобится Python 3.7+ и библиотека requests:
pip install requests
Шаг 1: Создайте Webhook в Discord
- Откройте ваш Discord сервер и перейдите в Настройки сервера
- Перейдите в Интеграции → Вебхуки
- Нажмите Новый вебхук
- Выберите имя и канал, куда будут отправляться сообщения
- Нажмите Копировать URL вебхука
URL вебхука будет выглядеть примерно так:
https://discord.com/api/webhooks/1234567890/abcdefghijklmnop
Важно: Храните URL вебхука в секрете. Любой, у кого есть URL, может отправлять сообщения в ваш канал.
Шаг 2: Отправьте простое текстовое сообщение
Самый базовый запрос webhook отправляет обычное текстовое сообщение:
import requests
WEBHOOK_URL = "https://discord.com/api/webhooks/YOUR_WEBHOOK_URL"
data = {
"content": "Привет из Python! 🐍"
}
response = requests.post(WEBHOOK_URL, json=data)
if response.status_code == 204:
print("Сообщение отправлено успешно!")
else:
print(f"Ошибка отправки: {response.status_code}")
Успешный запрос webhook возвращает статус код 204 No Content.
Шаг 3: Отправьте Embed-сообщение
Embed позволяют создавать красиво отформатированные сообщения с цветами, полями, изображениями и другим:
import requests
from datetime import datetime
WEBHOOK_URL = "https://discord.com/api/webhooks/YOUR_WEBHOOK_URL"
embed = {
"title": "Отчёт о состоянии сервера",
"description": "Все системы работают нормально.",
"color": 5763719, # Зелёный цвет в десятичном формате
"fields": [
{
"name": "Загрузка CPU",
"value": "23%",
"inline": True
},
{
"name": "Память",
"value": "4.2 ГБ / 16 ГБ",
"inline": True
},
{
"name": "Время работы",
"value": "14 дней, 6 часов",
"inline": False
}
],
"footer": {
"text": "Бот мониторинга"
},
"timestamp": datetime.utcnow().isoformat()
}
data = {
"embeds": [embed]
}
response = requests.post(WEBHOOK_URL, json=data)
print(f"Статус: {response.status_code}")
Справка по цветам Embed
Цвета embed в Discord указываются как десятичные числа. Вот некоторые популярные:
- Красный:
15548997(#ED4245) - Зелёный:
5763719(#57F287) - Синий:
5793266(#5865F2 — Discord blurple) - Жёлтый:
16776960(#FFFF00) - Белый:
16777215(#FFFFFF)
Шаг 4: Отправка с кастомным именем и аватаром
Вы можете переопределить имя и аватар webhook для каждого сообщения:
data = {
"content": "Деплой завершён! ✅",
"username": "Deploy Bot",
"avatar_url": "https://example.com/deploy-avatar.png"
}
response = requests.post(WEBHOOK_URL, json=data)
Шаг 5: Отправка файлов и вложений
Для отправки файлов используйте multipart/form-data вместо JSON:
import requests
import json
WEBHOOK_URL = "https://discord.com/api/webhooks/YOUR_WEBHOOK_URL"
# Данные сообщения
payload = {
"content": "Вот последний лог-файл:"
}
# Файл для загрузки
with open("server.log", "rb") as f:
files = {
"payload_json": (None, json.dumps(payload), "application/json"),
"file": ("server.log", f, "text/plain")
}
response = requests.post(WEBHOOK_URL, files=files)
print(f"Статус: {response.status_code}")
Лимиты запросов
Discord устанавливает лимиты на запросы webhook. Стандартные ограничения:
- 5 запросов за 2 секунды на один webhook
- 30 запросов за 60 секунд на один канал
При превышении лимитов вы получите ответ 429 Too Many Requests с полем retry_after:
import requests
import time
def send_webhook(url, data, max_retries=3):
for attempt in range(max_retries):
response = requests.post(url, json=data)
if response.status_code == 204:
return True
if response.status_code == 429:
retry_after = response.json().get("retry_after", 1)
print(f"Лимит превышен. Повторная попытка через {retry_after}с...")
time.sleep(retry_after)
continue
print(f"Ошибка: {response.status_code}")
return False
return False
Полный пример: Скрипт мониторинга
Вот практический пример — скрипт, который мониторит сайт и отправляет алерты в Discord:
import requests
import time
from datetime import datetime
WEBHOOK_URL = "https://discord.com/api/webhooks/YOUR_WEBHOOK_URL"
TARGET_URL = "https://example.com"
CHECK_INTERVAL = 60 # секунды
def check_website():
try:
response = requests.get(TARGET_URL, timeout=10)
return response.status_code, response.elapsed.total_seconds()
except requests.RequestException as e:
return None, str(e)
def send_alert(status, details):
is_up = status and status == 200
color = 5763719 if is_up else 15548997
embed = {
"title": f"{'✅' if is_up else '🔴'} {TARGET_URL}",
"description": f"Статус: **{status or 'НЕДОСТУПЕН'}**",
"color": color,
"fields": [
{"name": "Детали", "value": str(details), "inline": False}
],
"timestamp": datetime.utcnow().isoformat()
}
requests.post(WEBHOOK_URL, json={"embeds": [embed]})
if __name__ == "__main__":
print(f"Мониторинг {TARGET_URL}...")
last_status = None
while True:
status, details = check_website()
if status != last_status:
send_alert(status, details)
last_status = status
time.sleep(CHECK_INTERVAL)
Что дальше
Теперь, когда вы знаете, как отправлять webhook-сообщения с Python, вы можете:
- Создавать автоматизированные системы уведомлений
- Делать кастомные интеграции для вашего Discord сервера
- Настраивать отложенные сообщения для автоматической отправки по расписанию
- Добавлять опросы для сбора обратной связи от команды
- Использовать наш визуальный конструктор webhook для создания сложных embed-макетов, а затем экспортировать JSON и отправлять из ваших Python-скриптов
Discord Webhook Builder позволяет визуально проектировать сообщения перед кодированием автоматизации.
Обработка ошибок и отказоустойчивость
В продакшн-коде недостаточно просто отправить запрос и проверить статус-код. Сеть ненадежна: соединение может оборваться, сервер Discord может временно не отвечать, а DNS-резолвинг — зависнуть. Грамотная обработка ошибок — обязательная часть любой автоматизации, особенно если вы строите паттерны автоматизации для критически важных систем.
Библиотека requests предоставляет иерархию исключений, которые стоит обрабатывать по отдельности:
import requests
import time
def send_with_retry(url, data, max_retries=5):
"""Отправка webhook с экспоненциальной задержкой при ошибках."""
for attempt in range(max_retries):
try:
response = requests.post(url, json=data, timeout=10)
response.raise_for_status()
if response.status_code == 204:
return True
# Обработка rate limit
if response.status_code == 429:
retry_after = response.json().get("retry_after", 1)
time.sleep(retry_after)
continue
except requests.exceptions.ConnectionError:
print(f"[Попытка {attempt + 1}] Нет соединения с сервером")
except requests.exceptions.Timeout:
print(f"[Попытка {attempt + 1}] Превышено время ожидания")
except requests.exceptions.HTTPError as e:
print(f"[Попытка {attempt + 1}] HTTP ошибка: {e.response.status_code}")
# Не повторяем при клиентских ошибках 4xx (кроме 429)
if 400 <= e.response.status_code < 500:
return False
except requests.exceptions.RequestException as e:
print(f"[Попытка {attempt + 1}] Неизвестная ошибка: {e}")
# Экспоненциальная задержка: 1с, 2с, 4с, 8с, 16с
delay = 2 ** attempt
print(f"Повторная попытка через {delay}с...")
time.sleep(delay)
print("Все попытки исчерпаны")
return False
Ключевые принципы: всегда устанавливайте timeout в requests.post(), чтобы вызов не зависал бесконечно. Используйте экспоненциальную задержку (exponential backoff), чтобы не перегружать сервер повторными запросами. И разделяйте клиентские ошибки (4xx) от серверных (5xx) — повторная попытка при неправильном JSON не имеет смысла, а вот при временной недоступности сервера Discord — вполне оправдана.
Асинхронные вебхуки с aiohttp
Если вам нужно отправлять сообщения в несколько каналов одновременно или ваш скрипт уже использует асинхронный код, синхронная библиотека requests станет узким местом. Каждый вызов requests.post() блокирует выполнение, пока не придет ответ, и при отправке в десять каналов подряд общее время растет линейно.
Библиотека aiohttp решает эту проблему через async/await:
pip install aiohttp
import aiohttp
import asyncio
WEBHOOK_URLS = [
"https://discord.com/api/webhooks/CHANNEL_1_URL",
"https://discord.com/api/webhooks/CHANNEL_2_URL",
"https://discord.com/api/webhooks/CHANNEL_3_URL",
]
async def send_webhook(session, url, data):
"""Отправка одного webhook асинхронно."""
try:
async with session.post(url, json=data, timeout=aiohttp.ClientTimeout(total=10)) as resp:
if resp.status == 204:
print(f"Отправлено в {url[-8:]}...")
return True
else:
print(f"Ошибка {resp.status} для {url[-8:]}...")
return False
except asyncio.TimeoutError:
print(f"Таймаут для {url[-8:]}...")
return False
async def broadcast(message, embeds=None):
"""Отправка сообщения во все каналы одновременно."""
data = {"content": message}
if embeds:
data["embeds"] = embeds
async with aiohttp.ClientSession() as session:
tasks = [send_webhook(session, url, data) for url in WEBHOOK_URLS]
results = await asyncio.gather(*tasks)
success = sum(results)
print(f"Доставлено: {success}/{len(WEBHOOK_URLS)}")
return results
# Запуск
asyncio.run(broadcast("Внимание: плановые работы через 30 минут"))
Функция asyncio.gather() запускает все запросы параллельно. Если синхронная отправка в три канала занимает ~3 секунды (по секунде на каждый), то асинхронная — около 1 секунды. Разница становится особенно заметной при работе с embed-сообщениями: подробнее о форматировании эмбедов и доступных цветовых кодах.
Безопасность
URL вебхука — это, по сути, ключ доступа к вашему каналу. Любой, кто его получит, может отправлять произвольные сообщения. Поэтому хранить URL в коде или коммитить его в git-репозиторий — серьезная ошибка.
Используйте переменные окружения:
import os
import requests
WEBHOOK_URL = os.environ.get("DISCORD_WEBHOOK_URL")
if not WEBHOOK_URL:
raise ValueError("Переменная DISCORD_WEBHOOK_URL не задана")
requests.post(WEBHOOK_URL, json={"content": "Безопасная отправка"})
Для локальной разработки удобно использовать файл .env с библиотекой python-dotenv:
pip install python-dotenv
from dotenv import load_dotenv
import os
load_dotenv() # Загружает переменные из .env файла
WEBHOOK_URL = os.getenv("DISCORD_WEBHOOK_URL")
Файл .env:
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/1234567890/abcdefg
Обязательно добавьте .env в .gitignore, чтобы случайно не опубликовать URL в открытый репозиторий. Если URL все-таки утек, немедленно удалите вебхук в настройках Discord и создайте новый.
Тестирование и отладка
Во время разработки не стоит спамить в рабочий канал Discord при каждом запуске скрипта. Для тестирования структуры запроса можно использовать сервис httpbin.org, который просто возвращает то, что вы ему отправили:
import requests
import json
TEST_URL = "https://httpbin.org/post"
data = {
"content": "Тестовое сообщение",
"embeds": [{"title": "Тест", "color": 5793266}]
}
response = requests.post(TEST_URL, json=data)
print(json.dumps(response.json(), indent=2, ensure_ascii=False))
Это позволяет проверить корректность JSON-структуры перед отправкой в Discord. Для валидации embed-сообщений убедитесь, что все обязательные поля заполнены: Discord молча отбросит embed без title или description. Также создайте отдельный тестовый канал на вашем сервере — это лучший способ тестировать интеграцию без риска засорить рабочие каналы.
Помимо кода, discord-webhook.com предлагает визуальный конструктор с такими функциями как отложенные сообщения, поддержка тредов и форумов, опросы и интерактивные кнопки с действиями — всё без написания кода.
Похожие статьи
- Отправка Discord Webhook из JavaScript и Node.js — Туториал по отправке webhook на JavaScript с fetch API и Node.js
- Полное руководство по Discord Embed: поля, цвета, изображения, лимиты — Всё о создании красиво оформленных embed-сообщений
- Автоматические уведомления через Discord Webhook — Полное руководство — Автоматизация уведомлений для мониторинга, CI/CD и бизнес-процессов
- Конструктор опросов Discord Webhook — Создание опросов через webhook на Python и визуально
- Отложенные сообщения Discord Webhook — Планирование отправки сообщений по расписанию
- Треды и форумы Discord Webhook — Отправка сообщений в треды и форумы Discord
Попробуйте в нашем инструменте
Открыть конструктор Discord Webhook