Slack Link Preview Not Working? How to Fix Unfurls
When you paste a link into a Slack message, Slack fetches the page and "unfurls" it into a preview with a title, a short description, the site name and often an image.
When the preview is missing, shows the wrong title or has no image, the cause is almost always one of six things: missing tags, an image Slack cannot load, Slack's crawler being blocked, a redirect or login in the way, a preview setting switched off in the workspace, or an old unfurl held in Slack's cache. This guide covers each one, how to tell which you have, and how to fix it.
How Slack builds a link preview
When a link is posted in a channel or direct message, Slack's servers request the page. The request
comes from Slack's link expander, which identifies itself with a user agent containing Slackbot-LinkExpanding.
Slack reads the HTML head, picks out the tags that describe the page, and then fetches the preview image
through its own image proxy, which uses a separate user agent containing Slack-ImgProxy.
The result is attached to the message as an unfurl.
Slack looks for information in this order:
- oEmbed. If the page links to an oEmbed endpoint with a
<link rel="alternate" type="application/json+oembed">tag, Slack can use it. This is how video and media sites get playable previews. - Twitter card and Open Graph tags. For most pages these are what Slack uses:
og:title,og:description,og:imageandog:site_name, with the matching Twitter tags used where they are present. - Plain HTML. If neither is present, Slack falls back to the
<title>and the meta description, and usually shows no image.
Three things follow from that. Slack reads the HTML your server sends, not what a browser builds after running JavaScript, so tags added by a script are invisible to it. The image is fetched separately, so the text can unfurl while the image stays blank. And Slack keeps its copy of the preview for a while, so fixing the page does not change a link that has already been unfurled.
The tags Slack reads
| Tag | What Slack uses it for | Notes |
|---|---|---|
og:title | The bold, linked title of the preview. | Falls back to <title>.
Keep it short enough to read at a glance. |
og:description | The text under the title. | Slack cuts long descriptions after a few lines. |
og:image | The preview image. | A full https address. Relative paths are ignored. |
og:site_name | The small source line above the title. | Without it Slack shows the domain. |
twitter:card | How large the image is shown. | summary_large_image
asks for a wide image rather than a small thumbnail. |
twitter:label1, twitter:data1 | Extra labelled fields under the description. | Optional. Useful for reading time, author, price or event date. |
link rel="icon" | The small icon next to the site name. | Use a full https address that loads without cookies. |
A correct set you can copy
<head>
<meta charset="UTF-8">
<title>Quarterly release notes: version 4.2 | Harbour Software</title>
<link rel="canonical" href="https://example.com/blog/release-4-2">
<link rel="icon" href="https://example.com/favicon-32.png">
<meta property="og:type" content="article">
<meta property="og:site_name" content="Harbour Software">
<meta property="og:url" content="https://example.com/blog/release-4-2">
<meta property="og:title" content="Version 4.2: faster exports and shared folders">
<meta property="og:description" content="Exports now run in the background, folders can be shared with guests, and search covers archived projects.">
<meta property="og:image" content="https://example.com/images/release-4-2-1200x630.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:label1" content="Reading time">
<meta name="twitter:data1" content="4 minutes">
<meta name="twitter:label2" content="Written by">
<meta name="twitter:data2" content="Priya Shah">
</head>
Put these tags near the top of the head, before large inline scripts or styles. Slack reads the start
of the page, and tags buried deep in a very large head can be missed. Open Graph tags use property=;
Twitter tags use name=.
Images Slack will show
A preview that shows the title and description but no picture is an image problem. Slack fetches the image through its own proxy, so the image address has to work for a visitor with no cookies, no login and no referrer from your site.
| Requirement | What works | What fails |
|---|---|---|
| Size | 1200 x 630 pixels for a wide image | Very small images are shown as a tiny thumbnail or dropped. |
| File size | Under 1 MB loads reliably | Very large files can time out while Slack fetches them. |
| Format | JPG, PNG or GIF | SVG is not shown; newer formats may not show in every Slack app. |
| Address | Full https URL returning 200 with an image content type | Relative paths, http addresses, addresses that redirect to a login page. |
| Access | Public, no cookies needed | Hotlink protection, signed CDN links that expire, images blocked by robots.txt. |
Check the image headers as well as the image. The server must send a Content-Type such
as image/png or image/jpeg. An image served as text/html or application/octet-stream,
which happens with some storage buckets and misconfigured CDNs, may not be shown.
curl -sI https://example.com/images/release-4-2-1200x630.png | grep -i "^content-type\|^HTTP"
release-4-2.png?v=2.When Slack cannot fetch the page
If a link that should unfurl produces no preview at all, Slack's link expander is probably not getting the page. Check these in order:
- robots.txt. Slack respects robots.txt for the link expander. A rule such as
User-agent: * Disallow: /, or a rule forSlackbot, stops the preview. Allow it, including the folder that holds your images. - Firewalls and bot protection. Cloudflare Bot Fight Mode, Wordfence, ModSecurity
rules and hosting "anti-bot" settings often challenge or block unknown crawlers. Look for
Slackbot-LinkExpandingandSlack-ImgProxyin the firewall log and add allow rules for both. - Login walls and cookie gates. A page that sends visitors without a cookie to a login or consent page gives Slack that page instead. The tags must be in the HTML served to a visitor with no cookies.
- Private and internal addresses. Slack's servers are on the public internet. Links to an intranet, a staging site behind a VPN or a site restricted by IP address cannot unfurl. For internal tools, a Slack app can supply its own previews instead.
- Slow responses. Slack gives up on pages that take several seconds to respond. Heavy pages built on every request are the usual cause.
Your server's access log settles the question. Post the link, then search the log. No line means the request was blocked before it reached the site; a 403, 429 or 503 means the site refused it; a 200 means the problem is in the tags or the image.
sudo grep -i "slackbot-linkexpanding\|slack-imgproxy" /var/log/nginx/access.log | tail -5
Slack settings, apps and repeated links
Sometimes the page is fine and Slack is choosing not to show a preview. These are the common reasons:
- Preview settings. In Slack's preferences, under the messages and media settings, each person can turn off text previews and images from linked websites. Workspace owners can also limit link previews. If one person sees no previews anywhere while others do, it is their setting, not your page.
- Removed previews. Whoever posts a message can remove its preview, and Slack may then stop offering previews for that site to that person. Check with a different account.
- Messages posted by apps. Messages sent through the API or an incoming webhook only
unfurl ordinary web pages when the app asks for it with
unfurl_linksset to true. Media links are controlled separately byunfurl_media. - Repeated links. Slack may not unfurl a link again if the same link was unfurled in the same channel a short time before.
- Several links in one message. Slack unfurls only a limited number of links per message, so a message listing many links will not preview all of them.
curl -s -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json; charset=utf-8" \
-d '{"channel":"C0123456789","text":"Release notes: https://example.com/blog/release-4-2","unfurl_links":true,"unfurl_media":true}'
Old previews and the Slack cache
Slack stores the preview it built for each address and reuses it for a period of time. That is why a fixed page can still post with the old title or image. Unlike LinkedIn and Facebook, Slack has no public tool to ask it to fetch a page again.
- Fix the page and purge any CDN or page cache for that address, so Slack will be served the new version.
- Wait a while and post the link again in a test channel; the cached preview expires on its own.
- If you need the new preview straight away, share the address with a harmless query string, such as
?v=2, which Slack treats as a new link. - Check the new preview in both the desktop app and the mobile app.
Messages that have already been posted keep the preview they were created with. Edit the message to remove and re-add the link, or post it again, to show the corrected preview.
Redirects, canonical URLs and single-page apps
- Redirect chains. Slack follows redirects, but each one adds delay and a chance of failure. Share the final address, and keep http-to-https and www redirects to a single hop.
- Content type of the page. The page itself must be served as
text/html. A page sent astext/plainor as a download will not unfurl. - JavaScript redirects and meta refresh. Slack does not run scripts, so a page that sends visitors on with JavaScript shows Slack the empty first page.
- Single-page apps. Sites built with React, Vue or Angular that set tags in the browser send Slack a near-empty head. Render the tags on the server, or pre-render the pages you share.
The fix, step by step
Step 1
Check what Slack can see
Run the page through the Social Preview checker, which shows the Open Graph and Twitter tags the way Slack reads them, together with the image size and address. Then post the link in a private test channel or a direct message to yourself and note what appears: the title, description, image, site name and any extra fields, or no preview at all. Keep a note of the result.
Step 2
Add the tags Slack reads
View
the page source, not the browser element inspector, and check that og:title, og:description,
og:image and og:site_name are in the head once each, near the top, with full
https addresses. Add twitter:card set to summary_large_image for a wide image, and twitter:label1
and twitter:data1 if you want an extra field such as reading time. Remove duplicate tags
added by a second plugin or the theme.
Step 3
Use an image Slack will load
Open the og:image address in a private browser window. It should load straight away as a JPG, PNG or GIF of about 1200 by 630 pixels and under 1 MB, and the server should send an image content type. If it redirects, asks for a login, is blocked by hotlink protection or is tiny, replace it, and give a changed image a new file name.
Step 4
Let Slackbot fetch the page
Check
robots.txt, the firewall and any bot protection such as Cloudflare Bot Fight Mode or Wordfence, then
post the link and search the server access log for Slackbot-LinkExpanding and Slack-ImgProxy.
No log line means the request was blocked before the site; a 403, 429 or 503 means the site refused it.
Allow both user agents wherever they are blocked or challenged.
Step 5
Rule out Slack settings and app posting
If the page and the log look right, test with a second Slack account, because each person
can switch off text previews and images from linked websites in their preferences. For messages sent
by an app or webhook, set unfurl_links to true. Post the link on its own, not in a long
list of links, and not straight after the same link in that channel.
Step 6
Force a fresh unfurl and check again
Purge any CDN or page cache for the address so Slack is served the fixed page. Slack has no refresh tool, so either wait for its cached preview to expire or post the address with a harmless query string such as ?v=2. Check the new preview in the desktop and mobile apps, then repost or edit older messages that still show the old card.
Stopping it from coming back
- Tags in the template. Generate Open Graph and Twitter tags on the server for every page from the page's own title, description and featured image, so no page goes out without them.
- A default image. Set a site-wide 1200 x 630 fallback image for pages with no featured image, so every preview has a picture.
- An allow rule for crawlers. Keep Slackbot-LinkExpanding, Slack-ImgProxy, LinkedInBot, facebookexternalhit, Twitterbot and WhatsApp on the firewall's allow list.
- New image, new name. Change the file name when you change a share image.
- Test before announcing. Post important links in a test channel before sending them to a large channel, because you cannot refresh a preview after everyone has seen it.
1. Why is my Slack link not unfurling?
Usually because Slack could not fetch the page, or because the page has no tags it can use. Check your server access log for Slackbot-LinkExpanding right after posting the link. No request means robots.txt, a firewall or bot protection blocked it; a 403 or 503 means your site refused it. If the request succeeded, check that og:title and og:description are in the HTML your server sends, and that your own Slack preview settings are switched on.
2. How do I refresh a Slack link preview?
Slack has no public tool to fetch a page again, unlike LinkedIn Post Inspector or the Facebook Sharing Debugger. Fix the page and purge any CDN cache, then either wait for Slack's cached preview to expire or post the address with a harmless query string such as ?v=2, which Slack treats as a new link. Messages already posted keep their old preview, so edit or repost them to show the corrected card.
3. Why does my Slack preview have no image?
Slack fetches the image separately through its image proxy, so the text can unfurl while the image fails. The usual causes are a missing og:image, a relative address instead of a full https address, an image behind hotlink protection or a login, an image blocked by robots.txt or a firewall, or a server that sends the wrong content type. Open the image address in a private window and check the headers to find which one applies.
4. What image size works best in Slack?
About 1200 by 630 pixels, saved as a JPG or PNG and ideally under 1 MB so Slack can fetch it quickly. Set twitter:card to summary_large_image if you want the image shown wide under the description rather than as a small thumbnail beside it. The same image works for LinkedIn, Facebook, X and WhatsApp, so one well-made share image covers every platform. Keep important text away from the edges of the picture.
5. Does Slack use Twitter card tags or Open Graph tags?
Both. Slack reads Open Graph tags such as og:title, og:description, og:image and og:site_name, and it also reads Twitter card tags. It uses twitter:card to decide how large to show the image, and twitter:label1 and twitter:data1 to show extra fields such as reading time or author. If neither set is present it falls back to the page title and meta description. Keep both sets on every page so every platform is covered.
6. Why do links posted by my Slack app or webhook not unfurl?
Messages sent through the Slack API or an incoming webhook only unfurl ordinary web pages when the app asks for it. Add unfurl_links set to true to the chat.postMessage call or webhook payload, and unfurl_media set to true for images and video. Also check that the link is in the text of the message, not only inside a block button, and that the page itself can be fetched by Slackbot from the public internet.
7. Can Slack show previews of internal or private pages?
Not by fetching them itself. Slack's link expander runs on Slack's servers on the public internet, so pages on an intranet, behind a VPN, behind a login or restricted by IP address cannot unfurl. For internal tools, build a Slack app that listens for the link_shared event and supplies its own preview with the chat.unfurl method. That way the app, which can reach the private page, decides what the preview shows.
The Social Preview checker fetches your page the way Slack, LinkedIn, X, Facebook and WhatsApp do, lists every Open Graph and Twitter tag, checks the image size and address, and shows each card side by side.
Open Social Preview Fixes โ