Send Discord Webhooks Using curl (Command Line Guide)
Complete guide to sending Discord webhook messages with curl. Includes examples for text, embeds, files, and advanced formatting from the command line.
Why Use curl for Discord Webhooks?
curl is a command-line tool available on virtually every platform (Linux, macOS, Windows). It’s perfect for:
- Quick testing: Send test messages without writing code
- Shell scripts: Integrate Discord notifications into bash/zsh scripts
- CI/CD pipelines: Send build notifications from Jenkins, GitLab CI, or custom automation
- Debugging: Test webhook payloads before implementing them in applications
- Cron jobs: Schedule automated status updates or reports
This guide covers practical curl examples for Discord webhooks, from simple text messages to complex embeds.
Prerequisites
Check if curl is installed:
curl --version
If not installed:
- Linux:
sudo apt install curlorsudo yum install curl - macOS: Included by default
- Windows: Included in Windows 10+ or download from curl.se
You’ll also need a Discord webhook URL from Server Settings → Integrations → Webhooks.
Basic Text Message
Send a simple text message:
curl -H "Content-Type: application/json" \
-d '{"content": "Hello from curl!"}' \
https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN
Breakdown:
-H "Content-Type: application/json": Sets the content type header-d '{"content": "..."}': Sends JSON data in the request body- The webhook URL is the final argument
A successful request returns HTTP 204 with no response body.
Send with Custom Username and Avatar
Override the webhook’s default name and avatar:
curl -H "Content-Type: application/json" \
-d '{
"content": "Deployment complete!",
"username": "Deploy Bot",
"avatar_url": "https://example.com/bot-avatar.png"
}' \
https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN
The username and avatar_url fields are optional and apply only to this message.
Send a Rich Embed
Embeds provide formatted messages with colors, fields, and structure:
curl -H "Content-Type: application/json" \
-d '{
"embeds": [{
"title": "Server Status",
"description": "All systems operational",
"color": 5763719,
"fields": [
{
"name": "CPU Usage",
"value": "23%",
"inline": true
},
{
"name": "Memory",
"value": "4.2 GB / 16 GB",
"inline": true
}
],
"footer": {
"text": "Monitoring System"
},
"timestamp": "2025-04-05T14:30:00.000Z"
}]
}' \
https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN
Color values are decimal integers:
- Green:
5763719 - Red:
15548997 - Blue:
3447003 - Discord Blurple:
5793266
Convert hex to decimal: echo $((16#5865F2)) outputs 5793266.
Using Variables in Shell Scripts
Store the webhook URL and create reusable functions:
#!/bin/bash
WEBHOOK_URL="https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN"
send_message() {
local message="$1"
curl -H "Content-Type: application/json" \
-d "{\"content\": \"$message\"}" \
"$WEBHOOK_URL"
}
send_embed() {
local title="$1"
local description="$2"
local color="$3"
curl -H "Content-Type: application/json" \
-d "{
\"embeds\": [{
\"title\": \"$title\",
\"description\": \"$description\",
\"color\": $color
}]
}" \
"$WEBHOOK_URL"
}
# Usage
send_message "Backup started at $(date)"
send_embed "Backup Complete" "All files backed up successfully" 5763719
Important: Escape double quotes inside JSON strings when using variables.
Send Files and Attachments
To send files, use multipart/form-data:
curl -F "payload_json={\"content\": \"Here's the log file:\"}" \
-F "file=@/path/to/server.log" \
https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN
Breakdown:
-F: Sends form data (multipart/form-data)payload_json: The message payload as JSONfile=@/path/to/file: Uploads the file (@ prefix reads from file path)
Send multiple files:
curl -F "payload_json={\"content\": \"Multiple files:\"}" \
-F "file1=@/path/to/file1.txt" \
-F "file2=@/path/to/file2.log" \
https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN
Embed with Image and Thumbnail
Add images to embeds:
curl -H "Content-Type: application/json" \
-d '{
"embeds": [{
"title": "Server Screenshot",
"description": "Current dashboard view",
"color": 5793266,
"image": {
"url": "https://example.com/screenshot.png"
},
"thumbnail": {
"url": "https://example.com/icon.png"
}
}]
}' \
https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN
Image URLs must be publicly accessible (HTTPS recommended).
Error Handling in Scripts
Check the HTTP response code and handle errors:
#!/bin/bash
WEBHOOK_URL="https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN"
send_with_retry() {
local message="$1"
local max_retries=3
local retry_count=0
while [ $retry_count -lt $max_retries ]; do
response=$(curl -s -w "%{http_code}" -o /dev/null \
-H "Content-Type: application/json" \
-d "{\"content\": \"$message\"}" \
"$WEBHOOK_URL")
if [ "$response" -eq 204 ]; then
echo "Message sent successfully"
return 0
elif [ "$response" -eq 429 ]; then
echo "Rate limited. Retrying in 2 seconds..."
sleep 2
retry_count=$((retry_count + 1))
else
echo "Error: HTTP $response"
return 1
fi
done
echo "Failed after $max_retries retries"
return 1
}
send_with_retry "Test message with retry logic"
Common HTTP codes:
204: Success400: Bad request (invalid JSON)401: Unauthorized (invalid webhook URL)429: Rate limited (too many requests)
Real-World Example: Backup Script Notifications
Send Discord notifications from a backup script:
#!/bin/bash
WEBHOOK_URL="https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN"
BACKUP_DIR="/var/backups"
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
# Start notification
curl -H "Content-Type: application/json" \
-d "{\"content\": \"🔄 Backup started at $TIMESTAMP\"}" \
"$WEBHOOK_URL"
# Perform backup
tar -czf "$BACKUP_DIR/backup-$(date +%Y%m%d).tar.gz" /home/user/data
if [ $? -eq 0 ]; then
# Success
BACKUP_SIZE=$(du -h "$BACKUP_DIR/backup-$(date +%Y%m%d).tar.gz" | cut -f1)
curl -H "Content-Type: application/json" \
-d "{
\"embeds\": [{
\"title\": \"✅ Backup Complete\",
\"description\": \"Backup finished successfully\",
\"color\": 5763719,
\"fields\": [
{\"name\": \"Size\", \"value\": \"$BACKUP_SIZE\", \"inline\": true},
{\"name\": \"Time\", \"value\": \"$TIMESTAMP\", \"inline\": true}
]
}]
}" \
"$WEBHOOK_URL"
else
# Failure
curl -H "Content-Type: application/json" \
-d "{
\"embeds\": [{
\"title\": \"❌ Backup Failed\",
\"description\": \"Backup process encountered an error\",
\"color\": 15548997,
\"fields\": [
{\"name\": \"Time\", \"value\": \"$TIMESTAMP\", \"inline\": false}
]
}]
}" \
"$WEBHOOK_URL"
fi
Real-World Example: Server Monitoring
Monitor server resources and send alerts:
#!/bin/bash
WEBHOOK_URL="https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN"
# Get system stats
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
MEMORY_USAGE=$(free | grep Mem | awk '{printf "%.1f", $3/$2 * 100}')
DISK_USAGE=$(df -h / | awk 'NR==2 {print $5}' | cut -d'%' -f1)
# Determine alert level
if [ $(echo "$CPU_USAGE > 80" | bc) -eq 1 ] || \
[ $(echo "$MEMORY_USAGE > 80" | bc) -eq 1 ] || \
[ $DISK_USAGE -gt 80 ]; then
COLOR=15548997 # Red
TITLE="⚠️ High Resource Usage Alert"
else
COLOR=5763719 # Green
TITLE="✅ System Status Normal"
fi
curl -H "Content-Type: application/json" \
-d "{
\"embeds\": [{
\"title\": \"$TITLE\",
\"color\": $COLOR,
\"fields\": [
{\"name\": \"CPU Usage\", \"value\": \"${CPU_USAGE}%\", \"inline\": true},
{\"name\": \"Memory Usage\", \"value\": \"${MEMORY_USAGE}%\", \"inline\": true},
{\"name\": \"Disk Usage\", \"value\": \"${DISK_USAGE}%\", \"inline\": true}
],
\"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%S.000Z)\"
}]
}" \
"$WEBHOOK_URL"
Run this script via cron for periodic monitoring:
# Check every 5 minutes
*/5 * * * * /path/to/monitor.sh
Using jq for Complex JSON
For complex JSON payloads, use jq to build JSON programmatically:
# Install jq: sudo apt install jq
WEBHOOK_URL="https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN"
# Build JSON with jq
PAYLOAD=$(jq -n \
--arg title "Deployment Report" \
--arg desc "Version 2.1.0 deployed" \
--argjson color 5763719 \
'{
embeds: [{
title: $title,
description: $desc,
color: $color,
timestamp: (now | strftime("%Y-%m-%dT%H:%M:%S.000Z"))
}]
}')
curl -H "Content-Type: application/json" \
-d "$PAYLOAD" \
"$WEBHOOK_URL"
jq handles escaping and formatting automatically, reducing errors.
Rate Limits
Discord enforces rate limits:
- 5 requests per 2 seconds per webhook
- 30 requests per 60 seconds per channel
If you exceed limits, you’ll receive HTTP 429. Add delays between requests:
for i in {1..10}; do
curl -H "Content-Type: application/json" \
-d "{\"content\": \"Message $i\"}" \
"$WEBHOOK_URL"
sleep 0.5 # 500ms delay
done
Debugging curl Requests
Use verbose mode to see full request/response details:
curl -v -H "Content-Type: application/json" \
-d '{"content": "Debug test"}' \
https://discord.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN
The -v flag shows:
- Request headers
- Response headers
- HTTP status code
- SSL/TLS handshake details
Best Practices
Store webhook URLs securely: Use environment variables or config files with restricted permissions. Never commit webhook URLs to version control.
# .env file (add to .gitignore)
DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/..."
# Load in script
source .env
Validate JSON: Use jq to validate JSON before sending:
echo '{"content": "test"}' | jq .
Handle special characters: Escape quotes and newlines in shell variables:
MESSAGE="Line 1\nLine 2"
curl -d "{\"content\": \"$MESSAGE\"}" "$WEBHOOK_URL"
Test payloads visually: Use the Discord Webhook Builder to design embeds, then copy the JSON for use in curl commands.
Troubleshooting
400 Bad Request: Invalid JSON syntax. Validate with jq or an online JSON validator.
401 Unauthorized: Webhook URL is incorrect or the webhook was deleted.
curl: command not found: Install curl using your package manager.
SSL certificate errors: Update curl or use -k to skip verification (not recommended for production).
Next Steps
You now know how to send Discord webhooks using curl from the command line. For complex embed designs, try our free Discord Webhook Builder to visually create messages, then export the JSON for use in your shell scripts and automation workflows.
discord-webhook.com also offers scheduled messages, thread and forum support, polls, and interactive buttons with actions — all configurable through the visual builder without writing code.
Related Articles
- How to Send Discord Webhook Messages with Python — A practical guide to sending Discord webhook messages using Python and the requests library
- Send Discord Webhooks from JavaScript (Node.js & Browser) — Learn how to send webhook messages using JavaScript with Node.js and browser fetch API
- Send Discord Notifications from GitHub Actions CI/CD — Learn how to send Discord webhook notifications from GitHub Actions workflows
- Discord Webhook Polls Guide — Create interactive polls in Discord channels using webhooks
- Discord Webhook Scheduled Messages — Automate recurring messages and timed notifications with scheduled webhooks
Try it in our tool
Open Discord Webhook Builder