Open Graph Tags for Threads, Bluesky, and Mastodon in 2026 — The Complete Federated Link Preview Guide

May 17, 2026 · 9 min read · By TinyTools

For ten years the link-preview conversation had two columns: Facebook and Twitter. In 2026 it has at least five — and three of them (Threads, Bluesky, and the entire Mastodon federation) read Open Graph slightly differently, cache it on different schedules, and silently drop your preview card for reasons that never show up in a validator. If your share rate dropped after you stopped chasing Twitter’s API and started posting where the conversation actually is, this is probably why.

This is a working field guide to what each platform’s fetcher does in 2026, the five quirks that kill preview cards, and a single copy-paste meta block that renders correctly on all three without per-platform branching.

What changed in 2026: the fediverse is now most of your reach

Threads cleared 320 million monthly actives this spring and turned on full ActivityPub federation by default. Bluesky crossed 50 million accounts after the December onboarding wave and is the de-facto replacement for tech Twitter. Mastodon’s top 200 instances now host roughly 12 million active accounts, and ActivityPub bridges mean a post from any of them can land in a feed on the others.

Practically: the same blog post URL is now being fetched by three preview services with three different fetcher behaviors, and the worst-case rendering is the one your audience sees. Optimize for the strictest fetcher and the rest take care of themselves.

How each platform fetches and renders previews

The underlying protocol is the same on all three — an HTTP GET that parses the HTML <head> for Open Graph and Twitter Card meta tags — but the way that GET is made differs in ways that matter:

PlatformFetcher timeoutJS executed?User-AgentCache lifetime
Threads~5sNometa-externalagent~7 days (per-edge)
Bluesky~3sNoBluesky Cardyb/1.0~24 hours
Mastodon~10sNoMastodon/x.y.z (per instance)~14 days (per instance)

None of them execute JavaScript. Every meta tag you care about has to be in the static HTML response, before any client-side hydration runs. This is the single most common failure mode in 2026: pages that work fine on Twitter (which never executed JS either) and on Slack (which has a much longer fetcher window) silently render as bare URLs on Bluesky because the 3-second budget expired before the framework finished serializing the head.

The minimum-viable meta block that works everywhere

Drop this in your HTML <head> and you cover all three platforms plus the Twitter, Facebook, Slack, Discord, iMessage, and LinkedIn fetchers as a bonus. Inline-replace the four {...} values per page:

<!-- Open Graph (Threads, Bluesky, Mastodon, FB, LinkedIn, Slack, Discord) -->
<meta property="og:title" content="{Page title, <= 60 chars}" />
<meta property="og:description" content="{Summary, <= 155 chars}" />
<meta property="og:image" content="https://example.com/og/{page}.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="{Describe the image, <= 100 chars}" />
<meta property="og:url" content="https://example.com/{canonical-path}/" />
<meta property="og:type" content="article" />
<meta property="og:site_name" content="{Brand name}" />

<!-- Twitter Card (used as fallback by Threads on iOS) -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="{Page title, <= 60 chars}" />
<meta name="twitter:description" content="{Summary, <= 155 chars}" />
<meta name="twitter:image" content="https://example.com/og/{page}.png" />

Three things in that block are non-obvious and matter a lot in 2026. First, og:image:width and og:image:height are how Bluesky decides between the small and large card layouts — omit them and you get the small card every time, which has roughly half the click-through. Second, og:image:alt is the only one of these tags that affects accessibility on Mastodon and is read aloud by screen readers in feeds. Third, og:site_name shows up as the byline on Threads but as the source-attribution chip on Bluesky — both worth claiming.

Generate the full meta block in 30 seconds

Paste your URL, title, and description — get a clean, validator-passing meta block with OG, Twitter Card, JSON-LD, and canonical tags ready to drop into <head>. Runs entirely in your browser.

Try the SEO Meta Generator free →

The five silent failures (and how to spot them)

1. Client-rendered meta tags

If your framework injects og:* tags after hydration (React Helmet without SSR, Vue Meta in SPA mode, Next.js with 'use client' at the top of the page), Bluesky will time out and Mastodon will fetch only the bare HTML shell. The fix is server-side rendering or static export of the head — not just the body. Facebook’s sharing debugger still shows the same response Bluesky and Threads see, so use it to verify.

2. Large or slow-loading og:image

An og:image over about 5 MB will be dropped by Bluesky and downsampled to a placeholder by Threads. Cap to under 1 MB, encode as JPEG or compressed PNG, and serve from a CDN. If your OG images render dynamically (Next.js @vercel/og, Cloudflare workers), pre-cache the response so the first fetcher does not hit a 4-second cold start.

3. Stale Mastodon cache

Each Mastodon instance caches preview cards independently for up to 14 days. If you republish a post and the image looks wrong, do not assume your tags are broken — append ?v=2 (or any tracking param) to the URL when sharing. Each instance treats it as a new resource and refetches.

4. Bluesky’s 1.91:1 hard crop

Bluesky crops og:image to a 1.91:1 aspect ratio in feed regardless of what you declare. A 1200×630 image (already 1.91:1) renders identically. A 1200×1200 square gets its top and bottom 23 percent sliced off. Keep critical text and faces in the centered 1200×630 safe zone — the same zone used for Twitter Cards and Threads, so this is a one-template-fits-all problem.

5. Mixed-protocol canonical mismatch

If og:url uses HTTPS and an inbound share link uses HTTP (or has a trailing slash difference), Threads sometimes shows the bare link instead of the card. Always include a self-referencing <link rel="canonical"> matching og:url exactly, and redirect HTTP → HTTPS at the edge before the fetcher reaches the page.

Validation: a 60-second check across all three platforms

  1. Run the URL through OpenGraph.xyz — it simulates the bare-HTML fetch all three fetchers use.
  2. For Bluesky specifically, paste the URL into the compose box on web (without posting) and confirm the card renders within 3 seconds. If it does not, your TTFB is the problem.
  3. For Mastodon, paste the URL into a draft on mastodon.social or your home instance and watch the card render. If it shows on one instance but not another, you have a cache or fetcher issue, not a meta tag issue.
  4. For Threads, the in-app composer renders previews live as you type the URL — the fastest of the three to verify visually.

The ActivityPub-specific tags worth adding (optional)

None of these are required for link previews, but they unlock other federated-social behaviors:

What about Threads’ new "context cards"?

Threads is testing an extended card format that pulls additional structured data — author, published date, reading time — from a page’s JSON-LD Article schema. It is not live for every account yet, but pages that already have valid JSON-LD inherit the richer card automatically when rollout hits. This is the second-cheapest 2026 social win after fixing your OG tags: most CMSs ship valid Article schema, and the same JSON-LD also feeds Google AI Overviews and Bing’s generative answers.

A reasonable copy-paste workflow

For most blogs and SaaS landing pages in 2026, the entire problem reduces to: render Open Graph and Twitter Card tags server-side, point to a 1200×630 image under 1 MB, set og:image:width and og:image:height so Bluesky picks the large card, and add og:image:alt for Mastodon’s screen readers. Everything else (instance caching, fetcher timeouts, ActivityPub niceties) is optimization. Get that base right and your link previews will work on Threads, Bluesky, Mastodon, and every legacy platform that still bothers fetching them.

If you would rather not hand-write the block, the SEO Meta Generator outputs the exact template above with your fields plugged in, including the JSON-LD Article schema that unlocks Threads’ context cards. Paste your URL, title, description, and image URL — copy the result into <head> — you are done.

Get a clean OG + Twitter Card + JSON-LD block in 30 seconds

Browser-only. No upload. Outputs the exact meta block above, validator-clean, ready to paste into your HTML <head>.

Try the SEO Meta Generator free →