How Link Previews Work — The URL Unfurl Process Explained
When you paste a URL into Slack, Discord, Twitter/X, LinkedIn, Facebook, or iMessage, a preview card appears almost instantly — headline, summary, image, site name. That card is the visible output of URL unfurling, the same three-step process every modern platform runs under the hood.
This guide walks through the complete link preview pipeline (crawl, parse, render), which metadata tags power it, how to check URL metadata the way a platform crawler would, why caching causes previews to go stale, why JavaScript-rendered pages break URL unfurl so often, and the best practices that keep your link previews from breaking in the first place.
→ See how your URL unfurls on every platform
What Is URL Unfurling?
URL unfurling is the umbrella term for the process that turns a bare URL into a rich preview card. Every social network, chat app, and messaging platform runs it. The words "unfurling," "link unfurling," and "URL unfurl" are used interchangeably — and so is "embed" on Discord, "link preview" on Slack, and "link thumbnail" on iMessage.
The output is always the same: a tile that shows what's at the link before anyone clicks. The mechanics are also the same — fetch HTML, read meta tags, render a card, cache the result.
The Three-Step URL Unfurl Process
Every link preview is generated through the same fundamental pipeline.
1. Crawl — the platform fetches your page
When a URL is shared, the platform sends an HTTP request to that URL using its crawler bot. This happens server-side — not in a browser. The crawler requests the raw HTML of the page.
Important: most platform crawlers do not execute JavaScript. They retrieve only the initial HTML response from the server. This is why pages that rely on client-side rendering (React SPAs, Vue apps without SSR) often produce empty or broken URL unfurls.
Each platform uses its own crawler identity:
| Platform | Crawler user-agent |
|---|---|
facebookexternalhit |
|
| Twitter / X | Twitterbot |
LinkedInBot |
|
| Slack | Slackbot-LinkExpanding |
| Discord | Discordbot/2.0 |
WhatsApp |
|
| Telegram | TelegramBot |
| iMessage | facebookexternalhit (Apple reuses Meta's UA) |
| Microsoft Teams | Mozilla/5.0 (compatible; MSIE...) variants |
If your WAF blocks any of these user-agents, the URL unfurl for that platform silently fails.
2. Parse — metadata is extracted from the HTML
Once the HTML is retrieved, the platform scans the <head> section for metadata tags. It reads these in a specific priority order:
- Open Graph tags (
<meta property="og:*">) — the primary source for most platforms - Twitter Card tags (
<meta name="twitter:*">) — used by X, also read by Discord - HTML
<title>and<meta name="description">— fallback for all platforms - Favicon — used for small icon previews
The platform stores the extracted title, description, image URL, site name, canonical URL, and other values.
3. Render — the preview card is built and cached
Using the extracted metadata, the platform renders a visual preview card according to its own layout rules — applying title length limits, image crop dimensions, and the card format specific to that platform.
The rendered result is then cached. Future shares of the same URL serve the cached preview without re-fetching the page — which is why outdated URL unfurls persist even after you update your metadata.
What Metadata Powers Link Previews
Different platforms rely on different metadata standards:
| Standard | Tags | Used by |
|---|---|---|
| Open Graph | og:title, og:description, og:image, og:url, og:type |
Facebook, LinkedIn, Slack, Discord, WhatsApp, iMessage, Teams, Telegram |
| Twitter Cards | twitter:card, twitter:title, twitter:description, twitter:image |
Twitter / X (also read by Discord) |
| HTML meta | <title>, <meta name="description"> |
All platforms as fallback |
| Favicon | <link rel="icon"> |
Compact preview icons |
Most platforms prefer Open Graph if it's present and fall back to HTML meta tags if it isn't. This is why adding Open Graph tags is the single most impactful metadata improvement for link previews.
How to Check URL Metadata
To see what a platform crawler actually reads, you need a tool that fetches pages the same way they do — server-side, no JavaScript, platform-style user-agent. Three common methods:
1. Use TryUnfurl (fastest)
Paste the URL into TryUnfurl. It fetches the page live, parses Open Graph and Twitter Card tags, and renders the preview card every major platform will render. It also lists every detected metadata value side-by-side with the visual preview — so you can see exactly what the URL unfurl will look like across Facebook, LinkedIn, X, Slack, Discord, and iMessage at once.
2. View page source
Right-click the page → View Page Source (Ctrl+U / Cmd+Option+U) and search for og:. Every Open Graph tag appears exactly as the server rendered it. If a tag is visible in browser DevTools but missing in View Source, it's JavaScript-injected and platform crawlers won't see it.
3. cURL from the terminal
For a quick check-URL-metadata recipe that mirrors a platform crawler:
curl -sL -A "facebookexternalhit/1.1" https://example.com/your-page \
| grep -iE '<meta (property|name)="(og|twitter)'
That prints every og:* and twitter:* tag in the raw HTML — exactly what a crawler would see.
Platform-Specific Preview Generation
Each platform has quirks worth knowing when you're debugging a URL unfurl.
How Slack generates previews
Slackbot fetches once, caches per-URL per-workspace, and doesn't run JavaScript. Open Graph first, then Twitter Card, then HTML fallback. Delete-and-re-share is the simplest way to force a refresh; see our Slack unfurl guide for the full playbook.
How Discord generates embeds
Discordbot reads Open Graph and Twitter Cards, caches per URL, and respects angle-bracket suppression (<https://example.com> means "no embed, please"). The fastest refresh is a query-string cache-buster (?v=2). See the Discord preview fix guide.
How Facebook generates previews
Facebook's facebookexternalhit follows the Open Graph protocol Facebook invented. Previews are baked into a post at share time — once live, the URL unfurl for that post is frozen. New shares pick up the new tags after a Sharing Debugger re-scrape. Details in the Facebook link preview guide.
How LinkedIn generates previews
LinkedIn reads Open Graph only — Twitter Cards are ignored. Minimum image is 1200×627 px; anything smaller downgrades to a tiny thumbnail. Use the Post Inspector to clear LinkedIn's cache. See the LinkedIn preview guide.
How X/Twitter generates card previews
Twitter Card tags take priority; Open Graph is the fallback. twitter:card must be explicitly set to summary_large_image for the big card layout. The Card Validator re-scrapes each time you run it.
Why Caching Affects Previews
After a platform fetches and parses your page, it caches the preview result. Cache durations vary:
| Platform | Typical cache duration |
|---|---|
| 24 hours to several days | |
| Hours to days | |
| Twitter / X | Hours |
| Slack | A few hours |
| Discord | A few hours to ~24 hours |
| iMessage | Per-message cache, no expiry |
This means updating your metadata doesn't immediately change existing URL unfurls. You need to force a cache refresh using platform-specific tools or workarounds — see how to refresh a link preview.
Why JavaScript-Rendered Pages Break Previews
This is the most common technical cause of missing link previews.
Modern web apps often use JavaScript frameworks that build the page in the browser after the initial HTML loads. The initial HTML response contains almost nothing — just a <script> tag. Platform crawlers receive this empty shell and find no metadata.
The fix: ensure your meta tags are present in the initial server-rendered HTML, not injected by JavaScript. Solutions include:
- Server-side rendering (SSR) — e.g. Next.js, Nuxt.js, SvelteKit, Remix
- Static site generation (SSG) — e.g. Gatsby, Astro, Hugo, Jekyll, Eleventy
- A prerendering service that generates static HTML snapshots for crawlers
If you can see your Open Graph tags in browser DevTools but not in View Source / cURL, your tags are JS-injected and crawlers can't see them.
Preview Optimization Best Practices
- Set every core OG tag on every public page —
og:title,og:description,og:image,og:url,og:type. - Use a 1200×630 px
og:image— universal safe size across all major platforms. - Keep
og:descriptionunder 155 characters — avoids truncation across Facebook, LinkedIn, and Slack. - Serve the OG image from a CDN with long cache headers — crawlers re-fetch often.
- Server-render tags — never inject via client-side JavaScript.
- Test before every share — see how to test URL unfurl.
- Audit monthly — run evergreen pages through the bulk URL unfurl checker to catch silent regressions.
- Automate in CI/CD — use the TryUnfurl API to assert OG tags on every deploy.
How to Verify Your Link Preview
Since platform crawlers work differently from a regular browser, the best way to see what they actually read is to use a tool that fetches pages the same way they do.
TryUnfurl fetches any URL server-side (no JavaScript execution), extracts all metadata, and shows you rendered preview cards for every major platform — in seconds.
→ See how your link previews look now · → Bulk-check up to 100 URLs
Frequently Asked Questions
How does URL unfurling actually work?
Every platform runs the same three-step pipeline: fetch the HTML with a bot user-agent, parse Open Graph and Twitter Card tags from the <head>, and render a preview card using the extracted title/description/image. The result is cached per URL.
Why does my URL unfurl show different previews on different platforms?
Each platform has its own priority order. Twitter/X prefers Twitter Card tags, LinkedIn ignores them entirely, Facebook uses only Open Graph. Make your OG and Twitter Card tags consistent and the previews will converge.
How do I check URL metadata without sharing the link?
Paste the URL into TryUnfurl — it shows every Open Graph and Twitter Card tag your page exposes plus a rendered preview for every major platform. No login. No cache.
Why does the URL unfurl show nothing for my site?
Most common cause: your meta tags are injected client-side by a JavaScript framework. Platform crawlers don't run JS, so they see an empty HTML shell. Switch to SSR, SSG, or pre-rendering.
How long does a platform cache a URL unfurl?
Anywhere from a few hours (Slack, Twitter/X) to several days (Facebook, LinkedIn). See how to refresh a link preview for per-platform cache-busting instructions.