How to Generate Social Cards with Screenshots
Learn how to create dynamic Open Graph images for your website using the RenderScreenshot API.
Social cards make your links stand out when shared on Twitter, LinkedIn, Slack, and other platforms. Instead of static images, you can generate them dynamically from your actual content.
In this tutorial, we'll show you how to use RenderScreenshot to create social cards automatically.
The Problem with Static Social Cards
Most websites use the same Open Graph image for every page, or worse, no image at all. This means:
- Every link looks the same when shared
- Content updates don't reflect in the preview
- You need to manually create images for each page
Dynamic Social Cards
With RenderScreenshot, you can generate unique social cards for every page on your site. Here's how it works:
- Create a template page that displays your content nicely at 1200x630
- Use our API to capture a screenshot of that page
- Serve the screenshot URL as your
og:image
Step 1: Create a Template
Create a route in your app that renders content optimized for social sharing:
<!-- /social-card?title=Hello%20World --> <!DOCTYPE html> <html> <head> <style> body { width: 1200px; height: 630px; display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, #10b981, #059669); font-family: system-ui, sans-serif; } .card { text-align: center; color: white; } h1 { font-size: 64px; margin: 0; } </style> </head> <body> <div class="card"> <h1>{{ title }}</h1> <p>yoursite.com</p> </div> </body> </html>
Step 2: Generate the Screenshot
Use the RenderScreenshot API with the og_card preset:
const screenshotUrl = `https://api.renderscreenshot.com/v1/screenshot?` + `url=${encodeURIComponent('https://yoursite.com/social-card?title=Hello')}&` + `preset=og_card&` + `api_key=rs_pub_...`;
The og_card preset automatically:
- Sets dimensions to 1200x630
- Optimizes for fast loading
- Caches for 24 hours
Step 3: Add to Your Meta Tags
Reference the screenshot URL in your page's meta tags:
<meta property="og:image" content="https://api.renderscreenshot.com/v1/screenshot?url=..." /> <meta property="og:image:width" content="1200" /> <meta property="og:image:height" content="630" /> <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:image" content="https://api.renderscreenshot.com/v1/screenshot?url=..." />
Using Signed URLs
For production, use signed URLs to prevent abuse:
import { generateSignedUrl } from 'renderscreenshot'; const client = new RenderScreenshot({ publicKey: 'rs_pub_...', secretKey: 'rs_secret_...' }); const signedUrl = client.generateSignedUrl({ url: 'https://yoursite.com/social-card?title=Hello', preset: 'og_card', expiresIn: '7d' });
Signed URLs are safe to expose publicly because they can only be used for the specific parameters you signed.
Caching Strategy
Screenshots are cached automatically. The default TTL is 24 hours, but you can customize it:
// Cache for 7 days const url = client.generateSignedUrl({ url: 'https://yoursite.com/social-card', preset: 'og_card', cache: { ttl: '7d' } });
For content that changes frequently, use a shorter TTL or include a cache-busting parameter:
const url = `...&v=${post.updatedAt.getTime()}`;
Testing Your Cards
Before deploying, test your social cards:
- Twitter Card Validator: cards-dev.twitter.com/validator
- Facebook Debugger: developers.facebook.com/tools/debug
- LinkedIn Inspector: linkedin.com/post-inspector
Complete Example
Here's a complete Next.js implementation:
// pages/api/og.ts import { generateSignedUrl } from 'renderscreenshot'; export default function handler(req, res) { const { title, description } = req.query; const templateUrl = new URL('https://yoursite.com/og-template'); templateUrl.searchParams.set('title', title); templateUrl.searchParams.set('description', description); const screenshotUrl = generateSignedUrl({ publicKey: process.env.RS_PUBLIC_KEY, secretKey: process.env.RS_SECRET_KEY, url: templateUrl.toString(), preset: 'og_card', expiresIn: '30d' }); res.redirect(screenshotUrl); }
Then in your pages:
<meta property="og:image" content="/api/og?title=My%20Post&description=..." />
Related Guides
- Taking Screenshots with Puppeteer — Self-hosted screenshot alternative using headless Chrome
- Dark Mode Screenshots with Puppeteer and Playwright — Capture dark mode social cards that stand out in feeds
- Best Screenshot API Comparison — How RenderScreenshot compares to other screenshot services
Have questions? Check our documentation or reach out at [email protected].