What Is a Social Card? Parts, Sizes and Rendering

A social card is the preview box a platform builds when a link is shared. See which tag fills each part and one template rendered at three card sizes.

By Simon Chiu · Updated

A social card is the preview box that a social network or chat app builds when someone shares a link: an image, a title, a short description and the domain, assembled by the platform from the page's meta tags.

People also call it a link preview, a share card or an unfurl. The terms overlap; "social card" usually means the whole box, while OG image means only its picture. This entry is part of the screenshot and rendering glossary.

A plain explanation

You do not send a social card. You publish the ingredients, and every platform bakes its own card from them. A crawler fetches your page, reads the tags in the <head>, downloads the image and draws the box in its own style. That is why the same link looks slightly different in a chat app, a feed and a messaging app.

Card part Where the platform reads it Fallback when the tag is missing
Image og:image, or twitter:image on X No image, or one the platform picks from the page
Title og:title, twitter:title The page <title>
Description og:description, twitter:description <meta name="description"> or nothing
Domain The shared URL, or og:url Always shown
Layout (large or small image) twitter:card on X; the platform's choice elsewhere The platform's default

The Open Graph protocol entry explains the tags and how crawlers read them. The Twitter card entry covers the X-specific card types.

One template, three card shapes

The image is the only part you design, and card slots do not share one shape. We wrote one HTML template that sizes its text from the viewport height, then rendered it at the three card presets RenderScreenshot ships:

The same dark blue card with a Postmortem label, a three-line headline and a domain line, rendered at 1200 by 630, 1200 by 600 and 800 by 600. The text stays inside all three without cropping.
One template rendered with Puppeteer at 1200 x 630, 1200 x 600 and 800 x 600 on 2026-10-15, shown at 32% scale.
Size (preset) PNG bytes WebP bytes (quality 85)
1200 x 630 (og_card) 339,848 22,268
1200 x 600 (twitter_card) 316,580 21,234
800 x 600 (link_preview) 219,972 20,652

The gradient background is what made the PNGs large: smooth colour ramps compress badly in lossless formats. A flat background would shrink them several times. Check that the platforms you target accept WebP before you switch.

The headline in that test was Why our <canvas> charts broke in Safari & how we fixed them. It rendered as text, not as a broken <canvas> tag, because the template escapes every value. Card titles usually come from user or CMS input, so escaping is not optional.

How it works technically

  1. Someone shares https://example.com/post. The platform's crawler requests the HTML, usually without running JavaScript.
  2. It reads the meta tags, then downloads the image URL with no cookies.
  3. It stores the finished card and reuses it for everyone who shares the same URL, often for days.

So the image must be reachable without login, present in the server-rendered HTML, and stable at its URL. If you generate it on demand, the first crawler request waits for the render, so a cached image URL matters.

How to render one in Puppeteer, Playwright and RenderScreenshot

The template, shared by both browser scripts (card.mjs):

const esc = (s) => String(s).replace(/[&<>"']/g, (c) =>
  ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[c]);

export const cardHtml = ({ title, site }) => `<!doctype html><meta charset="utf-8">
<style>
  html, body { margin: 0; width: 100vw; height: 100vh; }
  body { box-sizing: border-box; padding: 6vh 6vw; display: flex; flex-direction: column;
         justify-content: space-between; background: #0f172a; color: #f8fafc; font-family: system-ui, sans-serif; }
  h1 { margin: auto 0; font-size: clamp(28px, 8.5vh, 64px); line-height: 1.12; max-width: 20ch; }
  p { margin: 0; font-size: 3.6vh; color: #cbd5e1; }
</style>
<h1>${esc(title)}</h1><p>${esc(site)}</p>`;

Puppeteer:

import puppeteer from 'puppeteer';
import { cardHtml } from './card.mjs';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.setViewport({ width: 1200, height: 630 });
  await page.setContent(cardHtml({ title: 'Release notes: October', site: 'example.com' }));
  await page.screenshot({ path: 'card.png' });
} finally {
  await browser.close();
}

Playwright:

import { chromium } from 'playwright';
import { cardHtml } from './card.mjs';

const browser = await chromium.launch();
try {
  const page = await browser.newPage({ viewport: { width: 1200, height: 630 } });
  await page.setContent(cardHtml({ title: 'Release notes: October', site: 'example.com' }));
  await page.screenshot({ path: 'card.png' });
} finally {
  await browser.close();
}

RenderScreenshot. Send the same HTML with a card preset, or capture a page URL with preset=og_card. The presets reference lists every size.

import { Client, TakeOptions } from 'renderscreenshot';
import { cardHtml } from './card.mjs';

const client = new Client(process.env.RS_API_KEY);
const image = await client.take(
  TakeOptions.html(cardHtml({ title: 'Release notes: October', site: 'example.com' })).preset('og_card'),
);

The template, the escaping and both browser scripts were tested on 2026-10-15 with Node 22.18, Puppeteer 24.43.1 (headless shell mode, Chrome 148) and Playwright 1.64.1 (Chromium 156). The RenderScreenshot snippet follows the SDK docs and was not run for this page.

Common mistakes

  • Text at the edges. Some layouts crop the sides or show a square. Keep the headline inside a central safe area.
  • Tags added by client-side JavaScript. Most crawlers read only the first HTML response.
  • An image behind authentication. The crawler has no cookies. Use a public URL, or a signed URL with a long expiry.
  • Unescaped titles. A title with < or & breaks the layout or injects markup into your template.

Before you ship, run through the social card checklist. To render your own card template at every preset size, get a free API key.

Frequently asked questions

Is a social card the same as an OG image?
No. The OG image is one part of the card. The card also shows a title, a description and the domain, and the platform lays them out. You control the parts through meta tags; the platform controls the layout.
Can one image work for every platform?
Usually. A 1200 x 630 image with the important text away from the edges works for most cards. Platforms that crop to a different shape cut the edges, so keep a margin, or render a second size with the same template.
Why does my card still show the old image?
Platforms cache the card. Change the image URL, for example with a version parameter, and use the platform's own debugger or re-share tool to ask for a fresh fetch.

Related in this topic

Try RenderScreenshot free

150 free credits every month, no credit card required.