Guide

Threads link preview not showing

You paste a link into a Threads post and get bare text, a card with no image, or last month’s title. Threads builds that card from your page’s Open Graph tags, fetched by Meta. Most fixes are on your server, not in the app.

Threads Help does not publish how the link card is built, which user agent fetches the page, or how long a card is cached. What Meta does publish is its web crawlers page: FacebookExternalHit crawls links shared on “Meta’s family of apps, such as Facebook, Instagram, or Messenger” and “gathers, caches, and displays” a title, description, and thumbnail. That page does not name Threads. Threads is a Meta app and Meta lists no separate link-preview crawler, so this guide treats the Facebook rules as the best documented baseline and says so where that is an assumption.

Check a live URL on CardScope. The free partial check shows the meta tags and whether og:image and og:title are set. It is not a screenshot of Threads, and it does not refresh Meta’s cache. A paid check of every app shows X, LinkedIn, Slack, Discord, and iMessage. The link preview mockup draws a Facebook card from text you type, which is the closest Meta layout it has.

Fix checklist

  1. The tags are in the first HTML response. Put og:title, og:description, og:image, and og:url in the server HTML. A tag added by JavaScript after load is a common reason a crawler sees nothing. See JavaScript / SPA previews.
  2. The tags come early. Meta says Open Graph properties must be within the first 1 MB of the page, or they are cut off. Its sample curl asks for only the first 512 KB with a Range header, so keep the tags near the top of <head>.
  3. og:image is an absolute https:// URL. Use the full URL, not /og.png. The image must load for an anonymous request. See absolute OG image URL.
  4. Meta’s crawler can reach the page. Meta asks you to allow the crawler’s user agent or IP addresses. A firewall challenge, a bot-fight rule, a login wall, or a geo block returns the wrong page to the crawler. See crawler blocked.
  5. The page answers fast. Meta says the content must be crawlable “within a few seconds”, and that the server must support gzip and deflate.
  6. The image is a sensible size. 1200×630 PNG or JPEG is the usual cross-app default. Meta’s Facebook FAQ says images up to 8 MB and close to 1.91:1 work best, and images under 600×315 render as a small square on Facebook. Threads does not publish its own numbers. See OG image size.
  7. Width and height are declared. Meta caches images asynchronously, so the image may not render the first time a link is shared. It recommends og:image:width and og:image:height, or a scrape in the Sharing Debugger first.
  8. The post can carry a card. In the Threads API docs, a link preview is for text-only posts: “It will not work with image, video, or carousel posts.” With no link_attachment, the first URL in the text becomes the preview. The app may behave differently, but if you attach a photo, expect the photo, not a link card.

The Open Graph tag generator writes the tags, and the Open Graph image resizer crops an image to 1200×630 in the browser. Neither one posts to Threads.

What Meta reads

Meta’s sharing guide for webmasters lists the basic tags: og:url, og:title, og:description, and og:image. Without them, “the Facebook Crawler uses internal heuristics to make a best guess” at the title, description, and image. That guess is often the reason a card shows a logo, a cookie banner, or the wrong headline.

<meta property="og:title" content="A specific title, not the brand name">
<meta property="og:description" content="One or two sentences that match the page.">
<meta property="og:image" content="https://example.com/og/threads-guide.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="What the image shows">
<meta property="og:url" content="https://example.com/permalink">

The same guide says og:url is the canonical URL and that shares aggregate there, so point it at the clean permalink. See og:url vs canonical. Write the title and description for people, not for a keyword list. See OG title & description. twitter:* tags are for X; Meta’s guide does not list them.

The crawler, and the one that is not it

Meta lists these user agents for FacebookExternalHit:

facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)
facebookexternalhit/1.1

The same page describes meta-externalagent as a crawler “for use cases such as training foundation AI models or improving products by indexing content directly.” It is not the link-preview crawler. Blocking it in robots.txt is a separate choice from blocking facebookexternalhit. If a rule or a bot-management product blocks “Meta” as a whole, check which user agents it actually covers.

Meta says FacebookExternalHit may bypass robots.txt for security or integrity checks, that robots.txt changes can take up to 24 hours because crawlers cache it, and that IP allowlisting is the more secure option. It points at AS32934 for its IP ranges and says those change often.

Test it with curl

This is Meta’s own simulation command from the crawler page. It sends the crawler user agent and asks for the first 512 KB.

curl -v --compressed -H "Range: bytes=0-524288" -H "Connection: close" \
  -A "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)" \
  "https://example.com/your-page"

You want a 200 or 206 with your real HTML, not a 403, a challenge page, or a redirect to a login. Then pull out just the tags, and check the image the same way:

curl -sL --compressed -A "facebookexternalhit/1.1" "https://example.com/your-page" \
  | grep -iE 'og:(title|description|image|url)'
curl -sI -A "facebookexternalhit/1.1" "https://example.com/og/threads-guide.png"

The image response should be 200 with an image/png or image/jpeg content type. A curl with that user agent shows what your server does for that header. It does not prove a request came from Meta, and a WAF that checks IP addresses can treat your curl differently from the real crawler.

Refresh a stale card

Meta’s crawler page says that if content was not available when it was crawled, you can force a new crawl with the Sharing Debugger or the Sharing API. Paste the exact URL, read what the debugger found, and use “Scrape Again” after you fix the tags.

Images are cached by URL. Meta’s guide says “to update an image after it’s been published, use a new URL for the new image,” and its FAQ says not to delete the old image, because existing shares can turn into a white box. So publish og-v2.png rather than overwriting og.png.

Meta does not document whether a Threads post that already shows a card picks up a new scrape. After the debugger shows the new tags, check with a new Threads post or draft. This guide does not promise that old posts update. Clear Open Graph cache covers the other apps, and Facebook link preview covers the debugger in more detail.

Threads posts on the fediverse

If you turn on sharing to the fediverse, Threads Help says new posts are shared to other servers after a 15-minute delay, and posts with a poll or limited replies are not shared. Meta’s engineering post on Threads in the fediverse says a link attachment is appended to the end of the post as a link if it is not already in the text.

So on Mastodon and similar servers, the reader sees a link, and that server builds its own card. On Mastodon, each server fetches the page itself with a Mastodon/ user agent. A Threads card that looks right does not prove the Mastodon card does, and the other way around. Bluesky is separate from both: its card is stored in the post when it is written.

FAQ

Does Threads use the Facebook crawler?

Meta does not say so on a Threads page. Its crawler page says FacebookExternalHit handles links shared on Meta’s family of apps and lists no other link-preview crawler. Allow facebookexternalhit and check your logs when you post a link to see what actually fetches it.

Will the Sharing Debugger fix a Threads card?

It forces Meta to crawl the URL again, and it shows what Meta’s crawler gets. Meta does not document that Threads reuses that result for a card already in a post. Use it to confirm the fix, then test with a new post.

Why does the card show the wrong image?

Usually there is no og:image and Meta guessed, the og:image is relative or behind a login, or Meta cached an older image at the same URL. Give the new image a new URL and scrape again.

Can I edit the card inside Threads?

Threads Help does not document an editor for the title or image of a link card. Change the tags on your page.

What does a CardScope check cost?

The five previews and the fix checklist are Pro: $19 once, not a subscription. No account. A sample report shows that result before you pay. The free partial check shows the meta tags and whether og:image and og:title are set. We parse HTML in memory and discard it — we do not store the page. The sample is not a Threads preview either.