TrafficTriage

og:image Not Showing? Fix Your Broken Link Preview

By Ugur Saritepe · July 8, 2026

You paste your link into X, LinkedIn, Slack, or iMessage and the preview comes up with no image — just text, or a blank grey box. Nearly always it's one of six things: the og:image tag is missing, it points at a relative or dead URL, it's the wrong file type, or the preview is cached from before you fixed it. You can find which one in about a minute.

The one-minute self-diagnosis

Read the og:image line straight out of your raw HTML — the HTML the server sends, before any JavaScript runs:

curl -s https://yourdomain.com | grep -i og:image

The output tells you which problem family you are in:

One fact underpins all of this: social preview crawlers — facebookexternalhit, Twitterbot, LinkedInBot, Slackbot — read the raw HTML and do not run your JavaScript. A tag your React code adds on the client is invisible to them. Always check the source, not what devtools shows after the page hydrates.

The six causes, most common first

1. There's no og:image in the raw HTML

Either you never added one, or you added it in client-side code so it only appears after JavaScript runs. Since scrapers don't run JavaScript, a client-rendered tag might as well not exist.

30-second check: the curl … | grep above prints nothing, but the tag doesshow when you inspect the live DOM in devtools. That gap is the tell — it's being rendered on the client.

Fix: emit og:imagein the HTML the server sends. In Next.js, set it in the route's metadata (the metadata export or generateMetadata in the App Router) so it ships in the initial HTML — never in a useEffect or a client component.

2. The URL is relative, not absolute

og:image must be a full absolute URL — https://yourdomain.com/og.png, never /og.png. A browser resolves a relative path against the current page, so it looks fine when you visit; a social scraper often won't, and as of July 2026 Facebook rejects a relative og:image outright. This is the single most common cause of a blank preview.

30-second check: read the content="…" value from the diagnosis step. It must start with https://. A leading slash or ./means it's relative.

Fix: emit the absolute URL. In Next.js this is exactly what metadataBase is for — set metadataBase: new URL("https://yourdomain.com") in your root layout and Next composes your relative image path into a full URL. Current Next.js versions treat a relative og:image with no metadataBase as a build error, so on that stack this usually surfaces before you deploy — but an SPA or a hand-rolled <head> gives you no such warning.

3. The image URL doesn't return a 200 image

The tag is there and absolute, but the URL 404s, redirects, sits behind auth or preview protection, or serves the wrong content type. Our Triage engine fetches your og:image and flags it unless it answers 200 with an image/* content type — the same test the scrapers run.

30-second check:

curl -sI https://yourdomain.com/og.png | grep -i "^HTTP\|content-type"

Good output: HTTP/2 200 and content-type: image/png (or image/jpeg). Bad: a 404, a 3xx redirect, or content-type: text/html — the last one usually means a dynamically generated image route is returning an error page instead of a picture.

Fix: make the URL answer 200with an image content type. If it's behind a login wall or Vercel preview protection, move the image somewhere public. If it's a generated OG route, confirm it returns a real image in production, not just on your machine.

4. It's the wrong format or size

SVG, AVIF, GIF, and WebP are not reliably supported as og:image— Facebook and most platforms ignore them. Use PNG or JPEG. Images under 200×200 px are rejected, and files over about 8 MB get dropped. The size that works everywhere is 1200×630.

30-second check: open the image URL. A .svg, a tiny favicon-sized icon, or a multi-megabyte file will all be skipped.

Fix:serve a 1200×630 PNG or JPEG, kept under about 1 MB so it renders fast and clean.

5. The platform cached an old, imageless preview

You fixed the tag, but the link still previews blank. Facebook, LinkedIn, and others cache their first scrape of a URL and don't re-fetch on their own for a long time. You're looking at a stale preview, not a live bug.

30-second check: does the raw HTML now have a valid, absolute, loading og:image(causes 1–4 all pass) while the preview stays blank? Then it's cache.

Fix: force a re-scrape. Paste the URL into Facebook's Sharing Debugger and click Scrape Again; use LinkedIn's Post Inspector for LinkedIn. X and Slack usually refresh on their own within a day or two.

6. Your image is blocked to social crawlers

A robots.txt rule or a firewall that challenges unknown bots will also block facebookexternalhit, Twitterbot, and the rest. They're always logged out and identify with their own user-agents; if your protection layer turns them away, they see nothing to preview.

30-second check: fetch the image as a social crawler and read the status:

curl -sI -A "facebookexternalhit/1.1" https://yourdomain.com/og.png | grep -i "^HTTP"

A 200 is good. A 403, a challenge page, or a redirect to a login means the crawler is being blocked. Fix: allow the social preview crawlers through both robots.txt and your firewall. The same misconfiguration often blocks search and AI crawlers too — the Vercel triage guide covers that side.

The verdict: fix exactly one thing this week

Run the checks in order and stop at the first hit:

  1. curl … | grep og:image prints nothing → add the tag to your server-rendered HTML (cause 1). Nothing else matters until the tag is actually in the source.
  2. The URL isn't an absolute https:// address → make it absolute (cause 2). This fixes more blank previews than any other single change.
  3. The image URL doesn't answer 200with an image type, or it's an SVG / tiny / huge file → fix what it serves (causes 3 + 4).
  4. Tag present, absolute, loads, right format — but the preview is still blank → it's cached; re-scrape it (cause 5).
  5. Still nothing and a firewall or robots rule is in play → let the social crawlers through (cause 6).

How to confirm the fix worked

Re-run the check that caught your cause — the header trace, the grep. Then paste your URL into Facebook's Sharing Debugger: it shows exactly what the crawler sees and re-scrapes on demand. When the debugger shows your image, every other platform that reads Open Graph will too. If the debugger still shows no image after the tag checks out, you're on cause 5 or 6 — a stale cache or a blocked crawler.

Want the rest of the checks that decide whether you show up at all? The Checks Explained guides cover each one.

From experience: the relative-URL trap

The first time this bit me was on one of my own Next.js sites. The og:image looked perfect in the browser — open the page and the image was right there — but every link I shared in Slack and on X came up blank. The tag existed; it was just a relative path. Browsers resolve a relative og:image against the page without complaint, so nothing looked wrong until the moment it mattered. Setting metadataBase in the root layout, so Next.js emitted a full https:// URL, fixed every platform at once. Newer Next.js versions turn this into a build error instead of a silent blank preview, which is a mercy — but on an SPA or a hand-rolled head, nothing warns you. Check the raw HTML, not the browser.

FAQ

Does og:image have to be an absolute URL?

Yes. It must be a full https:// URL like https://yourdomain.com/og.png. Relative paths such as /og.png work in a browser but social scrapers reject them, and Facebook ignores them outright. In Next.js, set metadataBase so relative image paths are composed into absolute URLs automatically.

I fixed my og:image but the old preview still shows — why?

The platform cached its first scrape of your URL. Paste the link into Facebook's Sharing Debugger and click Scrape Again to force a fresh fetch; LinkedIn's Post Inspector does the same for LinkedIn. X and Slack usually refresh on their own within a day or two.

What size should my og:image be?

1200×630 pixels, saved as PNG or JPEG, kept under about 1 MB. Anything below 200×200 is rejected, files over roughly 8 MB get dropped, and SVG, AVIF, and WebP aren't reliably supported.

Why does the preview work on one platform but not another?

Each platform scrapes and caches independently, and some read different tags — X checks twitter:image before falling back to og:image, for instance. A blank preview on just one platform usually means that platform cached an older scrape (re-scrape it) or you're missing its specific card tag.

Not sure if your link previews are broken?

Get a free Triage Report: eight checks run from your URL alone — including whether your og:image actually loads for crawlers — each scored Critical / Monitor / Healthy, ending with the one thing to fix this week. It renders on your screen in about half a minute — no signup, no email required.

Request your free Triage Report →