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:
- Create an HTML template for your OG image (1200x630px)
- Host the template at a URL with dynamic parameters (title, description, etc.)
- Use ScreenshotAPI to capture the rendered template as a PNG
- 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.webpDesign Tips for Great OG Images
- Keep text large: OG images are often shown at small sizes. Use 48px+ font sizes
- High contrast: White text on dark/gradient backgrounds works best
- Brand it: Include your logo and brand colors for recognition
- Keep it simple: 1-2 lines of text maximum. No complex layouts
- Test across platforms: Twitter, LinkedIn, Discord all crop differently
- Use WebP for performance: 60-80% smaller than PNG with similar quality
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:
- Vercel OG (@vercel/og): Uses Satori to render React to SVG. Limited to basic HTML/CSS, no full browser rendering
- Self-hosted Puppeteer: Full control but requires managing Chrome instances, memory, and scaling
- Cloudinary: Image transformation API, but not designed for HTML rendering
- ScreenshotAPI: Full browser rendering, any HTML/CSS/JS, simple API call, no infrastructure to manage
Start generating OG images
Try the API playground -- no signup needed. See your first OG image in seconds.
Related Articles
Social Card Generation
Generate dynamic social cards for Twitter, LinkedIn, and Discord.
Website Thumbnail Generation
Create website thumbnails with the output resize feature.
Automate Screenshots with Node.js
Build automated screenshot workflows with Node.js.
Complete Screenshot API Guide
Everything you need to know about screenshot APIs.