You added Open Graph tags, the link looks right on Facebook and Slack, and then someone pastes it into X and the card comes out wrong. The image is cropped strangely, or the title is missing, or there is no card at all. The reason is almost always the same: X reads its own set of tags first, and only some of your Open Graph tags stand in when those are absent.
This post is the short, practical version of how the two systems relate. What Open Graph covers, what Twitter Card adds on top, which tags overlap, and the smallest set you can ship so one link looks right everywhere it gets pasted.
Two standards, one link
Open Graph is Facebook's protocol, and it became the default the rest of the web reads. Slack, Discord, LinkedIn, WhatsApp, iMessage and most others unfurl a link by reading its og: tags. If you only ever add one family of tags, add these.
Twitter Card is X's own layer. It predates X reading Open Graph and still takes priority on that one platform. The important thing is that the two are not rivals you must choose between. X reads Twitter Card tags when they exist and quietly falls back to Open Graph when they do not.
What each tag does
Here is the overlap laid out. The left column is what X looks for, the right is what it uses instead when the left is absent.
| Twitter Card tag | Falls back to | What it sets |
|---|---|---|
twitter:title | og:title | The headline on the card |
twitter:description | og:description | The subhead under it |
twitter:image | og:image | The picture |
twitter:card | nothing | The card shape, summary or summary_large_image |
The pattern is clear. Three of the four Twitter tags have an Open Graph twin, so you rarely need to write them at all. The one tag with no fallback is twitter:card, and it is the one people forget.
The tag that has no fallback
twitter:card decides the shape of the card, and there is no Open Graph equivalent for X to borrow. Leave it out and X defaults to a small square thumbnail beside the text, not the wide banner you designed.
Two values matter:
summary_large_image. The full width banner. This is what you want for a share image drawn at 1200 by 630, and it is the only value that shows your card at the size the picture was made for.summary. A small square thumbnail with the text beside it. Fine for a logo, wrong for a designed card.
So the single most common bug is not a missing image. It is a present image shown too small because twitter:card was never set to summary_large_image.
The smallest set that works everywhere
You do not need every tag from both systems. This is the whole list for a link that looks right on every platform, X included.
og:title,og:description,og:image,og:urlandog:typecover every platform that reads Open Graph.twitter:cardset tosummary_large_imagegives X the wide banner. This is the only Twitter tag you truly need.
That is it. You can add twitter:title, twitter:description and twitter:image if you want a headline or picture on X that differs from the one everywhere else, but if they match your Open Graph values, writing them again only gives you two places to keep in sync. For the mechanics of adding these in a real app, the Open Graph meta tags guide walks through the Metadata API and the mistakes that make a card render blank.
The two Twitter tags with no Open Graph twin
Beyond twitter:card, there are two more X-only tags with nothing to fall back on. Neither is required, but both do something Open Graph cannot express, and both are cheap to add.
twitter:site. The@handleof the site or brand. X shows it as an attribution line on the card, and it is the account the card is credited to when someone shares it.twitter:creator. The@handleof the individual author. On a multi-author site this is how a card names the person who wrote the piece rather than the publication.
If your site is one person, twitter:site alone is enough and you can skip twitter:creator. If it is a publication with named writers, set both. Neither changes how the card looks anywhere except X, which is exactly why they have no Open Graph equivalent.
A complete head, once
Put the whole recommended set together and this is the entire block. Everything a link needs to render right on every platform, X included, in one place.
<!-- Reads everywhere: Slack, Discord, LinkedIn, WhatsApp, iMessage -->
<meta property="og:title" content="Your headline" />
<meta property="og:description" content="One line of subhead" />
<meta property="og:image" content="https://example.com/og.png" />
<meta property="og:url" content="https://example.com/page" />
<meta property="og:type" content="article" />
<!-- X only. The card type is the one tag with no fallback. -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@yourbrand" />Notice what is not here. No twitter:title, twitter:description or twitter:image, because each falls back to its Open Graph twin above and repeating them only gives you a second copy to keep in sync. Add one of those three only when you want X to show something different from every other platform.
Image rules the two share
Both systems point image tags at the same picture, and both have the same two requirements that trip people up.
The URL must be absolute. og:image and twitter:image both need a full https:// address, not a path like /og.png. A crawler is not on your site when it reads the tag, so a relative path resolves to nothing. This is the single most common reason a card renders blank in production.
The size is one number. 1200 by 630 satisfies summary_large_image on X and the wide unfurl everywhere else, so one file serves both. The full table of what each platform crops from that rectangle is in the OG image size guide, and the design rules for making a card readable at thumbnail size are in nine rules for social previews.
When the card still will not update
You set the tags, the image is absolute, twitter:card is right, and the old preview still shows. That is caching, not markup. Each platform holds a copy of your card for its own window, and X in particular can be stubborn. The fix is the same across platforms and is covered in full in why your OG image is not updating: change the image URL so the cache has nothing to serve but the new file.
The takeaway
Write Open Graph tags for the whole web. Add one Twitter tag, twitter:card set to summary_large_image, so X shows the banner instead of a thumbnail. Keep the image URL absolute and the picture at 1200 by 630. Everything past that is optional polish, not a requirement, and the fewer duplicate tags you keep in sync, the fewer ways a card has to break.