/ โ† Social Preview Fixes / Slack Preview
In this guide
  1. How Slack builds a link preview
  2. The tags Slack reads
  3. Images Slack will show
  4. When Slack cannot fetch the page
  5. Slack settings, apps and repeated links
  6. Old previews and the Slack cache
  7. Redirects, canonical URLs and single-page apps
  8. The fix, step by step
  9. Stopping it from coming back
  10. Questions and answers

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:

  1. 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.
  2. Twitter card and Open Graph tags. For most pages these are what Slack uses: og:title, og:description, og:image and og:site_name, with the matching Twitter tags used where they are present.
  3. 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.

๐Ÿ’ก Slack has no public debugger like Facebook's Sharing Debugger or LinkedIn's Post Inspector. The quickest test is to post the link in a private channel or in a direct message to yourself, and to check your server log for the Slackbot request at the same moment.

The tags Slack reads

TagWhat Slack uses it forNotes
og:titleThe bold, linked title of the preview.Falls back to <title>. Keep it short enough to read at a glance.
og:descriptionThe text under the title.Slack cuts long descriptions after a few lines.
og:imageThe preview image.A full https address. Relative paths are ignored.
og:site_nameThe small source line above the title.Without it Slack shows the domain.
twitter:cardHow large the image is shown.summary_large_image asks for a wide image rather than a small thumbnail.
twitter:label1, twitter:data1Extra 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.

RequirementWhat worksWhat fails
Size1200 x 630 pixels for a wide imageVery small images are shown as a tiny thumbnail or dropped.
File sizeUnder 1 MB loads reliablyVery large files can time out while Slack fetches them.
FormatJPG, PNG or GIFSVG is not shown; newer formats may not show in every Slack app.
AddressFull https URL returning 200 with an image content typeRelative paths, http addresses, addresses that redirect to a login page.
AccessPublic, no cookies neededHotlink 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"
โš ๏ธ If you change the image but keep the same file name, Slack, CDNs and browsers may keep serving the old one. Give a changed image a new file name, or add a version to the address, such as 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:

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:

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.

  1. Fix the page and purge any CDN or page cache for that address, so Slack will be served the new version.
  2. Wait a while and post the link again in a test channel; the cached preview expires on its own.
  3. 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.
  4. 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.

๐Ÿ’ก Make sure the page with the query string still has a canonical tag pointing to the clean address, so search engines do not treat the versioned link as a separate page.

Redirects, canonical URLs and single-page apps

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

Questions and answers

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.

Check your link preview now

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 โ†’
๐Ÿ’ฌ Got a problem?
Related Guides: All Social Preview Fixes  ·  Social Preview Guide  ·  LinkedIn Link Previews  ·  Discord Link Previews  ·  Learning Hub

About aiwebpageseo

aiwebpageseo.com is a data-driven SEO and AEO (Answer Engine Optimisation) platform providing a free suite of technical SEO tools. Rather than relying on AI-theorised assumptions, the platform analyses live URL performance, delivering objective diagnostics, page speed metrics, CLS debugging, and site crawl data alongside actionable technical tutorials.