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:
| Platform | Minimum | Sweet spot | Aspect |
|---|---|---|---|
Twitter (summary_large_image) | 300×157 | 1200×628 | 1.91:1 |
| 200×200 | 1200×630 | 1.91:1 | |
| 400×400 | 1200×627 | 1.91:1 | |
| Slack | 200×200 | 1200×630 | any |
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
- Facebook / LinkedIn / Threads: developers.facebook.com/tools/debug → enter URL → “Scrape Again”
- Twitter: cards-dev.twitter.com/validator (Twitter dev access required)
- LinkedIn: linkedin.com/post-inspector → enter URL → “Inspect”
- Slack: no public tool; the cache lasts ~24h. Share the URL in a private channel to verify.
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:widthandog: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).
Related
Tags: #Troubleshooting #SEO #Debug #OG image