OG image not showing? Nine causes, in the order to check them
A broken preview is nearly always one of nine things. Work down the list: the first five cover most cases.
Check these in order: the og:image tag is in the HTML the server sends (not added by JavaScript), its URL is absolute https://, the image downloads without a login or bot block, it's a JPG or PNG under 1 MB at 1200 × 630, and you've added twitter:card = summary_large_image for X.
If all of that is right and the old preview still shows, it's the cache: re-scrape in Facebook's Sharing Debugger or LinkedIn's Post Inspector, and share the URL with ?v=2 on X, Slack and Discord.
First, see what the crawler sees
Link previews are built by bots, not browsers. When you paste a link, X, LinkedIn, Slack and the rest send a crawler that downloads your page's HTML once, reads the <meta> tags in the <head>, then downloads the image named in og:image. It doesn't run JavaScript, doesn't log in, and gives up quickly.
So the first step is to look at your page the way the bot does. Two quick ways:
- Paste the URL into the link preview checker. It reads the same tags, fetches the image, and shows the result on X, LinkedIn, Slack, Facebook and iMessage.
- From a terminal:
curl -s https://yourdomain.com/page | grep -i 'og:\|twitter:'. If the tags aren't in that output, no platform can see them.
The nine causes
1. The tags are added by JavaScript
The most common cause on modern sites. A React, Vue or Svelte app that sets meta tags in the browser (with a head manager, or by changing document.head) shows correct tags in your browser's inspector but sends an empty <head> to crawlers. Fix: render the tags on the server or at build time: Next.js metadata, Nuxt useHead with SSR, Astro, or prerendering. See the Next.js OG image guide.
2. The image URL is relative
<meta property="og:image" content="/og.png"> doesn't work. Crawlers need the full address: https://yourdomain.com/og.png. Also check it uses your real domain, not localhost or a preview deployment.
3. The image can't be downloaded
Open the image URL in a private window. Then check the things a private window doesn't show:
- Bot protection or a firewall (Cloudflare challenges, hosting "attack mode") blocking crawler user agents such as
facebookexternalhit,LinkedInBot,Twitterbot,SlackbotandDiscordbot. robots.txtdisallowing the folder the image is in.- Password-protected staging or preview deployments. The crawler gets a login page instead of an image.
- Hotlink protection that only serves images to your own domain.
4. The file is the wrong type
SVG doesn't work for link previews. WebP works on the big platforms but not everywhere, and AVIF support is patchy. Use JPG or PNG. Also make sure the server sends the right Content-Type (image/png, image/jpeg): an image served as text/html or application/octet-stream is often skipped.
5. The file is too big or too small
X's limit is 5 MB and Facebook's is 8 MB, but crawlers time out on slow downloads long before that; WhatsApp is known to skip heavy images. Keep it under 1 MB. Under 600 × 315, Facebook and others show a small thumbnail instead of a large card. Use 1200 × 630; the OG image size guide covers what each platform crops.
6. No twitter:card tag (X only)
X reads your Open Graph title and image, but the card type comes from twitter:card. Without <meta name="twitter:card" content="summary_large_image"> you may get a small square thumbnail or no image.
7. Tags in the wrong place or with the wrong attribute
Tags must be inside <head>, near the top: some crawlers stop reading after the first part of the page. Open Graph tags use property="og:..."; Twitter tags use name="twitter:...". Duplicate og:image tags (one from your theme, one from an SEO plugin) make platforms pick either, often the wrong one.
8. Redirects
A chain like http → https → www → /en/ sometimes loses crawlers, and a redirect to a cookie or consent page loses them always. Make the shared URL and the image URL answer 200 directly.
9. The platform cached an old version
Every platform stores what it fetched the first time someone shared the URL, including a broken result. Your fix can be live and the old preview still shows. Next section.
Refreshing each platform's cache
| Platform | How to refresh |
|---|---|
| Facebook, Messenger, Instagram links | Meta's Sharing Debugger → Scrape Again. Press it twice if the image still looks old. |
| Post Inspector. Inspecting the URL re-fetches it. | |
| X (Twitter) | No refresh tool since the Card Validator lost its preview in 2022. Paste the URL into a new draft to see the current card, or share it with a query string (?v=2) so X treats it as a new URL. |
| Slack, Discord, Telegram | No public tool. A new query string works; in Telegram, the @WebpageBot bot refreshes previews. |
| WhatsApp, iMessage | Previews are fetched when the link is pasted, then kept with the message. Send it again (with ?v=2 if it still shows the old one). |
One thing no tool fixes: previews in posts that are already published usually keep the old image. Refreshing only changes new shares.
Platform quirks
- X shows only the image and your domain on large cards (no title since late 2023), at about 2:1. Put the message on the image.
- LinkedIn is the strictest about image size and caching; if Post Inspector shows the image but the composer doesn't, wait a minute and paste again.
- WhatsApp is the most sensitive to file size. If everything else works and WhatsApp doesn't, make the image smaller.
- iMessage fetches the preview from the sender's phone, so it can work even when your firewall blocks data-center crawlers.
- Slack puts
og:site_nameabove the title and shows the image small, so text on the image needs to be large to be read there.
Framework-specific traps
- Next.js: a missing
metadataBasemakes image URLs resolve to the wrong host. See the Next.js guide. - Create React App, Vite SPA: every route returns the same
index.html, so every page has the same (or no) preview. Add prerendering or move to a framework with SSR. - WordPress: two SEO plugins, or a theme and a plugin, both printing
og:image. Keep one. - Webflow, Framer: each page has its own "Open Graph image" setting that overrides the site-wide one. A blank page-level field falls back to the site image, which may not be what you want.
Need a proper OG image?
Launchpack makes a 1200 × 630 OG image from your name, tagline and a screenshot, plus the exact tags to paste. Free for the OG image.
Questions
Why is my OG image not showing on LinkedIn?
Usually a relative image URL, an image LinkedIn's crawler can't download, or an old cached preview. Make the og:image URL absolute https, keep the image 1200 × 627 to 1200 × 630 and under 5 MB, then run the URL through LinkedIn's Post Inspector to re-fetch it.
Why does my link show no image on X (Twitter)?
Check for <meta name="twitter:card" content="summary_large_image">, an absolute og:image URL, a JPG or PNG under 5 MB, and that your server doesn't block the Twitterbot crawler. Then paste the URL into a new draft to see the current card.
Why does Facebook show an old image?
Facebook caches previews. Open the Sharing Debugger, enter the URL and press Scrape Again. Posts that were already published may keep the old image.
Why is my WhatsApp link preview not showing?
WhatsApp is sensitive to image size and slow servers. Use a small JPG (a few hundred KB) at 1200 × 630 with an absolute https URL, make sure the page answers without redirects to a consent page, and send the link again.
My tags look right in the browser. Why don't crawlers see them?
Your browser runs JavaScript; crawlers don't. If a script adds the tags after the page loads, they're missing from the HTML the server sends. Check with curl or a link preview checker, and render the tags on the server.