Microsoft Teams is used by more than 320 million people daily. When someone pastes a URL into a Teams chat or channel, Teams fetches the page and renders an Adaptive Card preview — and like every other platform, it relies on Open Graph tags to build that card. If your OG tags are wrong, the preview is wrong, and your link gets ignored.
How Teams Fetches Link Previews
When a URL is pasted into Teams, the Teams bot service sends an HTTP GET request to the URL using the user-agent string "SkypeUriPreview". It reads the page HTML, extracts OG and Twitter Card meta tags, and assembles an Adaptive Card preview. The card appears inline below the message.
Teams does NOT execute JavaScript during this fetch. Your OG tags must be present in the raw server-rendered HTML — not injected by a client-side framework. If you are using a React SPA or Next.js with client-only rendering, Teams will see a blank shell and show no preview at all.
Which Tags Teams Reads
Teams reads the following meta tags in order of priority:
- —og:title — displayed as the card heading (truncated at ~75 characters)
- —og:description — displayed as the card body text (truncated at ~200 characters)
- —og:image — the preview image shown in the card
- —og:url — the canonical URL used for click-through
- —og:site_name — displayed as the source attribution below the title
- —twitter:title / twitter:description — used as fallback if OG equivalents are missing
Recommended Tag Set for Teams
<!-- Required for Teams link preview -->
<meta property="og:title" content="Your Page Title — Under 75 Characters" />
<meta property="og:description" content="A concise description of this page, ideally under 160 characters for Teams." />
<meta property="og:image" content="https://yourdomain.com/og-image.jpg" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:url" content="https://yourdomain.com/your-page" />
<meta property="og:type" content="website" />
<meta property="og:site_name" content="Your Brand" />Image Requirements for Teams
Teams enforces stricter image rules than most platforms:
- —Recommended size: 1200×630px at 1.91:1 aspect ratio
- —Minimum size: 200×200px — images smaller than this are not shown
- —Maximum file size: 1MB (Teams may silently drop images above this threshold)
- —Supported formats: JPG, PNG, GIF (first frame only), WEBP
- —Image must be served over HTTPS — HTTP images are blocked
- —Image URL must not redirect — Teams follows no more than one redirect
- —No authentication required — the Teams bot must be able to fetch the image without cookies or headers
Common Reasons Teams Shows No Preview
- —OG tags injected by JavaScript — Teams sees only the pre-JS HTML shell
- —og:image served over HTTP instead of HTTPS
- —og:image URL behind authentication or returning 403
- —og:image larger than 1MB
- —og:title missing or empty
- —Page returns a non-200 status code (301 redirect chains longer than 1 hop)
- —X-Frame-Options or Content-Security-Policy blocking the Teams fetcher
- —User-agent "SkypeUriPreview" blocked in robots.txt or server config
Teams vs. Other Platforms: Key Differences
Teams has a few behaviors that differ from Twitter, LinkedIn, and Discord:
- —Image size limit: 1MB is stricter than Twitter (5MB) and LinkedIn (5MB)
- —No animated GIFs: only the first frame is shown
- —No theme-color support: Teams ignores the theme-color meta tag Discord uses for embed color
- —Adaptive Card format: the preview is an Adaptive Card, not a simple image strip — layout is determined by Teams, not your tags
- —Cache duration: Teams caches previews for 24–72 hours; changes may not appear immediately
- —User-agent: "SkypeUriPreview" — some WAFs or bot-blockers incorrectly block this
Next.js and Teams: Server-Side Rendering Required
If you use Next.js App Router, your metadata is rendered server-side by default — which means Teams can read it without issues. But if you use client components that manipulate <head> dynamically, or if you are using a pure React SPA (Vite/CRA), Teams will not see those tags.
// Next.js App Router — metadata is server-rendered and readable by Teams
export const metadata: Metadata = {
title: 'Your Page Title',
description: 'Description under 160 characters.',
openGraph: {
title: 'Your Page Title',
description: 'Description for social platforms.',
url: 'https://yourdomain.com/page',
siteName: 'Your Brand',
images: [
{
url: 'https://yourdomain.com/og-image.jpg',
width: 1200,
height: 630,
alt: 'Preview image for Your Page Title',
},
],
type: 'website',
},
};How to Test Teams Link Previews
The most direct test is to paste your URL into a Teams chat. But this only works after you have deployed, and Teams caches results for up to 72 hours — making iteration slow. A faster workflow:
- 1.Use OGProof to validate your tags are present in static HTML and your image is accessible
- 2.Confirm og:image is served over HTTPS and is under 1MB
- 3.Paste the URL into a private Teams channel or 1:1 chat to see the live preview
- 4.If the preview is stale after an update, paste the URL with a cache-busting query string (?v=2) — Teams will re-fetch and update the cache
Debugging Teams Previews with curl
You can simulate the Teams fetcher by mimicking its user-agent in curl:
curl -s -A "SkypeUriPreview" https://yourdomain.com/page | grep -i 'og:title\|og:description\|og:image'If the tags appear in the curl output, Teams can read them. If they are missing, your tags are being injected client-side and Teams will not show a preview.
Unfurling in Teams vs. Messaging Extensions
Standard link unfurling (what happens when you paste a URL) uses OG tags. Teams also supports Messaging Extensions with link unfurling — a more advanced feature where a registered Teams app intercepts specific URL patterns and returns a custom Adaptive Card via a bot endpoint. This is different from OG tag rendering and requires app registration in the Teams Developer Portal. For most sites, OG tags are the right solution.
Checklist: Teams-Ready Open Graph Tags
- —og:title present and under 75 characters
- —og:description present and under 160 characters
- —og:image present and served over HTTPS
- —og:image between 200×200px and 1200×630px
- —og:image file size under 1MB
- —og:url matches canonical URL
- —og:site_name set to brand name
- —All OG tags in static server-rendered HTML (not JavaScript-injected)
- —SkypeUriPreview user-agent not blocked in robots.txt or firewall
- —Validated with OGProof to confirm tags are readable by the Teams bot