Formatting text for app surfaces

App surfaces — such as messages, modals, or Home tabs — can contain all types of textual treasures.

The Block Kit elements that form the layouts for these surfaces frequently use text objects to insert all kinds of content.

These text objects can be left as unformatted plain_text, or formatted with mrkdwn to create useful visual highlights or avail of syntax to trigger special parsing. This reference guide explains all of the mrkdwn formatting options available to use in text objects.

These instructions are also handy if you are retrieving messages and want to understand how to interpret the formatting syntax.

These are developer instructions covering content posted to Slack via APIs. For user instructions on text formatting in Slack clients, consult this help center article.


Escaping text

First, it's important to know that there are some characters in text strings that must be escaped.

Slack uses &, <, and > as control characters for special parsing in text objects, so they must be converted to HTML entities if they're not used for their parsing purpose:

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

Slack will take care of the rest.

You shouldn't HTML entity-encode the entire text, as only the specific characters shown above will be decoded for display in Slack.


Basic formatting with mrkdwn

Text objects contain a text field that can be formatted using a simple markup language called mrkdwn.

Use it in most Block Kit text objects by specifying a type of mrkdwn. There are, however, a few Block Kit blocks and elements that only allow plain_text with no formatting — these are called out in the Block Kit reference guides.

mrkdwn is also the default formatting method for the top-level text field in a message object when using the Web API to publish a message.

Finally, mrkdwn can be used within secondary message attachments by using the mrkdwn_in field as shown in the relevant reference guide.

This formatting is similar to Markdown markup, but with its own syntax, shown below.

Visual basics

These basic visual styles are very simple to use:

  • _italic_ will produce italicized text
  • *bold* will produce bold text
  • ~strike~ will produce strikethrough text

Line breaks

You can use multi-line text in app-generated text. Insert a newline by including the string \n in your text. For example:

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

Will produce the following formatting:

This is a line of text.
And this is another one.

Quotes, inline code blocks, lists

These styles help to organize or differentiate text for different purposes.

Block quotes

You can highlight some text as a block quote by using the > character at the beginning of one or more lines:

This is unquoted text\n>This is quoted text\n>This is still quoted text\nThis is unquoted text again

View this example

Code blocks

If you have text that you want to be highlighted like code (like this), surround it with back-tick (`) characters:

This is a sentence with some `inline *code*` in it.

View this example

Text within inline code blocks will not use any other formatting, so it can be useful even if you're not displaying actual code.

You can also highlight larger, multi-line code blocks by placing 3 back-ticks before and after the block:

```This is a code block\nAnd it's multi-line```

View this example

Lists

There's no specific list syntax in app-published text, but you can mimic list formatting with regular text and line breaks:

- Detective Chimp\n- Bouncing Boy\n- Aqualad

View this example


Links

To link to URLs casually in conversation, include the URL directly in mrkdwn text and it will be auto-transformed by the server into a link:

This message contains a URL http://example.com/
So does this one: www.example.com

You can also use mrkdwn to manually add links:

This message contains a URL <http://example.com/>

Adjust the text that appears as the link from the URL to something else:

<http://www.example.com|This message *is* a link>

And create email links:

<mailto:bob@example.com|Email Bob Roberts>

View these examples

You can also use Block Kit buttons as links by using the url parameter in button elements.

When you use any of the messaging APIs to retrieve a message, you'll see that auto-transformed URLs are shown in the mrkdwn format. So this:

This message contains a URL http://example.com/

Will be represented in the API as:

This message contains a URL <http://example.com/>

While this message:

So does this one: www.example.com

Will be retrieved in this form:

So does this one: <http://example.com|www.example.com>

Emoji

Emoji can be included in their full-color, fully-illustrated form directly in text.

Once published, Slack will then convert the emoji into their common 'colon' format. For example, a message published like this:

It's Friday 😄

will be converted into colon format:

It's Friday :smile:

If you're publishing text with emojis, you don't need to worry about converting them, just include them as-is.

If you're retrieving messages, you'll receive the emojis in colon format, so you might want to convert them back to their unicode emoji form.

The compatible emoji formats are 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 will be converted into their colon-format equivalents.

The list of emoji supported are taken from https://github.com/iamcal/emoji-data


Advanced formatting with special parsing

We told you earlier about the need to escape certain strings in text objects. These strings are used to trigger special parsing of the text, like user mentions or advanced date formatting. Read on to learn more about this advanced formatting.

Linking to public channels

Text can refer to a public Slack channel and transform that reference into a link to the channel itself. This uses a similar mrkdwn syntax as regular URL links:

Why not join <#C024BE7LR>?

View this example

#C024BE7LR is the channel's ID. Your app can get this ID from an interaction request payload, from the Event API payload sent when one of the event types occurs, or by looking it up directly with the conversation-related methods of the Web API.

You can also manually retrieve a specific channel's ID from its URL (highlighted here):

URL bar showing channel ID highlighted in green and yellow

When text containing the channel linking syntax is published in an app surface, the ID will be automatically converted to show the actual name of the conversation.

Remember you can only link to public channels. If you try to include a link to a private conversation, it will display as raw text.

If you're retrieving messages, use the conversations.info Web API method to lookup by channel ID and find out other relevant information (such as the actual name of the channel).


Mentioning users

A mention is a special type of reference that will provide a link to the mentioned user's profile in the published text.

If the mention is included in an app-published message, the mentioned user will also be notified about the reference. The help center page for mentions describes what that notification process looks like.

To mention a user in app-published text, you need to provide their user ID in the following syntax:

Hey <@U024BE7LH>, thanks for submitting your report.

View this example

Your app can get this user ID from an interaction request payload, from the Event API payload sent when one of the event types occurs, or by looking them up via the users.list Web API using another unique piece of information you have about them (such as their email address).

You can also manually retrieve a specific user's ID by clicking on the overflow button in their Slack profile, and choosing the Copy member ID option, as shown in the screenshot.

Menu showing user ID in Slack profile

When text containing the user-mention syntax is published by an app, the ID will be automatically converted to show the display name of the user.

If you're retrieving messages, you can use the users.info Web API method to lookup by user ID and find out other relevant information, such as their display name.


Mentioning groups

As with users, you can mention user groups, which will link to the group's profile.

If the mention is included in an app-published message, Slack will notify each user in the group about the mention.

To mention a user group in app-published text, you need to provide the group ID in the following general syntax:

`<!subteam^ID>`

!subteam^ is a literal string that should not change, but ID should be replaced with the actual user group ID. Here's an example:

Hey <!subteam^SAZ94GDB8>, there's a new task in your queue.

View this example

Your app can get this group ID from the Event API payload sent when one of the subteam event types occurs, or by looking them up via the usergroups.list Web API.

You can also manually retrieve a specific user group's ID from the URL shown when viewing its profile (highlighted here):

URL bar showing user group ID highlighted in green and yellow

When text containing the user group mention syntax is published by an app, the ID will be automatically converted to show the name of the user group.

If you're retrieving messages, you can use the usergroups.list Web API method to lookup by user group ID and find out other relevant information.


Special mentions

These special groups should be mentioned sparingly, as they tend to notify a large group of users. We don't have any specific guidelines, but use your discretion and favor mentioning individuals or more specific groups where possible.

There are a few core user groups built into Slack that can be mentioned in app-message text. These are:

  • @here notifies only the active members of a channel
  • @channel notifies all members of a channel, active or not
  • @everyone notifies every person in the #general channel (ie. every non-guest member of a workspace).

To add these to an app-published message, use the following syntax:

Hey <!here>, there's a new task in your queue.

Where here can be replaced with channel or everyone. Note that to display @here mentions correctly on older mobile clients you will need to specify a label with the <!here> command:

<!here|here>

Date formatting

Text containing a date or time should display that date in the local timezone of the person seeing the text. For app-published text, there is a handy date syntax available to format a Unix timestamp, and Slack will handle the timezone localization for you.

The <!date> command will format the timestamp using tokens within a string that you set, and it must include some fallback text for older Slack clients. Here's the general syntax to use:

<!date^timestamp^token_string^optional_link|fallback_text>

This wall of text can be broken down as follows:

  • The wrapping <> is used as a control character for the whole string, and ^ is used to divide different parts of the string
  • !date indicates to use the special date parsing
  • timestamp is a number in standard Unix time format, the date and time that you want to include in your text
  • token_string should provide a formatting for your timestamp, using plain text along with 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. The year will be omitted if the date refers to the current year.
    • {date_short} is displayed as Feb 18, 2014. The year will be omitted if the date refers to the current year.
    • {date_long} is displayed as Tuesday, February 18th, 2014. The year will be omitted if the date refers to the current year.
    • {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.
  • optional_link can be provided if your timestamp needs to be linked, specified using a standard, fully qualified URL.
  • fallback_text should be included 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.

Here are some examples of date formatting strings:

<!date^1392734382^Posted {date_num} {time_secs}|Posted 2014-02-18 6:39:42 AM PST>

View this example

<!date^1392734382^{date} at {time}|February 18th, 2014 at 6:39 AM PST>

View this example

<!date^1392734382^{date_short}^https://example.com/|Feb 18, 2014 PST>

View this example

If you're retrieving messages, you will receive the <!date> string back in its original format, and you can use the information above to parse it if necessary.


Automatic parsing

Above, we explained how to include various types of special syntax in your app-published text. What we didn't mention is that you can just include the same text as a user would post directly in Slack to achieve some of these things. For example, given the following text:

<http://example.com|example link> http://example.com #general @here 🤩 :smile:

Most of these references can be automatically parsed upon publishing to turn them into links or mentions:

<http://example.com|example link> <http://example.com> <#C0838UC2D|general> <!here> :star-struck: :smile:

You can achieve this in different ways, depending on where the text is being placed:

Disabling automatic parsing

If you want to disable automatic parsing, you have a couple of options depending on the type of text:

  • For text in layout blocks set a verbatim attribute of your text objects to true.
  • For the top-level text field, or text in secondary message attachments, as long as you exclude the link_names argument when publishing, this will be disabled by default. Regular URLs will still be converted into clickable links however - to disable this, pass the parse argument with a value of none when publishing.

Why you should consider disabling automatic parsing

Even with this functionality available, we still recommend that you use the manual methods shown above. (This is also why we didn't mention it earlier.)

This is important because the names of conversations or user groups may change at any time. What was previously a functioning reference may no longer work. Meanwhile, an ID will always remain the same. The same holds true for special mentions like @here.

Another good reason to disable automatic parsing is to be more explicit about where you want to include links and mentions. This could prevent random text from being unintentionally parsed and turned into one.

For example, imagine your app passes user input from a third-party service straight into the published text. Using automatic parsing, if this user text contained a string like @everyone, your app could unintentionally send a notification to the entire workspace.

We've already deprecated this functionality for user mentions, so always parsing manually will keep you prepared in case automatic parsing is deprecated for other entities like conversations or user groups in the future.


Disabling formatting

If you want to turn Slack's markdown-like processing off, you have different options depending on where the text is:


Notes on retrieving formatted messages

If you're retrieving messages, we've included some extra details in the sections above to help you parse the formatting syntax. This will let you properly format it for display on a different service, or to help your app fully understand the intent of a message. Here are the general steps involved for detecting advanced formatting syntax:

  1. Detect all sub-strings matching <(.*?)>
  2. Within those sub-strings, format content starting with #C as a channel link
  3. Format content starting with @U or @W as a user mention
  4. Format content starting with !subteam as a user group mention
  5. Format content starting with ! according to the rules for special mentions
  6. For any other content within those sub-strings, format as a URL link
  7. Once the format has been determined, check for a pipe (|) - if present, use the text following the pipe as the label for the link or mention.

Beyond formatting

This guide gives a taste of the possibilities offered by simply formatting and modifying the text included in each app surface.

But there's even more you can do to change the visual composition of those app surfaces.

Read our Block Kit guides to learn how to use blocks and block elements to compose complex layouts.

Was this page helpful?