How to Check a Website Thumbnail Before Publishing
Verify the title, description, image, crop, and cache of a link preview before you publish it.
Direct answer
Check a website thumbnail in three places before publishing: the public page, the destination platform’s preview composer or inspector, and the page’s server-delivered Open Graph metadata. Confirm that the preview uses the intended image, title, description, and URL; inspect the rendered crop; then refresh the platform cache if the result is stale.
For LinkedIn, verify og:title, og:image, og:description, and og:url. LinkedIn recommends an image of at least 1200 × 627 pixels, a 1.91:1 aspect ratio, and a maximum file size of 5 MB. Images under 401 pixels wide may appear as a thumbnail. These are LinkedIn requirements, not universal rules for every network. LinkedIn’s sharing guidance is the authority for its current limits.
1. Confirm the URL you will publish
- Open the public URL in a private browser window.
- Confirm that it is the intended canonical page, not a staging URL, redirect, login page, or tracking-only URL.
- Check the visible page title and description so you can compare them with the share card later.
- If the page redirects, use the final public URL when checking the preview.
2. Check the preview in the destination platform
Paste the URL into the platform’s share composer or official inspector. LinkedIn says to allow a few seconds for the preview image to appear. Inspect all three visible fields:
- Image: Is it the intended Open Graph image? Is the important content inside the crop?
- Title: Does it match the intended headline?
- Description: Is it accurate and readable at card size?
For LinkedIn, use Post Inspector when you need to refresh a URL preview. Refreshing affects future posts; it does not change a preview already attached to a published post. LinkedIn also says updated information can take up to 48 hours to appear.
3. Inspect the metadata delivered by the server
A visible page can look correct while its share metadata is wrong. Fetch the HTML that a crawler receives and inspect the Open Graph tags.
cURL
curl -L --max-time 30 'https://example.com/page' \
| grep -iE "<meta[^>]+(property|name)=['\"]og:(title|image|description|url)['\"]"
Also inspect the HTTP response for redirects and access errors:
curl -I -L --max-time 30 'https://example.com/page'
Python: extract Open Graph tags
from html.parser import HTMLParser
from urllib.request import Request, urlopen
class OpenGraphParser(HTMLParser):
def __init__(self):
super().__init__()
self.values = {}
def handle_starttag(self, tag, attrs):
if tag.lower() != 'meta':
return
data = dict(attrs)
key = data.get('property') or data.get('name')
if key and key.lower().startswith('og:'):
self.values[key.lower()] = data.get('content', '')
url = 'https://example.com/page'
request = Request(url, headers={'User-Agent': 'thumbnail-check/1.0'})
with urlopen(request, timeout=30) as response:
html = response.read().decode('utf-8', errors='replace')
parser = OpenGraphParser()
parser.feed(html)
for key in ('og:title', 'og:image', 'og:description', 'og:url'):
print(f'{key}: {parser.values.get(key, "MISSING")}')
Node.js: extract Open Graph tags
const url = 'https://example.com/page';
const res = await fetch(url, {
headers: { 'user-agent': 'thumbnail-check/1.0' }
});
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
const html = await res.text();
const wanted = ['title', 'image', 'description', 'url'];
for (const name of wanted) {
const pattern = new RegExp(
`<meta[^>]+property=["']og:${name}["'][^>]+content=["']([^"']*)["'][^>]*>`,
'i'
);
const match = html.match(pattern);
console.log(`og:${name}: ${match ? match[1] : 'MISSING'}`);
}
Prefer an HTML parser in production if your templates can change attribute order. The examples above are small inspection scripts, not validators for every malformed document.
4. Validate the image itself
Resolve the og:image URL and check that it is publicly retrievable. A correct tag is not enough if the image is blocked, protected, or stored behind authentication. LinkedIn specifically lists blocked retrieval and protected directories as reasons an otherwise valid image may not appear.
curl -I -L --max-time 30 'https://example.com/images/share-card.jpg'
Record these values:
| Check | What to verify |
|---|---|
| HTTP status | The image responds successfully without a login or private network. |
| Content type | The response identifies an image format supported by the destination. |
| Dimensions | For LinkedIn, use at least 1200 × 627 pixels and a 1.91:1 ratio. |
| File size | For LinkedIn, keep the file at or below 5 MB. |
| Composition | Keep faces, product details, and other important content away from edges that may be cropped. |
5. Render the card at the expected crop
The source image can meet the dimensions and still look wrong in the card. Create a local crop using the destination platform’s documented frame, then inspect it at the size readers will see.
Playwright example
npm install playwright
npx playwright install chromium
import { chromium } from 'playwright';
const imageUrl = 'https://example.com/images/share-card.jpg';
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1200, height: 627 } });
await page.setContent(`<!doctype html>
<style>html,body{margin:0;width:100%;height:100%;overflow:hidden}img{width:100%;height:100%;object-fit:cover}</style>
<img src="${imageUrl}">`);
await page.screenshot({ path: 'linkedin-crop.png' });
await browser.close();
This checks the image crop itself. The final platform card can apply additional layout, so always perform one check in the destination composer as well.
6. Fix stale previews
- Correct the Open Graph tags or replace the image at its URL.
- Make sure the new image URL is publicly accessible and returns the intended content.
- Run the URL through LinkedIn Post Inspector to request a fresh fetch.
- Wait for the inspector result, then check a new draft post.
- Allow up to 48 hours if updated information has not propagated.
Existing published posts keep their previous preview. A cache refresh helps future posts only.
Common problems and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| No thumbnail | og:image is missing, inaccessible, blocked, or in a protected location. |
Add an absolute public image URL, check it with curl -I -L, and remove access restrictions. |
| Wrong image | The page has multiple image tags, an old cached value, or a template fallback. | Inspect the delivered HTML, make the intended og:image explicit, then refresh the platform inspector. |
| Wrong title or description | Open Graph values differ from the visible page or are generated only in client-side JavaScript. | Serve the desired values in the initial HTML response and compare them with the preview. |
| Image appears as a small thumbnail | LinkedIn may treat images under 401 pixels wide as thumbnails. | Use an image at least 1200 pixels wide for the LinkedIn card. |
| Correct dimensions but no image | The crawler cannot retrieve the image, or the file is protected. | Test the image without cookies or authentication and check robots, firewall, hotlink, and CDN rules. |
| Old image after editing | The destination has a cached preview. | Use Post Inspector, then create a new draft and allow time for propagation. |
| Preview never finishes | The page or image is slow, redirects repeatedly, or returns an error to crawlers. | Check redirect chains, response times, status codes, and server logs for crawler requests. |
| Image looks cropped badly | Important content sits near the edges or the source ratio differs from the card ratio. | Recompose the source for the platform’s frame and inspect a rendered crop before publishing. |
Platform checks beyond LinkedIn
Use each destination’s own inspector or composer because preview extraction and image rules vary. Compare tools using five questions:
- Does it fetch the public URL like a crawler?
- Which platform cards does it simulate?
- Does it show extracted metadata and image dimensions?
- Can it refresh the destination’s cached version?
- What account, cost, and data handling does it require?
Do not treat LinkedIn’s 1200 × 627 recommendation as a universal requirement. Keep a platform-specific checklist for every network where you publish.
Performance, reliability, and cost notes
- Performance: Check the final URL and image with direct HTTP requests first. This isolates metadata and availability problems before you spend time in a browser.
- Reliability: Test without logged-in cookies, use absolute HTTPS image URLs, and verify redirects and status codes from a public network.
- Cache behavior: A corrected page can continue showing old data until the platform refreshes it. Inspect the refreshed result before publishing.
- Cost: Platform inspectors are useful for their own network. A screenshot service can automate visual checks across many URLs; compare its pricing and data handling with your publishing volume.
Or skip the browser setup
ScreenshotNeo can capture the final page or a preview test with one API request. Its clean-shot pipeline accepts consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. The MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
See the ScreenshotNeo API documentation for all options.
cURL
curl -G 'https://api.screenshotneo.com/v1/shot' \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com/page \
-o preview.webp
Python
import requests
r = requests.get('https://api.screenshotneo.com/v1/shot', params={'access_key': 'YOUR_API_KEY', 'url': 'https://example.com/page'}, timeout=90)
open('preview.webp', 'wb').write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com/page' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
const data = Buffer.from(await res.arrayBuffer());
require('node:fs').writeFileSync('preview.webp', data);
ScreenshotNeo includes full-page capture with lazy images loaded, element capture by CSS selector, custom CSS and JavaScript, waits for selectors or network idle, request blocking, custom headers and cookies, user-agent, timezone and geolocation, resizing, caching with a chosen TTL, signed links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API, and an OpenAPI specification. It accepts parameter names used by other screenshot APIs, which can simplify migration.
The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; yearly billing gives two months free. Create a free ScreenshotNeo account and check a thumbnail before publishing.
FAQ
Does checking the visible page prove the thumbnail is correct?
No. The destination may use Open Graph, oEmbed, cached data, and its own crop logic. Inspect the server-delivered metadata and the destination preview.
Will changing an image update an already published post?
No. LinkedIn’s inspector refreshes previews for future posts; an existing published post keeps its previous preview.
How long should I wait after fixing metadata?
Refresh the URL with the destination inspector, then allow up to 48 hours if the updated information still does not appear.
What is the safest image URL format?
Use an absolute HTTPS URL that responds publicly without cookies, authentication, or a protected directory.
Should I use one image size for every network?
No. Follow each platform’s current guidance and inspect the rendered card for that network.


