Skip to main content
A link preview or embed is what shows up in Discord when a link to your website is pasted into a chat. If you’ve ever seen a card pop up with your site name, the page title, a couple of lines of description, an accent color, and an image or a video player, that is a link preview. Discord builds that card by fetching the page and reading the metadata in its HTML, and the process of building it is called unfurling. If you want a preview that goes past a title, description, and image, Component Embeds let you build a fully custom layout out of Discord components. The rest of this page covers the standard preview.
Link previews are subject to change.

Quick Start

Drop this into the <head> of a page and you get a preview with your site name, a linked title, a description, an accent color, and a large image below the text.
An embed link preview showing the example above

How Discord Reads Your Page

Discord makes a single GET request for the URL that was shared and parses the HTML that comes back. Your page has to meet all of the following for a preview to appear.

Let the Crawler Through

The crawler identifies itself with this User-Agent:
If your site sits behind bot protection, a WAF, or a rate limiter, allow user agents containing Discordbot.
This is not the same User-Agent that API clients send. Apps calling the HTTP API identify themselves as DiscordBot ($url, $versionNumber), described in the API reference. Rules written against that string will not match the crawler.

Tag Reference

For each tag:
  • The key comes from name if present, otherwise from property.
  • The value comes from content if present, otherwise from value.
  • Key names are case-sensitive. og:title works, OG:Title does not.
  • When several tags map to the same field, the first non-empty one wins for the title, description, and site name. For layout, color, and date tags, the last one in the document wins.

Preview Layouts

The tags you set decide which layout a reader gets.

Images

  • Supported formats are PNG, GIF, JPEG, WebP, and AVIF.
  • Provide og:image:width and og:image:height. Without them, Discord fetches the image to measure it, and if that fetch fails or runs past the time budget the image is dropped.
  • Relative URLs must start with /. A bare images/card.png is not resolved.
  • Dimension, type, and alt tags attach to og:image and twitter:image only. They are not read for og:image:url, og:image:secure_url, or twitter:image:src, so use the plain tag names when you want to declare dimensions.
  • Two or more og:image tags produce a gallery. At most 4 images are shown.
  • Sharing a URL that points straight at an image file produces an image preview with no metadata required. An animated GIF shared this way plays as an animated image.

Video

A video plays inline when og:video points at a video file. Only the formats .mp4, .webm, or .mov are allowed. Point the tag at the file itself, not at a page that plays it. The following must also be true:
  • Set og:type to video.other or twitter:card to player. Video tags are ignored on the default link layout.
  • Set og:image. It becomes the poster frame and it is required to render the video.
  • Serve the file over https. Video URLs are always loaded over https, so an http URL is rewritten.
  • Discord measures the file to size the player, so og:video:width and og:video:height are optional. If the file cannot be measured and no dimensions are declared, the video is dropped and the layout falls back to a plain link preview.

oEmbed

Discord supports oEmbed in JSON only, discovered through a link tag in your document:
oEmbed runs after Open Graph, so most of its fields fill gaps rather than replacing what your <meta> tags already said. These fields are used: html, url, width, height, and cache_age are ignored. Errors fetching or parsing the oEmbed document are ignored too, so a broken endpoint costs you the oEmbed fields but leaves the rest of the preview intact.

Accent Color and Publish Date

theme-color sets the accent color of the preview, and it has to be a 6 or 8 digit hex value:
Three-digit shorthand such as #58F, CSS color names such as rebeccapurple, and rgb() notation are all ignored. Publish dates have to be full RFC 3339 timestamps with a time and an offset:
A date on its own, such as 2026-09-15, is not accepted.

Limits

Titles and descriptions are trimmed to fit. An over-long site name, alt text, or URL causes the preview to not render at all.
Title and description limits are counted in bytes, not characters.
The description is shown as plain text, and HTML tags in it appear literally. On og:type rich previews the description is rendered as Discord markdown instead, so asterisks, underscores, and backticks will format the text.

Caching and Testing

Discord caches previews for about 30 minutes. While a preview is cached, editing your tags and resharing the same URL shows the old card.
  • To see changes immediately, share the URL with a new query string, such as ?v=2.
  • Changing only the #fragment does not work. Fragments are not part of the cache key.
  • The Embed Debugger shows how Discord reads any URL, including which tags it picked up and which layout it chose.

Troubleshooting

No preview at all
  • Bot protection, a WAF, or a rate limiter blocked the request. Allow user agents containing Discordbot.
  • The page returned a non-2xx status, or a content type other than text/html or application/xhtml+xml.
  • Your tags are present but their content values are empty.
  • og:site_name, image alt text, or a URL ran past its limit.
  • The page produced nothing to show. A preview needs at least one of title, description, author, image, thumbnail, video, or site name.
  • Your tags are injected by client-side JavaScript. Render them server-side instead.
The image is missing
  • No og:image:width and og:image:height, and the image could not be fetched in time. Declare the dimensions.
  • The image is in a format other than PNG, GIF, JPEG, WebP, or AVIF.
  • The image URL is relative and does not start with /.
  • You set dimensions on og:image:url or og:image:secure_url instead of og:image.
The video does not play
  • og:type is not video.other and twitter:card is not player.
  • There is no og:image poster.
  • The URL is not a direct .mp4, .webm, or .mov file.
  • The file could not be measured and has no og:video:width and og:video:height.
The preview is stale
  • It is cached. Reshare with a new query string.

Next Steps

Component Embeds

Build a fully custom preview layout for your links out of Discord components.