OG Image Not Showing When Shared

Sharing a page on Twitter / LinkedIn / Slack shows no preview image.

Someone pastes your URL into Slack and the link unfurls to just the title — no image. Or it shows the image once, then never again. Or Twitter shows it but LinkedIn doesn’t. The Open Graph protocol is a 2010 standard; modern social platforms add their own quirks on top (size limits, scrape rate, cache duration). The fix is usually one of: missing og:image tag, relative or HTTP URL, image dimensions wrong, or platform cached a previous error.

This guide walks through the actual debug path platform-by-platform.

Common causes

Ordered by hit rate, highest first.

1. og:image URL is relative or HTTP

Open Graph requires an absolute HTTPS URL. Most platforms reject <meta property="og:image" content="/images/cover.png"> outright.

How to spot it:

curl -s "https://yoursite.com/article" | grep -oP '<meta property="og:image" content="\K[^"]+'

If the URL doesn’t start with https://, that’s it.

2. Image is too small or wrong aspect ratio

Different platforms have different rules:

PlatformMinimumSweet spotAspect
Twitter (summary_large_image)300×1571200×6281.91:1
Facebook200×2001200×6301.91:1
LinkedIn400×4001200×6271.91:1
Slack200×2001200×630any

The 1200×630 size (1.91:1 ratio) works on all of them.

How to spot it: Download the image and check dimensions. If < 600px wide, Twitter falls back to summary (no image), even though you specified summary_large_image.

3. Platform cached an old version (or a 404)

Facebook, LinkedIn, and Twitter aggressively cache the OG scrape result. If you shipped the page before fixing the image, the platform has a “no image” cache entry that lasts days to weeks.

How to spot it: Test in Facebook’s Sharing Debugger. If it shows the old version, the cache is stale.

4. Image returns non-200

The og:image URL itself returns 404, 403 (auth required), or 500. Browsers and scrapers can’t fetch it.

How to spot it:

curl -sI "https://yoursite.com/og-image.png" | head -1

Should be HTTP/2 200. Any other code = broken image.

5. Image is dynamically generated and slow/timing out

If you use Vercel OG / @vercel/og to generate images on the fly, first request can take 3-5s. Some platform scrapers time out at 2s and treat it as missing.

How to spot it: First request curl -w "%{time_total}" https://yoursite.com/api/og?title=test. If > 2 seconds consistently, scrapers will time out.

6. Twitter Card meta missing or wrong type

For Twitter to show a large image, you need both og:image AND <meta name="twitter:card" content="summary_large_image">. Without it, Twitter defaults to small-card mode.

How to spot it: curl -s "https://yoursite.com/article" | grep twitter:card. Should show summary_large_image if you want a large preview.

7. CORS / CSP issues for image fetch

If the image is on a different domain and CORS or CSP blocks third-party scrape, some platforms fail.

How to spot it: Use Vercel/Netlify origin for the image, not a third-party CDN with strict CORS.

Shortest path to fix

Step 1: View source and verify the tags

curl -s "https://yoursite.com/article" | grep -E 'og:|twitter:'

Should include at minimum:

<meta property="og:title" content="..." />
<meta property="og:description" content="..." />
<meta property="og:image" content="https://yoursite.com/og.png" />
<meta property="og:url" content="https://yoursite.com/article" />
<meta name="twitter:card" content="summary_large_image" />

og:image must be absolute HTTPS.

Step 2: Verify the image URL returns 200

curl -sI "$(curl -s 'https://yoursite.com/article' | grep -oP 'og:image" content="\K[^"]+')"

Should be 200 with Content-Type: image/png (or jpeg).

Step 3: Force-refresh each platform’s cache

Step 4: Set explicit dimensions

Add og:image:width and og:image:height so platforms don’t need to fetch the image just to check size:

<meta property="og:image" content="https://yoursite.com/og.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="Description of the image" />

Step 5: For dynamic OG images, cache aggressively

If using Vercel OG:

export const config = { runtime: 'edge' };

export default async function handler(req) {
  // ...generate image...
  return new ImageResponse(content, {
    width: 1200,
    height: 630,
    headers: {
      'cache-control': 'public, max-age=31536000, immutable',
    },
  });
}

A 1-year cache means scrapers always hit fast.

Step 6: Test the URL on each platform

After fix, share the URL on each platform in a real (private) post. Don’t trust only the validator — sometimes platforms behave differently in real use.

Prevention

  • Always use absolute HTTPS URLs in OG tags.
  • Always include og:image:width and og:image:height.
  • Default to 1200×630 image dimensions.
  • After any template change, test OG on at least 2 platforms (Facebook Debugger + LinkedIn Inspector).
  • Cache dynamic OG images aggressively (max-age=31536000 if content is stable, or hash-based caching).

Tags: #Troubleshooting #SEO #Debug #OG image