TutorialOG ImagesNode.js

Build an OG Image Generator with Screenshot API

Generate dynamic Open Graph images for every page on your site. No design tools needed -- just HTML templates and an API call.

Published March 28, 2026 -- 9 min read

What are OG Images and Why Do They Matter?

Open Graph (OG) images are the preview images that appear when you share a link on Twitter, LinkedIn, Discord, Slack, and other platforms. A compelling OG image can increase click-through rates by 2-3x compared to a generic or missing preview.

The problem? Creating unique OG images for every blog post, product page, or documentation page is tedious. Most teams either skip it entirely or use a single static image for the whole site. With a screenshot API, you can automate this completely.

How It Works

The approach is simple:

  1. Create an HTML template for your OG image (1200x630px)
  2. Host the template at a URL with dynamic parameters (title, description, etc.)
  3. Use ScreenshotAPI to capture the rendered template as a PNG
  4. Serve the PNG as your OG image via a meta tag

Step 1: Create Your OG Image Template

First, create an HTML page that renders at exactly 1200x630px. This will be your OG image template. Here is a simple example:

<!-- og-template.html -->
<!DOCTYPE html>
<html>
<head>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      width: 1200px;
      height: 630px;
      display: flex;
      align-items: center;
      justify-content: center;
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      font-family: system-ui, -apple-system, sans-serif;
      color: white;
      padding: 60px;
    }
    .container {
      text-align: left;
      max-width: 900px;
    }
    h1 {
      font-size: 56px;
      font-weight: 800;
      line-height: 1.1;
      margin-bottom: 20px;
    }
    .description {
      font-size: 24px;
      opacity: 0.9;
      line-height: 1.4;
    }
    .footer {
      position: absolute;
      bottom: 40px;
      left: 60px;
      font-size: 18px;
      opacity: 0.7;
    }
  </style>
</head>
<body>
  <div class="container">
    <h1 id="title">Your Blog Post Title</h1>
    <p class="description" id="desc">
      A short description goes here
    </p>
  </div>
  <div class="footer">yourdomain.com</div>
</body>
</html>

Step 2: Make It Dynamic with a Server

Host the template on a simple Express server that accepts query parameters:

// og-server.js
const express = require('express');
const app = express();

app.get('/og', (req, res) => {
  const { title, description, theme } = req.query;

  const bg = theme === 'dark'
    ? 'linear-gradient(135deg, #1a1a2e 0%, #16213e 100%)'
    : 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';

  res.send(`
    <!DOCTYPE html>
    <html>
    <head>
      <style>
        body {
          width: 1200px; height: 630px;
          display: flex; align-items: center;
          background: ${bg};
          font-family: system-ui; color: white;
          padding: 60px;
        }
        h1 { font-size: 52px; font-weight: 800; }
        p { font-size: 22px; opacity: 0.85; margin-top: 16px; }
      </style>
    </head>
    <body>
      <div>
        <h1>${title || 'My Blog Post'}</h1>
        <p>${description || ''}</p>
      </div>
    </body>
    </html>
  `);
});

app.listen(3002);

Step 3: Capture with ScreenshotAPI

Now use the ScreenshotAPI to capture your dynamic template as an image:

// generate-og.js
const fs = require('fs');

async function generateOgImage(title, description) {
  const templateUrl = encodeURIComponent(
    `https://your-server.com/og?title=${title}&description=${description}`
  );

  const response = await fetch(
    `https://screenshotapi-api-production.up.railway.app/v1/screenshot` +
    `?url=${templateUrl}` +
    `&width=1200&height=630` +
    `&format=png`,
    {
      headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
    }
  );

  const buffer = await response.arrayBuffer();
  fs.writeFileSync('og-image.png', Buffer.from(buffer));
  console.log('OG image generated!');
}

generateOgImage(
  'How to Build a Screenshot API',
  'Complete guide to building and scaling a screenshot service'
);

Step 4: Automate for Your Entire Site

For a blog or documentation site, you can generate OG images at build time or on-demand with caching. Here is an approach using Next.js API routes:

// pages/api/og/[slug].js
export default async function handler(req, res) {
  const { slug } = req.query;

  // Look up post data from your CMS/database
  const post = await getPostBySlug(slug);
  if (!post) return res.status(404).end();

  // Check cache first
  const cached = await checkCache(slug);
  if (cached) {
    res.setHeader('Content-Type', 'image/png');
    res.setHeader('Cache-Control', 'public, max-age=86400');
    return res.send(cached);
  }

  // Generate via ScreenshotAPI
  const templateUrl = encodeURIComponent(
    `${process.env.APP_URL}/og-template?title=${post.title}`
  );

  const screenshot = await fetch(
    `https://screenshotapi-api-production.up.railway.app/v1/screenshot` +
    `?url=${templateUrl}&width=1200&height=630&format=png`,
    { headers: { 'Authorization': `Bearer ${process.env.SCREENSHOT_API_KEY}` } }
  );

  const buffer = Buffer.from(await screenshot.arrayBuffer());
  await saveToCache(slug, buffer);

  res.setHeader('Content-Type', 'image/png');
  res.setHeader('Cache-Control', 'public, max-age=86400');
  res.send(buffer);
}

Then reference it in your page's meta tags:

<meta property="og:image" content="https://yoursite.com/api/og/your-post-slug" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />

Advanced: Using the Output Resize Parameter

ScreenshotAPI supports output resizing, which is perfect for generating multiple sizes from a single capture. For example, generate both an OG image and a Twitter card size:

# OG Image (1200x630)
curl "https://screenshotapi-api-production.up.railway.app/v1/screenshot\
  ?url=YOUR_TEMPLATE_URL\
  &width=1200&height=630&format=png" \
  -H "Authorization: Bearer YOUR_API_KEY" -o og.png

# Twitter card (smaller, for faster loading)
curl "https://screenshotapi-api-production.up.railway.app/v1/screenshot\
  ?url=YOUR_TEMPLATE_URL\
  &width=1200&height=630&format=webp\
  &output_width=600&output_height=315&quality=85" \
  -H "Authorization: Bearer YOUR_API_KEY" -o twitter-card.webp

Design Tips for Great OG Images

Cost Analysis

With ScreenshotAPI's free tier (100 screenshots/month), you can generate OG images for 100 pages per month at no cost. For a typical blog publishing 4-8 posts per month, the free tier is more than enough. If you need more, the Pro plan ($29/month) gives you 10,000 screenshots -- enough for even the largest content sites.

Alternatives Compared

There are other approaches to generating OG images:

Start generating OG images

Try the API playground -- no signup needed. See your first OG image in seconds.

Related Articles