Skip to main content

Slack Markdown Formatting

Slack uses its own Markdown variant called mrkdwn. Single asterisks for bold, angle-bracket links, and no native lists or headers. Here is every difference, with copy-ready examples.

The Slack composer is forgiving and accepts standard Markdown shortcuts. The API and Block Kit are strict — they only accept mrkdwn.

Read this first

Three things Slack does differently from every other Markdown

1. Bold

*bold* not **bold**

A single asterisk wraps bold text. Double asterisks render as literal text.

2. Strikethrough

~strike~ not ~~strike~~

One tilde on each side. The GitHub-style double tilde does not work.

3. Links

<url|text> not [text](url)

Angle brackets and a pipe. The standard Markdown link works only in the composer.

Text Formatting

Slack's emphasis syntax differs from standard Markdown. Most other tools render the syntax below incorrectly, so the "How it looks in Slack" panel shows the actual Slack rendering.

Bold — single asterisks

Slack uses *one* asterisk for bold. **Two** asterisks render as literal text with asterisks visible.

Slack syntax
*bold text*
How it looks in Slack
bold text
Italic — single underscores

Underscores around the text. Asterisks around text mean bold in Slack, not italic.

Slack syntax
_italic text_
How it looks in Slack
italic text
Strikethrough — single tildes

Slack uses one tilde on each side. Two tildes (~~text~~) is GitHub style and does not work.

Slack syntax
~strikethrough~
How it looks in Slack
strikethrough
Bold + Italic combined

Nest underscores inside asterisks (or vice versa). Slack has no triple-asterisk shortcut.

Slack syntax
*_bold italic_*
How it looks in Slack
bold italic

Mentions

Slack mentions use angle brackets and IDs, not display names. The composer auto-completes @username into the proper ID, but API messages must already contain the ID.

Mention a user

Use the user ID, not the display name. The Slack client renders it as @username.

<@U024BE7LH>
How it looks in Slack
@username
Mention a channel

Channel ID with the channel name after a pipe. Slack renders it as #general.

<#C024BE7LV|general>
How it looks in Slack
#general
Notify the entire channel

Pings everyone in the channel. Use sparingly — many workspaces restrict this.

<!channel>
How it looks in Slack
@channel
Notify active users only

Only pings members currently active in the channel. Less disruptive than @channel.

<!here>
How it looks in Slack
@here
Mention a user group

User-group ID with a fallback display name. Renders as @team-name.

<!subteam^S0NHM1FH4|team-name>
How it looks in Slack
@team-name

Lists

This is where Slack gets weird. Mrkdwn does not support lists. If you type - item in the composer, Slack creates a rich-text list block — but that is a Block Kit feature, not mrkdwn. API messages with mrkdwn cannot produce bulleted or numbered lists.

In the composer

Type - item or 1. item and Slack converts it to a rich-text list block as you type. Press Enter to add another item.

  • First item
  • Second item
  • Third item

In API messages (mrkdwn)

Sending { mrkdwn: true, text: "- one\n- two" } renders the hyphens as literal characters. To get a real list, use a Block Kit rich_text block with rich_text_list elements.

- one
- two

Headers

Mrkdwn has no heading syntax. The composer accepts a # heading shortcut and inserts a Block Kit header block, but this is a UI feature, not part of the mrkdwn format itself.

If you want a heading in an API message

Use a Block Kit header block instead of mrkdwn. Header blocks are a structural element separate from text content:

{
  "blocks": [
    {
      "type": "header",
      "text": { "type": "plain_text", "text": "Section Title" }
    },
    {
      "type": "section",
      "text": { "type": "mrkdwn", "text": "Body copy with *bold* text." }
    }
  ]
}

Blockquotes

Blockquotes work the same as standard Markdown. Start a line with > to indent and quote it. Slack does not support a triple-bracket >>> for multi-line quotes the way Discord does — repeat > on each line.

Standard > prefix — same as CommonMark.
> Single-line blockquote in Slack.
Preview

Single-line blockquote in Slack.

Multi-line quote — start each line with >
> Line one of a multi-line quote.
> Line two continues here.
Preview

Line one of a multi-line quote.
Line two continues here.

Code

Inline code and fenced code blocks work the same as CommonMark. Slack uses a monospace font and preserves whitespace, but does not apply syntax highlighting — a language identifier on the opening fence is silently ignored.

Inline code — single backticks (same as CommonMark)
`inline code`
Preview

inline code

Code block — triple backticks. Slack ignores any language hint after the opening fence.
```
function hello() {
  return "world";
}
```
Preview
function hello() {
  return "world";
}

Composer vs API mrkdwn

The single biggest source of confusion is that Slack's composer (the input box) and the underlying mrkdwn format accept different syntax. The composer is forgiving — it converts standard Markdown shortcuts on send. The API is strict and only accepts mrkdwn.

FeatureComposer acceptsAPI / mrkdwn requires
Bold**text** or Cmd/Ctrl+B*text*
Italic*text* or Cmd/Ctrl+I_text_
Strikethrough~~text~~ or Cmd/Shift+X~text~
Inline code`code``code`
Code block```code``` or Cmd/Shift+C```code```
Link[text](url)<url|text>
Bulleted list- item (creates rich_text_list block)Not supported in mrkdwn
Numbered list1. item (creates rich_text_list block)Not supported in mrkdwn
Heading# heading (creates header block)Not supported in mrkdwn
Quote> quote> quote
Pro tip: To preview what mrkdwn will look like before sending from a bot, use Slack's Block Kit Builder — paste your message JSON and see the rendered output.

Common Mistakes

The most frequent ways people get Slack mrkdwn wrong. Each row shows what does not work and the correct mrkdwn version.

Does not work

**bold**

Use instead

*bold*
Double asterisks render as literal **bold** in mrkdwn. Slack uses a single asterisk on each side.

Does not work

~~strikethrough~~

Use instead

~strikethrough~
Slack only recognizes a single tilde for strikethrough. Double tildes render as literal text.

Does not work

[click here](https://example.com)

Use instead

<https://example.com|click here>
Standard Markdown link syntax only works in the composer. The API and Block Kit expect angle brackets with a pipe.

Does not work

@alice

Use instead

<@U024BE7LH>
Typing @alice in the composer auto-completes to a mention, but API messages must use the user ID inside angle brackets.

Does not work

```python code ```

Use instead

``` code ```
Slack ignores the language identifier — there is no syntax highlighting in mrkdwn code blocks. The lang hint is harmless, just useless.

Quick Reference

Every Slack mrkdwn syntax and feature support at a glance.

Syntax / FeatureWorks in Slack?Notes
*bold* with single asterisksYesNative — but breaks if you paste from CommonMark.
**bold** with double asterisksNoRenders as literal **text** in mrkdwn. Composer converts on send.
_italic_ with underscoresYesNative syntax.
~strikethrough~ (single tilde)YesNative syntax.
~~strikethrough~~ (double tilde)NoNot recognized. Composer accepts the shortcut and converts.
[text](url) link syntaxPartialComposer converts to <url|text> on send. API messages must use angle brackets.
<url|text> link syntaxYesThe canonical mrkdwn form.
# HeadingsPartialComposer creates a separate header block. Raw mrkdwn renders # as literal text.
- and 1. listsPartialComposer creates rich_text_list blocks. Raw mrkdwn does not render bullets.
> BlockquotesYesSame as CommonMark.
``` code blocks ```YesTriple backticks. Language identifier is ignored — no syntax highlighting.
TablesNoNot supported. Paste as a code block to keep alignment.
Images via ![alt](url)NoUse the file upload UI, or use the image block in Block Kit.
@username mentionYesUse <@USER_ID> format in API messages; composer auto-formats.
:smile: emoji shortcodesYesSlack expands shortcodes inline.

Frequently Asked Questions

Why does *text* show as bold in Slack but italic everywhere else?

Slack invented its own markdown variant called mrkdwn before CommonMark stabilized. In CommonMark, single asterisks mean italic and double asterisks mean bold. Slack flipped that: a single asterisk means bold, and underscores mean italic. This is the single biggest source of confusion when copy-pasting between GitHub, Discord, and Slack.

What is the difference between Slack's composer and mrkdwn?

The composer is the input box where you type messages. It is WYSIWYG and accepts standard Markdown shortcuts like **bold** and [text](url) that it converts on send. Mrkdwn is Slack's stored message format — the API and Block Kit text fields expect mrkdwn-native syntax: *bold*, _italic_, <url|text>. If you build a bot or send messages via the API, you must use mrkdwn directly.

Does Slack support markdown headings?

Not in raw mrkdwn. The # character renders as literal text. The composer accepts the # shortcut and creates a separate Block Kit header block, but this is a UI affordance, not a mrkdwn feature. If you are sending messages via the API, use a Block Kit header block instead.

Why don't my bullet lists work in Slack messages from the API?

Lists are not part of mrkdwn. The composer creates rich_text_list blocks when you type - or 1. — these are stored as Block Kit blocks, not mrkdwn. To send a bulleted list via the API, use the rich_text block with rich_text_list elements, not mrkdwn formatting.

How do I link to a URL with custom text in Slack?

Use the format <https://example.com|Click here>. Angle brackets wrap the URL, and a pipe separates the URL from the display text. The standard Markdown [text](url) syntax works in the composer (it converts on send) but not in API messages.

Can I include syntax highlighting in Slack code blocks?

No. Slack code blocks use a monospace font and preserve whitespace, but they do not apply syntax highlighting. You can write ```python at the top of a fence, but Slack ignores the language identifier.

How do I mention a user from a Slack bot or webhook?

Use <@U024BE7LH>, replacing U024BE7LH with the user's Slack ID (not their display name). You can fetch user IDs from the users.list API. The same pattern applies to channels (<#C024BE7LV|channel-name>) and user groups (<!subteam^S0NHM1FH4|team-name>).

Are Slack tables supported?

No. Slack does not support Markdown tables — no |---| header separator syntax. The most common workaround is to format tabular data inside a code block, using spaces to align columns. The fixed-width font preserves alignment.

How do I escape special characters in Slack API messages?

Slack interprets <, >, and & specially when parsing mrkdwn. Replace them with their HTML entities: &lt; for <, &gt; for >, and &amp; for &. This is only required when sending via the API — the composer handles escaping for you.

Learn More Markdown

Slack's mrkdwn is one of several Markdown variants. Compare it to the standards and other platforms: