Puppeteer vs Satori vs Template APIs (2026)

Puppeteer vs Satori vs Template APIs (2026)

There are three ways to generate images from code in 2026: take a screenshot of HTML with Puppeteer, convert JSX to an image with Satori, or call a template API. Each has real trade-offs in speed, cost, and how much infrastructure you want to babysit.

I've used all three in production. Here's what I'd pick for different situations and why.

The quick answerThe Quick Answer

PuppeteerSatoriTemplate APIs
Speed1-5 seconds20-300ms1-2 seconds
Cost (10K images/mo)$1-40$0-5$25-150
Setup time1-2 weeks2-4 hours1-4 hours
MaintenanceHighLowVery low
CSS supportFullFlexbox onlyVisual editor
Best forComplex layoutsSimple OG imagesBranded content at scale

If you just want the answer: use Satori for simple OG images and social cards. Use a template API for anything branded, data-driven, or designed by non-developers. Use Puppeteer only when you need full CSS support and are willing to maintain the infrastructure.

Approach 1 puppeteer headless browser screenshotsApproach 1: Puppeteer (Headless Browser Screenshots)

Puppeteer launches headless Chrome, renders your HTML page, and takes a screenshot. It's the brute-force approach: if a browser can render it, Puppeteer can capture it.

How it worksHow It Works

import puppeteer from "puppeteer"
 
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.setViewport({ width: 1200, height: 630 })
await page.setContent(`
  <div style="display: grid; place-items: center;
    width: 1200px; height: 630px;
    background: #1a1a2e; color: white;
    font-family: Inter, sans-serif;">
    <h1>Your Dynamic Title Here</h1>
    <p>Generated at ${new Date().toISOString()}</p>
  </div>
`)
const image = await page.screenshot({ type: "png" })
await browser.close()

That's the basic version. Production code is... more.

The real cost of puppeteerThe Real Cost of Puppeteer

The screenshot call itself is fast (50-570ms). But total end-to-end latency includes browser launch, page load, font loading, and the screenshot. In practice, that's 1-5 seconds per image.

And the infrastructure requirements are heavy:

  • 200-300MB RAM just to start Chrome
  • 500MB+ with images and fonts loaded
  • 70-90% CPU per render on a moderately complex page
  • Docker images bloated by 200-300MB for the Chromium binary

I once deployed a Puppeteer-based OG image generator on a 512MB serverless function. It worked for about a week, then started timing out as traffic grew. Bumped it to 1GB, then 2GB. The screenshots were fine. The AWS bill wasn't.

When puppeteer makes senseWhen Puppeteer Makes Sense

  • You need full CSS support (Grid, transforms, animations, variable fonts)
  • You're rendering existing web components as images
  • The design is complex enough that simpler tools can't handle it
  • You have DevOps capacity to maintain headless Chrome in production

When it doesntWhen It Doesn't

  • Simple card layouts or OG images (overkill)
  • Serverless environments with tight memory/timeout limits
  • Teams without DevOps support
  • High concurrency (Chrome processes don't share resources well)

Approach 2 satori vercelogApproach 2: Satori / @vercel/og

Satori converts JSX to SVG using a custom layout engine, then rasterizes to PNG with resvg (a Rust-based renderer compiled to WASM). No browser needed. It's what powers Vercel's next/og image generation.

How it works 1How It Works

import { Resvg } from "@resvg/resvg-js"
import satori from "satori"
 
const svg = await satori(
  <div
    style={{
      display: "flex",
      flexDirection: "column",
      alignItems: "center",
      justifyContent: "center",
      width: 1200,
      height: 630,
      backgroundColor: "#1a1a2e",
      color: "white",
      fontFamily: "Inter",
    }}
  >
    <h1>Your Dynamic Title Here</h1>
    <p>Generated with Satori</p>
  </div>,
  {
    width: 1200,
    height: 630,
    fonts: [{ name: "Inter", data: fontData }],
  }
)
 
const resvg = new Resvg(svg)
const png = resvg.render().asPng()

Speed is the killer featureSpeed Is the Killer Feature

Satori generates images in 20-50ms once fonts are loaded. With font loading factored in, you're looking at 100-300ms on a warm function. That's 10-50x faster than Puppeteer.

On Vercel Edge Functions or Cloudflare Workers, this is essentially free at most volumes. 10,000 images per month? You won't leave the free tier.

The css limitation is realThe CSS Limitation Is Real

And this is where Satori breaks down. It only supports Flexbox. Here's what you can't use:

  • CSS Grid (the big one)
  • transform / rotate / scale
  • calc()
  • CSS variables
  • filter (blur, drop-shadow)
  • Animations / transitions
  • Variable fonts (often crash)
  • WOFF2 fonts (only TTF, OTF, WOFF)
  • RTL languages

And the worst part? Satori silently ignores unsupported CSS. No errors, no warnings. Your layout just looks wrong and you have to figure out why. I've spent frustrating hours debugging a design only to realize the property I was using wasn't supported.

When satori makes senseWhen Satori Makes Sense

  • OG images and social cards with simple layouts
  • Text-heavy designs on solid backgrounds
  • You're already in Next.js and want next/og integration
  • Speed matters more than design flexibility
  • You're comfortable with Flexbox-only constraints

When it doesnt 1When It Doesn't

  • Complex multi-layer designs
  • Anything needing CSS Grid or transforms
  • Non-Latin text or variable fonts
  • Designs created by a non-technical designer (they can't work in JSX)
  • You need pixel-perfect control beyond Flexbox

Approach 3 template image apisApproach 3: Template Image APIs

Template APIs like Imejis.io, Bannerbear, and Placid take a different approach entirely. You design templates in a visual editor, mark dynamic fields, then call a REST API with your data.

How it works 2How It Works

curl -X POST 'https://render.imejis.io/v1/YOUR_TEMPLATE_ID' \
  -H 'dma-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "title": { "text": "Your Dynamic Title Here" },
    "subtitle": { "text": "Generated via API" },
    "background": { "fillColor": "#1a1a2e" }
  }'

The response is the image. That's it. No browser, no JSX, no font loading, no layout engine. Send JSON, get PNG. If you're new to this approach, our beginner guide to generating images with an API walks through the basics.

The maintenance argumentThe Maintenance Argument

This is where template APIs win for most teams. Compare what you're responsible for:

You ManagePuppeteerSatoriTemplate API
Rendering engineChrome updatesLibrary updatesNothing
Font loadingManual installBundle fontsBuilt into editor
Error handlingCrash recovery, zombiesMinimalNothing
ScalingQueue system, concurrencyEdge functionsNothing
Template creationHTML/CSS codeJSX codeVisual editor
MonitoringUptime, memory, CPUMinimalNothing

With a template API, the answer to "who handles infrastructure?" is "not you." You send a request. You get an image. The provider handles everything else.

Cost at scaleCost at Scale

VolumePuppeteer (self-hosted)Satori (Vercel)Imejis.io
100/mo~$0$0$0 (free tier)
1,000/mo~$5$0$14.99
10,000/mo$20-40$0-5$24.99
100,000/mo$100-300$20-50$69.99

Satori is cheapest. But you can only build simple Flexbox layouts. Puppeteer is cheap to host but expensive in developer time. Template APIs cost more per image but eliminate all infrastructure work.

The question isn't just "how much does the compute cost?" It's "how much does a developer spend maintaining Puppeteer instead of building features?"

When template apis make senseWhen Template APIs Make Sense

  • Non-technical team members design templates
  • You want zero infrastructure maintenance
  • Branded, consistent output at any scale
  • Social media automation, certificates, product images, marketing
  • You'd rather spend dev time on your actual product

When they dontWhen They Don't

  • Simple OG images where Satori works fine
  • You need full CSS control over every pixel
  • Very low volume where the free tier of any approach works

Decision frameworkDecision Framework

Here's how I decide in practice:

"I need OG images for my Next.js blog." Use Satori / next/og. It's built in, fast, and free. See our dynamic OG image generation guide and Next.js image generation tutorial for step-by-step setup.

"I need branded social media cards from a spreadsheet of 2,000 products." Use a template API. Design once in the visual editor, send data via API.

"I need to render a complex React dashboard as an image for PDF reports." Use Puppeteer. Nothing else can render full CSS Grid + animations.

"My marketing team needs to generate event banners without developer help." Use a template API with public links. They fill in a form, they get their image.

"I need the absolute cheapest option and I know React." Satori on Vercel's free tier. Can't beat $0.

"I'm tired of maintaining headless Chrome and debugging font issues." Switch to a template API. Seriously. I made this exact switch last year and the only regret is not doing it sooner.

For more on template API pricing, see our Image Generation API Pricing Comparison. If you're evaluating AI-generated images vs template APIs, check AI Image Generation vs Template APIs. And for real-world speed data, see our Image API Speed Benchmark.

FaqFAQ

Which is fastest puppeteer satori or template apisWhich is fastest: Puppeteer, Satori, or template APIs?

Satori is fastest at 20-300ms per image. Template APIs like Imejis.io take 1-2 seconds. Puppeteer is slowest at 1-5 seconds due to headless browser overhead.

Whats the cheapest way to generate images programmaticallyWhat's the cheapest way to generate images programmatically?

Satori is essentially free on edge platforms, but only supports Flexbox CSS. For full design flexibility with zero maintenance, Imejis.io costs $24.99/month for 10,000 images. Puppeteer self-hosted runs $1-40/month but requires significant DevOps.

Can satori replace puppeteerCan Satori replace Puppeteer?

Only for simple layouts. Satori supports Flexbox but not CSS Grid, transforms, animations, or variable fonts. If your design needs any of these, you'll need Puppeteer or a template API.

Should i use puppeteer or a template api for og imagesShould I use Puppeteer or a template API for OG images?

A template API is usually better. Puppeteer requires managing headless Chrome, handling crashes, and dealing with cold starts. Template APIs handle all infrastructure and return images via a simple REST call.

What are the downsides of puppeteer for image generationWhat are the downsides of Puppeteer for image generation?

Headless Chrome uses 200-300MB RAM per instance. Zombie processes can crash your server. Cold starts on serverless add 2-5 seconds. And you're responsible for browser updates, font loading, and retry logic. It works, but it's a lot of maintenance.

Try it yourselfTry It Yourself

Want to skip the infrastructure headaches? Try Imejis.io free with 100 API calls per month. Design a template in the visual editor, call the API, get your image. No Chrome to manage. No fonts to bundle. No zombie processes at 3am.