# og:image not showing? How to debug it and bust each cache

> Why a link preview has no image or an old one: eight usual causes, how to see what the crawler sees, and how to refresh Facebook, LinkedIn, X and Slack.

Published 2026-10-24 · https://shareglint.com/en/guides/og-image-not-showing

When a shared link shows no image — or yesterday's image — the cause is almost always one of eight things, and the platform's own debugger will tell you which in a minute. The second half of the problem is caching: every platform keeps its own copy of your preview, and each one is refreshed differently. This guide covers both, in the order you should check them.

## The eight usual causes

1. **Relative URL.** `content="/og/post.png"` works in a browser and fails in every crawler. `og:image` must be an absolute `https://` URL.
2. **The crawler cannot fetch the image.** A login, a firewall, bot protection (Cloudflare's bot modes, security plugins), hotlink protection or a `robots.txt` rule blocks `facebookexternalhit`, `LinkedInBot` or `Twitterbot`. Note that Slack [does not honour robots.txt](https://api.slack.com/robots) for unfurls, so "works in Slack, not on LinkedIn" often points here.
3. **Wrong size or file.** Under 200×200 Facebook ignores the image; over 8 MB it rejects it ([Meta](https://developers.facebook.com/docs/sharing/webmasters/images)). LinkedIn wants at least 1200×627, at most 5 MB, and lists only JPG, PNG and GIF ([LinkedIn](https://www.linkedin.com/help/linkedin/answer/a521928)) — a WebP image can fail there while working elsewhere.
4. **The tags are added by JavaScript.** Preview crawlers read the server's HTML; a React or Vue app that sets meta tags after load shows them nothing. Render the tags on the server.
5. **Two `og:image` tags.** A theme and an SEO plugin both print one; the crawler takes the first, which is often the wrong one.
6. **Your own cache serves old HTML.** A page cache or CDN still returns the page from before you added the tag.
7. **The image URL redirects badly or returns the wrong type.** Long redirect chains, a `200` with an HTML error page, or `Content-Type: text/plain` on a PNG.
8. **The platform's cache.** Everything is fixed, but the platform shows what it fetched last week.

## Step 1: see what the crawler sees

Fetch the page the way a crawler does and look at the tags:

```bash
curl -sL -A "facebookexternalhit/1.1" https://example.com/blog/post \
  | grep -Eio '<meta[^>]+(og:|twitter:)[^>]+>'
```

If the output has no `og:image`, the problem is in your HTML (causes 1, 4, 5, 6). If it does, check the image itself:

```bash
curl -sIL -A "facebookexternalhit/1.1" https://example.com/og/post.png
```

You want a final `200`, `Content-Type: image/png` or `image/jpeg`, and a `Content-Length` well under 5 MB. A `403` here is cause 2; a `text/html` content type is cause 7.

Our free [OG Checker](https://shareglint.com/en/tools/og-checker) fetches the page the way Facebook's crawler does, lists what is missing and previews the card on X, LinkedIn, Facebook, Slack and Discord; it can also scan a sitemap for pages without tags.

## Step 2: ask the platform

| Platform | Tool | Refreshes the cache? |
|---|---|---|
| Facebook, Messenger | [Sharing Debugger](https://developers.facebook.com/tools/debug/) | Yes — *Scrape Again* |
| LinkedIn | [Post Inspector](https://www.linkedin.com/post-inspector/) | Yes, for new posts ([LinkedIn](https://www.linkedin.com/help/linkedin/answer/a6233775)) |
| X | Paste the link into the post composer (no need to post) | No — re-crawled about weekly; change the URL |
| Slack | None needed | Expires after about 30 minutes ([Slack](https://api.slack.com/robots)) |
| Discord | None | Expires after about 30 minutes ([Discord](https://docs.discord.com/developers/link-previews/overview)); or add `?v=2` |
| Telegram | [@WebpageBot](https://t.me/WebpageBot) | Yes, for new messages |
| WhatsApp | None | No — change the URL |

The Facebook debugger is the most useful diagnostic even if you do not care about Facebook: it shows the exact image it chose, its dimensions, the HTTP response code it got from your server, and a warning when the image could not be downloaded or is too small. Without a manual scrape Facebook refreshes a URL's data about every 30 days; the Graph API can trigger a re-scrape (`POST /?id={url}&scrape=true`), which helps when you publish many pages at once ([Meta](https://developers.facebook.com/documentation/sharing/webmasters/getting-started/change-link.md)). Existing shares keep the data they were created with.

## Step 3: bust the cache properly

Platforms cache two things: the **page** (its tags) and the **image** (the file behind the URL). Refreshing the page in a debugger does not always refresh the image — Meta's own advice is to "use a new URL for the new image" ([Meta](https://developers.facebook.com/docs/sharing/webmasters/images)).

So when you change an image, change its URL:

```html
<!-- before -->
<meta property="og:image" content="https://example.com/og/post.png">
<!-- after: a new file name or a version parameter -->
<meta property="og:image" content="https://example.com/og/post-v2.png">
```

Generated images get this for free if the URL depends on the content: a hash of the title in the file name, or a signed URL whose query string contains the title. Change the title and the URL changes with it. Shareglint's signed `/i/` URLs and auto-OG `/u/` URLs work this way — and an identical image is served from cache without a new render.

For platforms with no refresh tool (X, Discord, WhatsApp), the page URL is the cache key too. X re-crawls cards roughly every seven days and suggests sharing a changed URL to see a fix sooner ([archived X docs](https://web.archive.org/web/2024/https://developer.x.com/en/docs/twitter-for-websites/cards/guides/troubleshooting-cards)). New posts pick up a new preview once the cached one expires; to force it now, share a URL the platform has not seen, such as `https://example.com/blog/post?v=2`. Do not count on previews inside messages and posts that were already sent changing; on most platforms they keep what was fetched at the time.

## Framework-specific traps

- **Next.js:** since v15.2 `generateMetadata` can stream its tags after the page body, but Next.js keeps them in `<head>` for "HTML-limited bots" such as `facebookexternalhit`, detected by user agent ([Next.js docs](https://nextjs.org/docs/app/api-reference/functions/generate-metadata#streaming-metadata)). If you serve crawlers through a custom proxy or rewrite the user agent, check that they still get blocking metadata.
- **Single-page apps (Vite, CRA, Vue CLI):** prerender the routes you want shared, or add server-side rendering for meta tags; client-side helmet libraries do not help crawlers.
- **WordPress:** purge the page cache after changing SEO plugin settings; see [automatic OG images in WordPress](https://shareglint.com/en/guides/wordpress-og-images-without-code).
- **Static sites:** a relative image path in front matter is the classic bug; see [OG images for Hugo, Jekyll and Astro](https://shareglint.com/en/guides/og-images-static-sites-hugo-jekyll-astro).

## When the image is generated on request

If `og:image` points at an image that is rendered when first requested (a signed URL, `next/og`, your own Puppeteer endpoint), the first crawler visit pays for the render. Crawlers have short timeouts; a cold headless Chrome that needs five seconds can make the first share imageless, and the platform caches that result. Two fixes:

- **Warm it:** after publishing, request the image once yourself (or paste the URL into the Facebook debugger) before anyone shares it.
- **Render ahead of time:** generate the image when the post is saved and store the URL, as shown in the [Laravel](https://shareglint.com/en/guides/dynamic-og-images-laravel), [Rails](https://shareglint.com/en/guides/dynamic-og-images-rails) and [Django](https://shareglint.com/en/guides/dynamic-og-images-django) guides.

## A 60-second checklist

- [ ] `og:image` is absolute, `https://`, and appears once in the server HTML.
- [ ] The image returns `200`, an image content type, 1200×630, under 5 MB, JPEG or PNG.
- [ ] Crawlers are not blocked by a login, firewall, bot protection or hotlink rule.
- [ ] `og:image:width`, `og:image:height` and `twitter:card` are present.
- [ ] After a change: new image URL, page cache purged, Facebook *Scrape Again*, LinkedIn Post Inspector.

## FAQ

### Why is my og:image not showing on Facebook?

Usually one of: the image URL is relative, the image is smaller than 200×200 or larger than 8 MB, the crawler is blocked by a firewall or login, or Facebook cached an older version of the page. Paste the URL into the Sharing Debugger: it lists the image it found and any warnings, and Scrape Again refreshes the cache.

### How do I force LinkedIn to refresh a link preview?

Inspect the URL in LinkedIn's Post Inspector, which fetches the page again; new posts then use the refreshed preview. Posts that were already published keep the old one.

### How do I refresh a Telegram or WhatsApp link preview?

Telegram has an official bot, @WebpageBot: send it the URL and it updates the cached preview for new messages. WhatsApp has no refresh tool; change the image URL (for example add ?v=2) and, if needed, the page URL you share.

### Do social media crawlers run JavaScript?

Link-preview crawlers such as facebookexternalhit, LinkedInBot, Twitterbot and Slackbot read the HTML the server returns and do not wait for client-side JavaScript. Meta tags added by a single-page app after load are invisible to them.
