You have a Slack workspace where your team posts important messages, but you want those messages to appear in a Discord channel with proper formatting. Discord webhooks can receive data from Slack, but the message format differs between the two platforms. Slack uses its own message formatting with features like user mentions, channel links, and rich attachments, while Discord expects a different JSON structure. This article explains how to set up a Discord webhook, configure Slack to send messages to it, and convert Slack message formatting to Discord-compatible formatting using a simple script or middleware.
Key Takeaways: Discord Webhook for Slack Messages With Format Conversion
- Discord Webhook URL in Server Settings > Integrations > Webhooks: Create a webhook that provides a unique URL for receiving messages.
- Slack Outgoing Webhook or Slack Workflow with Webhook Request: Send Slack messages to the Discord webhook URL with a JSON payload.
- Format Conversion via Cloud Function or Script: Transform Slack message fields like text, user_id, and channel into Discord embed or content fields.
How Discord Webhooks Work With Slack Messages
A Discord webhook is a simple HTTP endpoint that accepts JSON payloads and posts them to a specified Discord channel. Slack can send messages to any HTTP endpoint using its Outgoing Webhooks feature or Slack Workflows. However, the JSON structure Slack sends differs from what Discord expects. Discord webhooks expect a payload with fields like content, embeds, username, and avatar_url. Slack sends fields like text, user_name, channel_name, and attachments. Without conversion, Slack messages appear as plain text or fail to post entirely.
Prerequisites
Before starting, you need a Discord server where you have the Manage Webhooks permission, a Slack workspace where you can create Outgoing Webhooks or Workflows, and a way to run a serverless function or a small script. This article uses a free Google Cloud Function as the middleware, but you can use any HTTP endpoint you control, such as an AWS Lambda, Azure Function, or a Node.js server on a Raspberry Pi.
Understanding the Format Differences
Slack sends messages in a JSON object that includes the message text, the user who sent it, the channel, and optional attachments. Discord webhooks accept a JSON object with content for plain text, embeds for rich cards, and allowed_mentions for controlling mentions. Key differences include:
- Slack uses
textfor the message body; Discord usescontent. - Slack uses
user_namefor the sender name; Discord usesusernamein the webhook payload. - Slack supports
@userand#channelmentions; Discord uses<@user_id>and<#channel_id>. - Slack attachments contain
title,text,color, andfields; Discord embeds containtitle,description,color, andfields.
Steps to Set Up Discord Webhook and Forward Slack Messages
- Create a Discord Webhook
Open Discord and go to your server. Click Server Settings > Integrations > Webhooks. Click New Webhook. Give it a name, select the target channel, and click Copy Webhook URL. Save this URL for later. - Set Up Slack Outgoing Webhook
In Slack, go to Slack API dashboard at api.slack.com/apps. Create a new app or use an existing one. Under Features, click Incoming Webhooks and activate them. Or use Outgoing Webhooks under the same app. For Outgoing Webhooks, set the URL to the middleware endpoint you will create in the next step. If you use Slack Workflows, create a new workflow with a Webhook Request trigger and set the URL to your middleware endpoint. - Create the Format Conversion Middleware
Write a simple HTTP endpoint that receives Slack payloads, converts them to Discord format, and forwards them. Example using Node.js and Google Cloud Functions:exports.slackToDiscord = (req, res) => { const slackPayload = req.body; const discordPayload = { content: slackPayload.text || '', username: slackPayload.user_name || 'Slack User', avatar_url: slackPayload.user_icon || 'https://example.com/default-icon.png', embeds: [] }; if (slackPayload.attachments) { slackPayload.attachments.forEach(att => { discordPayload.embeds.push({ title: att.title || '', description: att.text || att.fallback || '', color: att.color ? parseInt(att.color, 16) : 0, fields: att.fields ? att.fields.map(f => ({name: f.title, value: f.value, inline: f.short})) : [] }); }); } fetch(DISCORD_WEBHOOK_URL, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(discordPayload) }); res.status(200).send('OK'); };Deploy this function to Google Cloud Functions, AWS Lambda, or any HTTP endpoint. Set the environment variable
DISCORD_WEBHOOK_URLto the URL you copied in step 1. - Test the Integration
In Slack, send a message that includes text, an attachment, or a link. The message should appear in your Discord channel within seconds. Check the Discord channel for the formatted message. If it does not appear, check the logs of your middleware function for errors. - Handle Slack Mentions and Channel References
Slack uses<@U12345>for user mentions and<#C12345>for channel references. Discord uses<@123456789>and<#123456789>with numeric IDs. Write a conversion function that maps Slack user IDs to Discord user IDs if you need mentions to work. For simple forwarding, you can strip the mention syntax or replace it with the user display name from a lookup table.
Common Issues and How to Fix Them
Slack Message Does Not Appear in Discord
Check the middleware function logs. Common causes include incorrect Discord webhook URL, missing environment variable, or the middleware returning an error. Ensure your middleware function returns a 200 status to Slack; otherwise Slack may retry and cause duplicates.
Formatting Looks Wrong in Discord
Slack attachments and Discord embeds have slightly different field names. Map Slack text to Discord description, Slack color (hex string) to Discord color (integer), and Slack fields[].title to Discord fields[].name. Also, Discord embeds have a limit of 6000 characters total; truncate long Slack messages.
User Names Not Showing Correctly
Slack sends user_name as the display name. Discord webhooks accept a username field in the root payload. If you want the Slack user icon, include the avatar_url field. Note that Discord webhooks ignore the username field if you set it to a bot name that violates Discord’s terms.
Discord Webhook vs Slack Webhook: Key Differences
| Item | Discord Webhook | Slack Webhook |
|---|---|---|
| Payload format | JSON with content, embeds, username, avatar_url | JSON with text, attachments, channel, username, icon_url |
| Mention syntax | <@user_id> or <@&role_id> | <@user_id> or <!subteam^group_id> |
| Attachment support | Embeds with title, description, fields, color, image, footer | Attachments with title, text, fields, color, image_url, thumb_url |
| Rate limits | 30 requests per second per webhook | 1 message per second per webhook |
| Custom username | Yes, set in payload | Yes, set in payload |
After setting up the middleware, you can forward Slack messages to Discord with proper formatting. The conversion script handles text, attachments, and user names. For advanced use, extend the script to map Slack user mentions to Discord user IDs using a lookup table. This integration keeps your team in sync across both platforms without manual reposting.