Discord webhooks allow automated messages to be posted into a text channel. GitHub Actions can trigger these webhooks to send notifications about repository events. You might want to alert your team about a successful deployment, a failed build, or a new pull request. This article explains how to configure a Discord webhook and integrate it into a GitHub Actions workflow using curl and GitHub Secrets.
The core problem is that GitHub Actions do not have direct access to Discord. You need a way to pass the webhook URL securely and send a properly formatted JSON payload. This guide covers setting up the webhook in Discord, storing the URL as a GitHub Secret, and writing a workflow step that sends the notification.
By the end, you will have a working workflow that posts a custom message to your Discord channel whenever a specific GitHub event occurs. You will also learn how to handle common errors and customize the message content.
Key Takeaways: Sending Discord Webhooks from GitHub Actions
- Discord Channel > Integrations > Webhooks: Create a webhook and copy its URL from your Discord server settings.
- GitHub Repository > Settings > Secrets and Variables > Actions: Store the webhook URL as a repository secret named
DISCORD_WEBHOOK. curl -H "Content-Type: application/json" -d '{...}' ${{ secrets.DISCORD_WEBHOOK }}: Send the JSON payload from your workflow step.
Understanding Discord Webhooks and GitHub Actions
A Discord webhook is a URL that accepts HTTP POST requests with a JSON body. When you send a request to that URL, Discord posts the message content to the associated text channel. GitHub Actions is a CI/CD platform that runs workflows in response to repository events like pushes, pull requests, or releases.
The combination lets you automate notifications. For example, when a developer pushes code to the main branch, a GitHub Action can build the project and then send a webhook to Discord saying “Build succeeded for commit abc123.” The webhook URL must be kept secret because anyone with that URL can post messages to your channel.
Prerequisites
Before writing the workflow, you need:
- Administrator or Manage Webhooks permission in the Discord server.
- A GitHub repository with at least one workflow file (YAML in
.github/workflows/). - Basic familiarity with YAML syntax and JSON format.
JSON Payload Structure
Discord webhooks accept a JSON object with these common fields:
- content (string): The main message text, up to 2000 characters.
- username (string): Overrides the webhook display name.
- avatar_url (string): Overrides the webhook avatar image.
- embeds (array): Richer messages with title, description, fields, color, etc.
For simple notifications, the content field is enough. You can include Markdown formatting like bold, italic, and `code`.
Steps to Send a Discord Webhook From a GitHub Action
- Create a Discord Webhook
Open Discord and go to your server. Click the server name at the top-left, then select Server Settings > Integrations > Webhooks. Click New Webhook. Give it a name like “GitHub Notifications” and select the target text channel. Click Copy Webhook URL and save it somewhere secure. You will not be able to see the full URL again after closing the page. - Add the Webhook URL as a GitHub Secret
Go to your GitHub repository. Click Settings > Secrets and variables > Actions. Click New repository secret. Set the name toDISCORD_WEBHOOKand paste the URL into the value field. Click Add secret. The secret will be masked in logs and cannot be read by unauthorized users. - Create or Edit a Workflow File
In your repository, navigate to.github/workflows/. Create a new file, for examplediscord-notify.yml. Use the YAML template below. The workflow triggers onpushto themainbranch. You can change the trigger topull_request,release, or any GitHub event. - Write the Workflow Step That Sends the Webhook
Inside the job, add a step that runs acurlcommand. Use thesecrets.DISCORD_WEBHOOKvariable to reference the URL. The JSON payload should include acontentfield with your message. Example:curl -H "Content-Type: application/json" -d '{"content": "Deploy succeeded!"}' ${{ secrets.DISCORD_WEBHOOK }} - Test the Workflow
Commit and push the workflow file to themainbranch. Go to the Actions tab in your repository and watch the workflow run. If the step succeeds, you will see a message in your Discord channel. If it fails, check the workflow logs for error details.
Full Workflow Example
Here is a complete workflow file that sends a notification on every push to the main branch:
name: Discord Notification
on:
push:
branches: [ main ]
jobs:
notify:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Send Discord webhook
run: |
curl -H "Content-Type: application/json" \
-d '{"content": "New push to main branch by ${{ github.actor }}: ${{ github.event.head_commit.message }}"}' \
${{ secrets.DISCORD_WEBHOOK }}
This workflow uses github.actor for the username and github.event.head_commit.message for the commit message. You can customize these variables.
Common Mistakes and Limitations
Webhook URL Is Exposed in Logs
If you accidentally print the webhook URL in a workflow step, GitHub masks it as in the logs. However, the URL is still sent as a header. To be safe, never hardcode the URL in the workflow file. Always use secrets.
Payload Size Exceeds Limit
Discord webhooks have a 2000-character limit for the content field. For longer messages, use embeds which allow up to 6000 characters across multiple fields. If you exceed the limit, the webhook returns a 400 Bad Request error.
Rate Limiting
Discord applies rate limits to webhook endpoints. If you send many requests in a short time, you may receive a 429 Too Many Requests response. Add a delay between requests or batch messages. For most CI/CD use cases, one request per workflow run is safe.
Webhook Deleted or Renamed
If someone deletes or renames the webhook in Discord, the URL becomes invalid. The workflow will fail with a 404 Not Found error. Check the Discord server integrations to confirm the webhook still exists.
Discord Webhook Notification Methods: curl vs Official Action
| Item | curl command | Official GitHub Action (e.g., Ilshidur/action-discord) |
|---|---|---|
| Setup complexity | Minimal: single run step |
Requires adding a third-party action to your workflow |
| Flexibility | Full control over JSON payload, headers, and error handling | Limited to parameters the action exposes |
| Dependencies | None: curl is preinstalled on Ubuntu runners |
Action may have dependencies or require a specific version |
| Security | Secrets are used directly in the command | Action handles secrets through inputs |
| Maintenance | You control the code; no external updates needed | Action may become deprecated or break with GitHub changes |
You can now send Discord webhooks from a GitHub Action using a simple curl command and a secret. Start with a basic notification and then add embeds for richer messages. For advanced use, consider using an official GitHub Action if you prefer a declarative syntax. Always test your workflow on a non-production branch first to avoid spamming your Discord channel.