Guide

Mastodon link preview not showing? How Mastodon builds link cards

You post a link on Mastodon and get a bare URL, a card with no picture, or a card that still shows last month’s title. Some people see the card and others do not. That is because Mastodon has no central crawler: every server that carries the post fetches your page itself and keeps its own copy of the card.

The details below come from Mastodon’s own code — FetchLinkCardService and LinkDetailsExtractor, as of the 4.7 release — and the PreviewCard and profile docs. Servers run different versions, so treat a real post as the final check.

Check a live URL on CardScope. The free check shows the meta tags and whether og:image and og:title are set. It is not a screenshot of Mastodon, and it cannot refresh a card a Mastodon server already stored. A paid check of every app still shows X, LinkedIn, Slack, Discord, and iMessage.

To sketch the words and the picture before the page is live, the link preview mockup draws X, Facebook, LinkedIn, Slack, Discord, and iMessage from text you type. It does not draw a Mastodon card. The tags are the same Open Graph set.

Every server fetches your page itself

When someone publishes a post with your link, their server queues a fetch of your page. When the post reaches other servers, each one queues its own fetch of the same URL. Current Mastodon spreads those remote fetches over a random delay of up to one minute so they do not all land at once. The card is not copied from the author’s server. A post from an account with followers on 2,000 servers can mean roughly 2,000 requests for your page and 2,000 for your image within a minute or two.

That is why the result can differ by server. If a WAF, a bot challenge, or a rate limit rejects some of those requests, the users on those servers get no card — or a card with no image — while everyone else sees it fine. You cannot allow-list Mastodon by IP address: there are thousands of servers, each on its own IP.

What one fetch looks like in current source:

If your site sits behind a firewall or a bot manager, crawler blocked covers the allow rules. For Mastodon, the rule should let a short burst of Mastodon/ requests through rather than challenge them.

Which tags Mastodon reads

Mastodon matches a meta tag by property or name, case-insensitively. If a schema.org JSON-LD block of type NewsArticle or WebPage is on the page, its values win over the Open Graph ones for title, description, and site name — so a stale headline in JSON-LD will beat a fixed og:title.

Card fieldRead from, in order
TitleJSON-LD headline → og:title → <title>. No title means no card is saved.
DescriptionJSON-LD description → og:description → <meta name="description">
Imageog:image only
Image alt textog:image:alt
Site nameJSON-LD publisher.name → og:site_name
Author nameJSON-LD author.name → og:author
Author accountfediverse:creator (see below)
Published dateJSON-LD datePublished → article:published_time
Card URL<link rel="canonical"> → og:url, only if it is on the same host as the fetched page
Video playertwitter:player, with twitter:player:width and twitter:player:height

What is not read: twitter:title, twitter:description, and twitter:image. A page that only has Twitter Card tags gets its title from <title>, its description from the meta description, and no image. Add the Open Graph set — the Open Graph tag generator writes it.

oEmbed is tried first. If the page advertises an oEmbed endpoint (<link type="application/json+oembed">), Mastodon asks it before reading Open Graph. A rich oEmbed response is ignored and Open Graph is used instead. A link, photo, or video response becomes the card, and oEmbed has no description field — so if your endpoint answers with link, the card will have no description no matter what og:description says.

Image requirements

Reasons a post gets no card at all

Cards are cached per server

Each server keeps one stored card per URL and attaches it to every post on that server that links the URL. Editing your page does not change cards that servers already stored, and there is no Facebook-style debugger that tells every server to look again.

What actually refreshes a card, on one server at a time:

Clear Open Graph cache covers Slack, X, LinkedIn, Discord, Facebook, and iMessage. Bluesky is different again: there the card is stored inside the post when it is composed.

Credit the author with fediverse:creator

Since Mastodon 4.3, a card can show the author’s fediverse account under the link. Add one tag to the page:

<meta name="fediverse:creator" content="@you@mastodon.example">

The tag alone is not enough. The account it names must list your site’s domain under Preferences → Public profile → Verification → Author attribution (“Websites allowed to credit you”). That stops any site from claiming to be written by you. The handle can be on any fediverse software that publishes that list of allowed domains, and if a page has more than one tag, the first is used.

Add the domain before the link is shared. A server that fetched the page before the domain was allowed has already stored a card without the byline, and the refresh rules above apply.

A minimal set

<title>A specific title, not the brand name</title>
<meta name="description" content="One sentence that matches the page.">
<link rel="canonical" href="https://example.com/permalink">
<meta property="og:title" content="A specific title, not the brand name">
<meta property="og:description" content="One sentence that matches the page.">
<meta property="og:image" content="https://example.com/og.png">
<meta property="og:image:alt" content="What the picture shows">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:site_name" content="Example">
<meta property="og:url" content="https://example.com/permalink">
<meta name="fediverse:creator" content="@you@mastodon.example">

Width and height are not read for a link card. They are here for the other apps. Length and wording are in OG title & description, and og:url vs canonical covers the URL tags.

Test it like a Mastodon server

Read the first response, not the Elements panel after JavaScript has run. Use a Mastodon-style user agent so a bot rule that treats Mastodon differently shows up:

UA='Mastodon/4.7.3 (http.rb/5.3.1; +https://mastodon.social/) Bot'

# Final status and Content-Type after redirects: want 200 and text/html
curl -sIL -A "$UA" -H 'Accept: text/html' https://example.com/your-page

# The tags Mastodon reads, in the HTML the server sent
curl -sL -A "$UA" -H 'Accept: text/html' https://example.com/your-page \
  | grep -iE 'og:|fediverse:creator|

Then open view-source: on the same URL in a browser and confirm the same og: tags are there. If the curl requests get a 403, a 429, or a challenge page while the browser works, fix the firewall first — the tags do not matter yet. A single curl will not reproduce a burst from hundreds of servers, so check your rate-limit rules too.

Fix checklist

  1. The page answers 200 with text/html to a Mastodon/ user agent, after redirects, without a challenge.
  2. Rate limits and bot rules allow a burst of Mastodon/ requests for the page and the image.
  3. og:title, og:description, and og:image are in the server-rendered HTML, early in <head>.
  4. Any NewsArticle or WebPage JSON-LD has the same headline and description as the Open Graph tags.
  5. You are not relying on twitter:title, twitter:description, or twitter:image alone.
  6. og:image is an absolute, public https:// URL to a JPEG, PNG, GIF, or WebP under 8 MB.
  7. If the page advertises oEmbed, the endpoint does not answer with type link unless you are fine with no description.
  8. A changed image has a new URL.
  9. fediverse:creator names your handle, and your account allows the domain — before you share.
  10. To check a fix, post the URL in a new post without media. Old posts on servers that already stored the card keep it until the refresh rules above apply.

FAQ

Who fetches my page when a link is posted on Mastodon?

Every server that stores the post. The author’s server fetches it when the post is published, and each server that receives the post fetches it again on its own, within about a minute. A rate limit or firewall that blocks some of them leaves their users with no card.

Which tags does Mastodon read?

og:title, og:description, og:image, og:image:alt, og:site_name, and article:published_time, with <title> and the meta description as fallbacks. A NewsArticle or WebPage JSON-LD block wins for title, description, and site name. The twitter: title, description, and image tags are not read.

Why does an old post still show the old card?

Each server stores one card per URL and reuses it. A server fetches again only when someone on it posts the link and the stored card is at least two weeks old or has no image. A changed image at the same URL is not downloaded again.

How does fediverse:creator work?

Add <meta name="fediverse:creator" content="@you@mastodon.example"> to the page, and list your site’s domain under Author attribution in that account’s profile settings. Mastodon 4.3 and later show the byline with a link to the account.

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 is the way to see that result before you pay. The free 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 Mastodon preview either.