Discord Text Formatting & Markdown Guide
Discord's markdown looks familiar but behaves like no other dialect: italics care about spaces, ordered lists silently merge into bullet lists, and links trim their own punctuation. This reference covers the full syntax plus the edge cases DWEEB's preview parser is tested against real Discord clients for.
The complete formatting cheat sheet
| Syntax | Result | Notes |
|---|---|---|
| **text** | Bold | Also combines: ***bold italic*** |
| *text* or _text_ | Italic | See the quirks below — they are not interchangeable |
| __text__ | Underline | Nest with italics: __*text*__ |
| ~~text~~ | Strikethrough | Works inline anywhere |
| ||text|| | Spoiler | Hidden until the reader clicks it |
| `code` | Inline code | Use ``double backticks`` to contain a backtick |
| ```lang``` | Code block | Multi-line; the language tag is kept but webhook messages get no highlighting |
| > text | Quote | >>> quotes every following line |
| # / ## / ### text | Heading 1–3 | Must start the line |
| -# text | Subtext | Small, muted line — good for captions and footnotes |
| - text or 1. text | Bullet / numbered list | Indent two spaces for a nested level |
| [label](https://…) | Masked link | Bot, webhook and embed text only — regular user chat posts it literally |
Quirks Discord actually enforces
These are the rules that make a message render differently in Discord than in a generic markdown previewer. DWEEB's preview parser is verified against the live Discord client for each of them, so what you see in the editor is what the channel gets.
- *italics* needs a non-space character right after the opening asterisk: `* text*` stays literal, which keeps math like 3 * 4 * 5 intact.
- _underscore italics_ needs word boundaries — snake_case_names stay literal, while a space-padded _phrase_ formats.
- Inline styles keep going across a line break: an unclosed **bold can format the next line.
- Numbered items directly after a bullet list merge into that bullet list; separate them with a blank line to keep the numbers.
- Bare URLs auto-link, but Discord drops trailing punctuation like .,:;"')] from the link.
- In Components V2 text, unicode emoji render slightly enlarged but never as jumbo emoji — an emoji-only message does not blow up the way it does in normal chat.
Mentions, emoji and other tokens
A custom emoji whose ID does not resolve renders as plain :name: text, so test custom emoji in the destination server before a big announcement.
| Token | Renders as | Where the ID comes from |
|---|---|---|
| <@user_id> | @user mention | Copy ID with Developer Mode enabled |
| <@&role_id> | @role mention | Server settings → Roles → Copy ID |
| <#channel_id> | #channel link | Right-click the channel → Copy ID |
| <:name:emoji_id> | Custom emoji | The bot/webhook needs no membership for unicode; custom emoji must resolve |
| <a:name:emoji_id> | Animated custom emoji | Same as custom emoji, with the a: prefix |
| <t:unix:style> | Dynamic timestamp | Shown in each reader's own timezone — see the timestamp guide |
Where each rule works
Regular user chat supports the core styles but not masked links. Webhook and bot messages support everything above, including masked links, in plain content and in Components V2 Text Displays. Legacy embed descriptions and fields support most inline styles and masked links, but headings and subtext belong to the modern surfaces.
Components V2 Text Displays are the most capable text surface: headings, subtext, lists, quotes, code, mentions and timestamps all render, and DWEEB counts every character against the message-wide budget as you type.
Escaping and plain text
Prefix a formatting character with a backslash to show it literally: \*not italic\*. For a block that must never format — a config sample, a token pattern, ASCII art — use a code block, which suppresses all markdown inside it.
Put the guide into practice
Open the exact workflow in DWEEB. Nothing posts until you review and confirm it.
Try the formatting live →