OG Image Generator APIs Compared: Templates vs Screenshots vs Custom
The best og image generator API depends on your design complexity and budget. For simple text-on-background cards, Vercel OG (Satori) is free and fast. For full CSS control with any design, SnapRender captures HTML templates as images starting at $9/mo. For non-developers who need drag-and-drop, template services like Placid start at $29/mo. This article compares all three categories with real pricing and code.
Every link shared on social media needs an OG image. Without one, your link gets a plain text card that nobody clicks. With a good one, click-through rates jump 30-40%. The question isn't whether you need OG images. It's which generation approach fits your stack.
I've used all three categories in production. Here's how they actually compare.
Category 1: Satori and Vercel OG (JSX to Image)
Vercel's @vercel/og turns JSX into SVG using Satori, then renders the SVG to PNG with Resvg. It runs on the Edge Runtime, needs no browser, and is genuinely fast.
How It Works
// Next.js App Router: app/api/og/route.tsx
import { ImageResponse } from 'next/og';
export const runtime = 'edge';
export async function GET(req: Request) {
const { searchParams } = new URL(req.url);
const title = searchParams.get('title') ?? 'My Site';
return new ImageResponse(
(
<div style={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
padding: 80,
background: '#0f172a',
color: 'white',
fontFamily: 'Inter',
}}>
<div style={{ fontSize: 56, fontWeight: 800 }}>{title}</div>
</div>
),
{ width: 1200, height: 630 }
);
}
What Works
Satori handles basic layouts well. Flexbox, text, colors, linear gradients, border radius, and simple positioning all work. For a card with a title, subtitle, and maybe a logo, it's fine. Response times are excellent: 50-200ms cold, under 50ms warm.
What Breaks
Satori implements a CSS subset. The moment your design needs anything beyond basic Flexbox, you hit walls:
- No CSS Grid. If your OG design uses a grid layout, you'll need to restructure it entirely.
- Limited
position: absolute. Partially supported, but layout bugs are common. - No
box-shadow. A design staple that simply doesn't exist in Satori. - No pseudo-elements.
::beforeand::afterdon't work. - No
backdrop-filter. Frosted glass effects are out. - Font loading is manual. You must fetch font files and pass them as ArrayBuffers. No Google Fonts URL support.
- Edge Runtime only. You need Vercel or a compatible edge platform.
The font situation deserves extra emphasis. Loading fonts in Satori looks like this:
const inter = await fetch(
new URL('../../assets/Inter-Bold.ttf', import.meta.url)
).then((res) => res.arrayBuffer());
return new ImageResponse(jsx, {
width: 1200,
height: 630,
fonts: [{ name: 'Inter', data: inter, weight: 700 }],
});
You need the raw .ttf or .woff file bundled with your code. Multiple weights means multiple font files. It works, but it's friction that HTML templates don't have.
Pricing
Free on Vercel's hobby plan. On Pro ($20/mo), OG image generation uses your Edge Function invocations, which are generous enough that OG images are effectively free.
Best For
Teams already on Vercel with simple OG designs (text, basic shapes, solid/gradient backgrounds). If your design fits Flexbox-only CSS, this is the cheapest and fastest option.
Category 2: Screenshot APIs for OG Image Generation
Screenshot APIs like SnapRender and ScreenshotOne capture actual web pages as images. For OG generation, you design an HTML template and point the API at it. The API launches a real browser, renders the page, and returns the image.
How It Works with SnapRender
Design your OG template as a plain HTML page. Host it anywhere. Call SnapRender to capture it.
import { SnapRender } from 'snaprender';
const client = new SnapRender({ apiKey: process.env.SNAPRENDER_KEY });
async function generateOgImage(title, author) {
const templateUrl = `https://og.yoursite.com/blog?title=${encodeURIComponent(title)}&author=${encodeURIComponent(author)}`;
const image = await client.capture({
url: templateUrl,
width: 1200,
height: 630,
format: 'png',
cache: true,
cacheTtl: 86400,
});
return image;
}
That's the entire og image generator API integration. The HTML template does the heavy lifting.
What Works
Everything. Your template is a real web page rendered by a real browser. This means:
- Full CSS support. Grid, Flexbox, absolute positioning, transforms, shadows, filters.
- Google Fonts via a
<link>tag. No manual font loading. - Embedded images via
<img>tags. Product screenshots, author avatars, logos. - Any JavaScript that runs on page load (data fetching, canvas rendering, animations frozen at final frame).
- WebP, SVG, and any other image format browsers support.
Design iteration is straightforward: open the template URL in your browser, use DevTools to tweak CSS, refresh. When it looks right in the browser, it will look identical in the screenshot.
SnapRender Specifically
SnapRender is a single GET endpoint. No SDKs required (though Node.js, Python, and Go SDKs exist if you want them). Relevant features for OG generation:
| Feature | Why It Matters for OG Images |
|---|---|
| Custom viewport (width/height) | Set exactly 1200x630 |
| Format selection (PNG/JPEG/WebP) | PNG for crisp text, JPEG for photo backgrounds |
| Cache with TTL | Same template + params returns cached image in under 200ms |
| Block ads and cookie banners | Clean captures if your template includes third-party elements |
| Custom headers/cookies | Pass auth tokens if your template server requires them |
| Batch screenshots | Generate OG images for hundreds of pages in one API call |
SnapRender's cache is particularly useful for OG images. Once generated, the same URL returns a cached response in under 200ms. You don't need to build your own caching layer if your template URLs are deterministic. For more on batch processing, see Batch API Optimization Guide.
Pricing
SnapRender starts at $9/mo for 2,000 screenshots on the Starter plan. The free tier gives you 500/mo. For OG images specifically:
- A blog publishing 10 posts/week uses ~40 images/month. The free tier covers this.
- A content site with 5,000 existing pages needs a one-time backfill (Growth plan at $29/mo for 10,000), then drops to Starter or free for ongoing generation.
- An e-commerce site with 50,000 products fits the Scale plan at $199/mo for 200,000 images.
No feature gating across plans. The free tier has the same capabilities as Scale. For a full pricing breakdown, see Cheapest Screenshot APIs with Free Tiers.
ScreenshotOne Comparison
ScreenshotOne offers similar functionality but starts at $17/mo for 2,000 screenshots. SnapRender is $9/mo for the same volume. Both support custom viewports and caching. ScreenshotOne has been around longer and has more documentation, but SnapRender's single-endpoint design is simpler to integrate. For a deeper comparison, see ScreenshotOne Alternative at Lower Price.
| SnapRender | ScreenshotOne | |
|---|---|---|
| 2,000 screenshots/mo | $9 | $17 |
| 10,000 screenshots/mo | $29 | $79 |
| Free tier | 500/mo | 100/mo |
| Cache included | Yes, configurable TTL | Yes |
| Auth | API key header | API key param |
Best For
Any team that needs full CSS control over OG image design. The template approach works with any framework, any hosting provider, and any level of design complexity. It's the most flexible og image generator API approach.
Category 3: Template Services (Placid, Bannerbear)
Template services provide a visual editor where you design OG image templates by dragging and dropping elements. You then call their API with dynamic data, and they render the image.
How They Work
- Open the Placid/Bannerbear web editor.
- Drag text layers, image layers, shapes onto a 1200x630 canvas.
- Mark certain layers as "dynamic" (title, author name, avatar URL).
- Call the API with values for those dynamic layers.
- Get back a rendered image.
// Placid API example
const response = await fetch('https://api.placid.app/api/rest/images', {
method: 'POST',
headers: {
'Authorization': `Bearer ${PLACID_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
template_uuid: 'abc123',
layers: {
title: { text: 'My Blog Post Title' },
author: { text: 'Jane Smith' },
avatar: { image: 'https://example.com/jane.jpg' },
},
}),
});
const { image_url } = await response.json();
Pricing
This is where template services get expensive:
| Service | Starter Price | Images Included | Per Extra Image |
|---|---|---|---|
| Placid | $29/mo | 1,000 | $0.03 |
| Bannerbear | $49/mo | 1,000 | $0.05 |
| Htmlcsstoimage | $14/mo | 750 | $0.02 |
Compared to SnapRender at $9/mo for 2,000 images, template services cost 3-5x more per image. And that's before counting the limitations.
What Works
The visual editor is genuinely nice for non-developers. Marketing teams can create and update OG templates without writing code. The drag-and-drop interface means anyone who's used Canva can design a template.
What Breaks
- Limited design control. You're constrained to the elements the editor supports. No custom CSS, no complex animations, no full-page layouts.
- Vendor lock-in. Your templates live on their platform. Moving to a different service means rebuilding everything.
- Slow iteration for developers. If you're comfortable with HTML/CSS, the visual editor feels slower than writing code.
- Font limitations. Some services only support a subset of Google Fonts. Custom fonts require enterprise plans.
Best For
Marketing teams and non-developers who need to create and update OG images without developer involvement. If your team can't write HTML/CSS, template services are the pragmatic choice.
The Full Comparison
| Feature | Vercel OG / Satori | SnapRender | ScreenshotOne | Placid | Bannerbear |
|---|---|---|---|---|---|
| CSS support | Flexbox subset | Full | Full | Drag-and-drop | Drag-and-drop |
| CSS Grid | No | Yes | Yes | N/A | N/A |
| Custom fonts | Manual TTF loading | Google Fonts link | Google Fonts link | Limited selection | Limited selection |
| Shadows/filters | No | Yes | Yes | Basic | Basic |
| Embedded images | Limited | Full <img> support |
Full <img> support |
Image layers | Image layers |
| Design iteration | Deploy to test | Browser DevTools | Browser DevTools | Visual editor | Visual editor |
| Fresh render time | 50-200ms | 2-5s | 2-5s | 3-10s | 3-10s |
| Cached response | Compute each time | Under 200ms | ~200ms | Varies | Varies |
| 2,000 images/mo | Free | $9 | $17 | $29+ | $49+ |
| 10,000 images/mo | Free | $29 | $79 | $99+ | Custom |
| Free tier | Unlimited | 500/mo | 100/mo | None | None |
| Setup complexity | Low (Vercel only) | Medium | Medium | Low | Low |
| Framework lock-in | Next.js / Edge | None | None | None | None |
Decision Framework
The right choice depends on three factors: design complexity, team composition, and budget.
Pick Vercel OG if:
- You're already on Vercel with Next.js.
- Your OG designs are simple: title text on a colored/gradient background.
- You don't need CSS Grid, shadows, or complex positioning.
- Budget: $0.
The speed is unbeatable. Edge-rendered images in under 100ms with no external API calls. But the CSS limitations mean you'll outgrow it the moment a designer hands you anything moderately complex.
Pick SnapRender if:
- You need full CSS control over your OG image designs.
- You want the cheapest per-image cost among screenshot APIs.
- Your templates use web fonts, CSS Grid, shadows, or embedded images.
- You want caching built in so repeat requests are under 200ms.
- Budget: $0-29/mo.
SnapRender's approach treats OG image generation as a special case of screenshot capture. Design your template in HTML/CSS with full browser capabilities, capture it at 1200x630, and cache the result. The Starter plan at $9/mo covers 2,000 images, which handles most content sites. The free tier's 500 monthly screenshots work for smaller blogs.
The og image generator API pattern with SnapRender looks like this in practice:
// Complete OG image generation
const params = new URLSearchParams({
url: `https://og.mysite.com/template?title=${encodeURIComponent(title)}`,
width: '1200',
height: '630',
format: 'png',
cache: 'true',
cache_ttl: '86400',
});
const img = await fetch(`https://app.snap-render.com/v1/screenshot?${params}`, {
headers: { 'X-API-Key': process.env.SNAPRENDER_KEY },
});
No SDK needed. No browser to manage. No template service vendor lock-in. Your HTML template is portable; if you ever switch APIs, you change one URL.
Pick a template service (Placid/Bannerbear) if:
- Your marketing team needs to create and edit OG templates without developers.
- You're willing to pay 3-5x more per image for the visual editor.
- Design complexity is moderate (text, images, basic shapes).
- Budget: $29-99/mo.
Template services make sense when the bottleneck is designer/developer handoff, not technical capability.
Pick ScreenshotOne if:
- You need the same full-CSS approach as SnapRender but prefer a more established vendor.
- Budget flexibility: $17/mo and up.
ScreenshotOne does the same thing as SnapRender at roughly double the price. Both work. SnapRender is cheaper.
Cost at Scale
Let's make the numbers concrete for a content site generating 5,000 OG images per month (backfill plus ongoing):
| Solution | Monthly Cost |
|---|---|
| Vercel OG | $0 (compute included in Vercel Pro) |
| SnapRender Growth | $29 (10,000 included) |
| ScreenshotOne | $79 (10,000 included) |
| Placid | $99+ (custom pricing above 1,000) |
| Bannerbear | $149+ (custom pricing) |
Vercel OG wins on price if your designs fit its CSS subset. SnapRender wins if they don't. The template services cost 3-5x more and offer less design flexibility than HTML templates. For more on screenshot API pricing, see Screenshot API Pricing Compared.
What I Actually Use
For every project where OG images matter, I've landed on the screenshot API approach. The reasoning is simple:
-
HTML/CSS is the design tool. No new syntax to learn (Satori JSX), no visual editor to fight, no CSS subset to memorize. If it works in Chrome, it works in the screenshot.
-
Templates are portable. They're HTML files. They work with any screenshot API, any hosting, any framework. Zero vendor lock-in.
-
Debugging is trivial. Open the template URL, hit F12, fix the CSS. With Satori, you're guessing which CSS properties are supported. With template services, you're fighting a drag-and-drop editor.
-
Caching eliminates the speed gap. Yes, fresh renders take 2-5 seconds. But OG images are generated once per content piece and cached. SnapRender's built-in cache returns repeat requests in under 200ms. In practice, the generation speed is irrelevant.
The $9/mo for SnapRender's Starter plan is the cost of not having to think about browser management, Puppeteer memory leaks, or Chrome update breakage. For OG images, that tradeoff is obvious. To get started, see How to Screenshot a URL in 3 Lines of Code.