← Back to blog

Generate Social Media Preview Cards with Screenshot API

March 2026 -- 8 min read

When someone shares a link on Twitter, LinkedIn, Slack, or Discord, those platforms display a preview card with a title, description, and image. The image is the most impactful element -- it determines whether people click. This guide shows you how to generate those images dynamically using a screenshot API.

Why Dynamic Social Cards Matter

Links with preview images get 2-3x more engagement than links without them. But manually creating an image for every page is impractical when you have hundreds or thousands of pages. Dynamic generation solves this.

Use cases for dynamic social cards:

The Architecture

The approach is straightforward:

  1. Create an HTML template for your social card (or use the actual page)
  2. Use a screenshot API to capture it at 1200x630 pixels (the standard OG image size)
  3. Serve the image via your OG meta tags
  4. Cache the result for performance

Method 1: Screenshot Your Actual Pages

The simplest approach -- capture a screenshot of each page and resize to OG dimensions.

Node.js -- Generate OG image from any URL
const express = require('express');
const app = express();

const API_BASE = 'https://screenshotapi-api-production.up.railway.app';
const API_KEY = process.env.SCREENSHOT_API_KEY;

// Cache for generated images (use Redis in production)
const cache = new Map();

app.get('/og-image', async (req, res) => {
  const { url } = req.query;
  if (!url) return res.status(400).send('URL required');

  // Check cache
  if (cache.has(url)) {
    res.set('Content-Type', 'image/jpeg');
    return res.send(cache.get(url));
  }

  // Generate screenshot at OG image dimensions
  const params = new URLSearchParams({
    url,
    width: '1200',
    height: '630',
    format: 'jpeg',
    quality: '85',
    output_width: '1200',  // Ensure exact output size
    output_height: '630',
  });

  const response = await fetch(
    `${API_BASE}/v1/screenshot?${params}`,
    { headers: { 'Authorization': `Bearer ${API_KEY}` } }
  );

  const buffer = Buffer.from(await response.arrayBuffer());

  // Cache for 1 hour
  cache.set(url, buffer);
  setTimeout(() => cache.delete(url), 3600000);

  res.set('Content-Type', 'image/jpeg');
  res.set('Cache-Control', 'public, max-age=3600');
  res.send(buffer);
});

app.listen(3000);

Method 2: Custom Social Card Template

For more control, create a dedicated HTML template for your social cards and screenshot that instead.

Next.js -- Social card template page
// app/social-card/page.js
// A dedicated page designed to look good at 1200x630

export default function SocialCard({ searchParams }) {
  const { title, description, author } = searchParams;

  return (
    <div style={{
      width: 1200, height: 630,
      display: 'flex', flexDirection: 'column',
      justifyContent: 'center', padding: 80,
      background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
      color: 'white', fontFamily: 'Inter, sans-serif',
    }}>
      <h1 style={{ fontSize: 48, fontWeight: 800, marginBottom: 24 }}>
        {title || 'My Blog Post'}
      </h1>
      <p style={{ fontSize: 24, opacity: 0.9 }}>
        {description || 'A great article about something interesting'}
      </p>
      <div style={{ marginTop: 'auto', fontSize: 18, opacity: 0.7 }}>
        {author || 'yourdomain.com'}
      </div>
    </div>
  );
}
Generate the card image
// Use CSS injection to ensure no scrollbars
const params = new URLSearchParams({
  url: 'https://yoursite.com/social-card?title=My+Post&author=John',
  width: '1200',
  height: '630',
  format: 'jpeg',
  quality: '90',
  css: 'body { margin: 0; overflow: hidden; }',
  wait: '500',
});

const response = await fetch(
  `https://screenshotapi-api-production.up.railway.app/v1/screenshot?${params}`,
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);

Method 3: Thumbnail Previews

For link directories or bookmark managers, generate smaller thumbnails:

Generate 400px thumbnails
# Capture at full viewport, resize output to 400px wide thumbnail
curl "https://screenshotapi-api-production.up.railway.app/v1/screenshot\
  ?url=https://example.com\
  &width=1280&height=800\
  &output_width=400\
  &format=webp&quality=80" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -o thumbnail.webp

Adding OG Meta Tags

Once you have your image generation endpoint, reference it in your HTML:

HTML meta tags
<!-- Open Graph (Facebook, LinkedIn) -->
<meta property="og:image" content="https://yoursite.com/og-image?url=https://yoursite.com/blog/my-post" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />

<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content="https://yoursite.com/og-image?url=https://yoursite.com/blog/my-post" />

Performance Tips

Conclusion

Dynamic social card generation with a screenshot API is one of the highest-impact things you can do for link engagement. With the output resize feature, you can capture pages at their natural viewport size and resize to the exact dimensions social platforms expect -- no distorted layouts or broken responsive designs.

Generate Social Cards Now

Try the playground -- capture and resize screenshots instantly.

Open Playground

Related Articles