Skip to content

OG Engine vs Puppeteer — Performance Comparison

If you’re using Puppeteer, Playwright, or any headless browser to generate OG images, social cards, or email banners — this page is for you.

Puppeteer / PlaywrightOG Engine
How it worksLaunches full Chrome, loads HTML/CSS, screenshots viewportMeasures text with Pretext, draws directly to Canvas
RuntimeChrome binary + Xvfb + sandbox + Node.jsNode.js (or Bun) only
Text renderingFull browser layout engine (Blink)Pretext: Unicode-aware segmentation + Canvas
OutputScreenshot of browser viewportCanvas → PNG / WebP
LanguagesAll (full browser)All — CJK, Arabic, emoji, bidirectional
FontsSystem fonts or network fetchPre-loaded .ttf files (8 families, zero latency)
MetricPuppeteerOG EngineImprovement
Render time~130ms (warm) / ~660ms (cold)~22ms6x faster (warm) / 30x faster (cold)
Memory per render200–500 MB~10 MB20–50x less
Concurrency per instance5–10500+50–100x more
Cold start2–5 seconds~50ms40–100x faster
CPU per renderHigh (full layout + paint)Minimal (text measure + draw)~10x less

For 50,000 images/month:

Puppeteer (self-hosted)OG Engine (hosted)OG Engine (self-hosted)
Compute2–4 vCPU, 4–8 GB RAM1 vCPU, 512 MB RAM
Monthly cost~$40–100 (cloud VM)€39 (Pro plan)~$5–10 (container)
MaintenanceChrome updates, Xvfb, sandboxing, crash recoveryZeroDocker image updates
ScalingManual (add instances, load balance)AutomaticManual

OG Engine is not a general-purpose browser renderer. It generates images from structured text data. You cannot:

  • Render arbitrary HTML/CSS
  • Execute JavaScript in a browser context
  • Screenshot existing web pages
  • Use browser-specific APIs (DOM, CSSOM)

If you need full HTML rendering, keep Puppeteer. If you need text-on-image generation (OG cards, social images, email banners), OG Engine is 6-30x faster and dramatically simpler.

import puppeteer from 'puppeteer'
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.setViewport({ width: 1200, height: 630 })
await page.setContent(`
<html>
<body style="background: #0a0a0a; color: white; font-family: sans-serif; padding: 60px;">
<h1 style="font-size: 48px;">My Blog Post Title</h1>
<p style="font-size: 22px; color: #888;">A description that renders in a real browser.</p>
</body>
</html>
`)
const screenshot = await page.screenshot({ type: 'png' })
await browser.close()
import { OGEngine } from '@atypical-consulting/og-engine-sdk'
const og = new OGEngine(process.env.OG_ENGINE_KEY)
const image = await og.render({
format: 'og',
title: 'My Blog Post Title',
description: 'A description that renders without a browser.',
style: { accent: '#38ef7d', font: 'Outfit', layout: 'left' },
})
Terminal window
curl -X POST https://og-engine.com/render \
-H "Authorization: Bearer $OG_ENGINE_KEY" \
-H "Content-Type: application/json" \
-d '{"format":"og","title":"My Blog Post Title","description":"A description that renders without a browser."}' \
--output og.png
  1. Sign upPOST /auth/register with your email (free, no credit card)
  2. Map your HTML to JSON — title, description, tag, author, style (accent, font, layout)
  3. Replace the Puppeteer call with og.render() or a curl to /render
  4. Remove Chrome dependencies — uninstall puppeteer, remove Xvfb from Dockerfile, drop --no-sandbox flags
  5. Test with /validate — free, unlimited — check that your text fits before rendering
Use CasePuppeteerOG Engine
OG / social card imagesOverkillBest fit
Email bannersSlow, complexBest fit
Blog hero imagesSlowBest fit
Dynamic ad creativesPossibleBest fit
Screenshot existing pagesOnly optionNot supported
Full HTML renderingOnly optionNot supported
PDF generation from HTMLOnly optionNot supported