You must enable javascript in order to use Slack. You can do this in your browser settings.

Formatting messages

These docs describe an outmoded approach to composing messages and interactive experiences. Learn how to more effectively communicate and help folks get work done by our new documentation and transitioning to "blocks".
The rundown
Read this if:You're still experimenting, prototyping, and exploring.
Read first:Block Kit
Read next:Making messages interactive

Basic message formatting is easy, but there are a few quirks you'll want to understand before making your messages more complex. Learn how to mark your messages up so they're easy to read and go with the flow of conversation.

A gorgeous message

Messages can contain any displayable Unicode sequence of characters (all messages must use UTF-8 encoding), but need to be slightly escaped by clients.

All text in Slack uses the same system of escaping: chat messages, direct messages, file comments, etc.

These formatting instructions pertain to content posted programmatically to Slack. For instructions on formatting messages within Slack itself, consult this help center article.

How to escape characters

3 Characters you must encode as HTML entities

There are three characters you must convert to HTML entities and only three: &, <, and >.

Slack will take care of the rest.

  • Replace the ampersand, &, with &amp;
  • Replace the less-than sign, < with &lt;
  • Replace the greater-than sign, > with &gt;

That's it. Don't HTML entity-encode the entire message. Of course, when you send your message using URL-encoding, you'll still need to URL encode the ampersand.

Try it!

URL encoding and Unicode

When sending messages using URL or POST-based parameters, as you may with chat.postMessage and similar approaches, you'll need to "URL encode" the parameter value containing your message.

Unicode characters, like many emojis and accent characters, should be presented in URL-encoded hex. For example, 🌊 is F0 9F 8C 8A in hex and further URL-encoded as %F0%9F%8C%8A.

A user types    : Hello & <world> 🌊
Encoded message : Hello &amp; &lt;world&gt; 🌊

And would be sent URL-encoded as:


Control sequences

Slack uses &, <, and > as control characters so that messages may contain special escaped sequences.

Linking to channels and users

For example, to refer to a channel or user within a message, a client should send the following messages:

Why not join <#C024BE7LR|general>?
Hey <@U024BE7LH>, did you see my file?

These escape sequences are then forwarded to all members of the channel as usual, and clients can format these links specially.


Remember you can only link to public channels. If you try to include a link to a private channel in a message, it will display as plain text.

The function of username and username mentions is drastically changing throughout the Slack product and platform. See this changelog for further detail.

Linking to URLs

To link to URLs casually in conversation, include the URL directly in the message.

To link more traditionally, send messages like this:

This message contains a URL
So does this one:

URL detection is performed by the server. We do this so that URL detection (a non-trivial operation) is performed consistently across multiple clients. The example messages will be broadcast to other clients as follows:

This message contains a URL <>
So does this one: <|>

In the first case, the URL is detected as-is. In the second, the full URL is included first, then a pipe character (|), then finally the originally typed version of the URL.

The server will also detect mailto links in the format <email|user>. For example:


Turn your simple links into buttons by attaching link buttons to messages instead.

Formatting dates

Messages containing a date or time should be displayed in the local timezone of the person seeing the message. The <!date> command will format a Unix timestamp using tokens within a string that you set. You may also optionally link a date using a standard URL. A <!date> must include some fallback text for older Slack clients (in case the conversion fails).


The unix_epoch_timestamp is required and should be a number in standard Unix time format.

Describe your date and time as a string, using any of the following tokens:

  • {date_num} is displayed as 2014-02-18. It will include leading zeros before the month and date and is probably best for more technical integrations that require a developer-friendly date format.
  • {date} is displayed as February 18th, 2014.
  • {date_short} is displayed as Feb 18, 2014.
  • {date_long} is displayed as Tuesday, February 18th, 2014.
  • {date_pretty} displays the same as {date} but uses "yesterday", "today", or "tomorrow" where appropriate.
  • {date_short_pretty} displays the same as {date_short} but uses "yesterday", "today", or "tomorrow" where appropriate.
  • {date_long_pretty} displays the same as {date_long} but uses "yesterday", "today", or "tomorrow" where appropriate.
  • {time} is displayed as 6:39 AM or 6:39 PM in 12-hour format. If the client is set to show 24-hour format, it is displayed as 06:39 or 18:39.
  • {time_secs} is displayed as 6:39:45 AM 6:39:42 PM in 12-hour format. In 24-hour format it is displayed as 06:39:45 or 18:39:42.

Note: if the date you wish to display is within six months of the present, the year will be omitted.

If your timestamp needs to be linked, specify an optional link parameter using a standard, fully qualified URL.

Finally, include a string of fallback text just in case the client is unable to process the date. Consider adding timezone information to your fallback text since it will potentially be different from the timezone of the person reading it.


  • <!date^1392734382^Posted {date_num} {time_secs}|Posted 2014-02-18 6:39:42 AM> will display as: Posted 2014-02-18 6:39:42 AM
  • <!date^1392734382^{date} at {time}|February 18th, 2014 at 6:39 AM PST> will display as: February 18th, 2014 at 6:39 AM
  • <!date^1392734382^{date_short}^|Feb 18, 2014 PST> will display as: Feb 18, 2014


Some messages contain special words with extra behavior. For these we use the format <!foo>, where foo is a special command. Currently defined commands are !channel, !here, and !everyone. These indicate an @channel, @here, or @everyone message, and should cause a notification to be displayed by the client.

Note that to display @here on older mobile clients you will need to specify a label with the <!here> command (eg. <!here|here>).

For paid accounts, there is an additional command for User Groups that follows the format <!subteam^ID|@handle>. (subteam is literal text. ID and handle are replaced with the details of the group.) These indicate a User Group message, and should cause a notification to be displayed by the client. User Group IDs can be determined from the usergroups.list API endpoint. For example, if you have a User Group named happy-peeps with ID of S012345, then you would use the command <!subteam^S012345|@happy-peeps> to mention that user group in a message.

More commands will be added in the future. Unrecognized commands can be output as-is, with the enclosing brackets to indicate something about the text is special. If a label is present it should be used.

For example:

  • <!foo> should be displayed as <foo>
  • <!foo|label> should be displayed as <label>

Parsing modes

The function of username and username mentions is drastically changing throughout the Slack product and platform. See this changelog for further detail.

By default, messages you pass to API methods and webhooks will be assumed to be pre-formatted based on the above spec. That is, you can include marked up URLs, user links, channel links and commands, but we will still linkify any non-linked URLs present in your message.

IN  : Foo <!everyone> bar
OUT : Foo <!everyone> bar <>

By default, Slack will not linkify channel names (starting with a '#') and usernames (starting with an '@'). You can enable this behavior by passing link_names=1 as an argument. This behavior is always enabled in parse=full mode (see below).

IN  : Hello @bob, say hi to @everyone in #general
OUT : Hello <@U123>, say hi to <!everyone> in <#C1234|general>

If you don't want Slack to perform any processing on your message, pass an argument of parse=none.

IN  : Foo <!everyone> bar
OUT : Foo <!everyone> bar

(In this case, Slack will still test the validity of your markup - we won't send invalid messages to clients).

If you want Slack to treat your message as completely unformatted, pass parse=full. This will ignore any markup formatting you added to your message.

IN  : Foo <!everyone> bar
OUT : Foo &lt;!everyone&gt; bar <>

In full parse mode, we will find and linkify URLs, channel names (starting with a '#') and usernames (starting with an '@').

Multiline Messages

You can post multiline messages through Slack's APIs. Insert a newline by including the characters \n in your text. For example:

    "text": "This is a line of text.\nAnd this is another one."

The above JSON payload will be displayed in the channel as:

Screenshot of a webhook with a newline

Try it!


Slack attempts to normalize emoji across multiple platforms using the following approach:

  1. All emoji sent to Slack (as chat message to the message server, or arguments to the API) are translated into the common 'colon' format (e.g. :smile:)
  2. At display time, Slack clients are encouraged to convert these colon-sequences into native Emoji where available, otherwise fallback to images.

The Slack message server and API handle conversion from several binary emoji formats - the Unicode Unified format (used by OSX 10.7+ and iOS 6+), the Softbank format (used by iOS 5) and the Google format (used by some Android devices). These Unicode code points will be converted into their colon-format equivalents.

The list of emoji supported are taken from

Formatting and Attachments

You can create richly-formatted messages using Attachments. Learn how to add attachments to messages.

Screenshot of attachments with colors

We strongly recommend using a maximum of 20 attachments per message. Messages are limited to 100 attachments.

Message Formatting

Slack messages may be formatted using a simple markup language similar to Markdown. Supported formatting includes: ```pre```, `code`, _italic_, *bold*, and even ~strike~.; full details are available on our help site.

By default bot message text will be formatted, but attachments are not. To disable formatting on a non-user message, set the mrkdwn property to false. To enable formatting on attachment fields, set the mrkdwn_in array on each attachment to the list of fields to process. Some examples:

    "text": "*bold* `code` _italic_ ~strike~",
    "username": "markdownbot",
    "mrkdwn": true

Try it!

    "text": "*not bold*",
    "username": "markdownbot",
    "mrkdwn": false

Try it!

    "attachments": [
            "title": "Title",
            "pretext": "Pretext _supports_ mrkdwn",
            "text": "Testing *right now!*",
            "mrkdwn_in": ["text", "pretext"]

Try it!

Valid values for mrkdwn_in are: ["pretext", "text", "fields"]. Setting "fields" will enable markup formatting for the value of each field.

Limit the number of characters in the text field to 40,000 characters. Ideally, messages should be short and human-readable, if you need to post longer messages, please consider uploading a snippet instead.

How to display formatted messages

If you want to display formatted messages on the web, your client should take the following steps:

  1. Detect all sequences matching <(.*?)>
  2. Within those sequences, format content starting with #C as a channel link
  3. Within those sequences, format content starting with @U or @W as a user link
  4. Within those sequences, format content starting with ! according to the rules for the special command.
  5. For remaining sequences, format as a link
  6. Once the format has been determined, check for a pipe - if present, use the text following the pipe as the link label

Because the ampersands and angled brackets are already escaped, no further translation need take place (for a web-client). The server ensures that no extra un-escaped angled brackets or ampersands are included in the message.

When a client sends a message, the response that is returned by the server contains the server-formatted version of the message. Clients should use this to replace their own local version of the message so that urls are correctly highlighted.

Disabling markup processing

If you just want to turn Slack's markdown-like processing off so that all those characters (`*_```~) do nothing, include the mrkdwn attribute with a false value:

  "mrkdwn": false,
  "text": "*This will not be bold.* It will be surrounded gloriously with stars."

(Message Builder Example)

If you want to reinforce the default behavior explicitly, add a mrkdwn field to your message JSON and set it to true.

The mrkdwn attribute is missing vowels because our markup language is not quite markdown but something quite like it.