GET /og — OG Image API

Generate Open Graph images from a signed URL. Public endpoint, no API key required.

Endpoint

GET https://api.renderog.app/og

Request Parameters

Parameter Type Default Limits Notes
template string basic, gradient, blog, product Required
title string ≤200 chars Required, the main text
subtitle string optional Secondary text (template-dependent)
description string optional Longer text, used by some templates
theme string dark light, dark Color scheme
w int 1200 100–2400 Width in pixels
h int 630 100–1260 Height in pixels
format string png png, webp, avif, svg Output format
expires int unix seconds Optional; if set, signature must include this and must be in the future
sig string hex, 64 chars HMAC-SHA256 signature (required)

Response

Status 200 (success):

  • Content-Type: image/png, image/webp, image/avif, or image/svg+xml
  • Content-Length: size in bytes
  • Cache-Control: public, s-maxage=31536000, immutable — cached at edge for 1 year
  • X-Render-Ms: milliseconds to render (≤100ms cached, ≤500ms cold)
  • X-Cache: HIT or MISS

Status 400 (invalid params):

{ "error": { "code": "invalid_params", "message": "..." } }

Not billed. Check title length, dimensions, template name.

Status 403 (signature invalid/expired):

{ "error": { "code": "invalid_signature", "message": "..." } }

Not billed. Verify signature calculation and that expires (if set) is a future unix timestamp.

Status 422 (render failed):

{ "error": { "code": "render_failed", "message": "..." } }

Not billed. Usually invalid CSS or template HTML. Test with a simple template first.

Status 429 (rate limited):

{ "error": { "code": "rate_limited", "message": "..." } }

Not billed. Includes Retry-After header. Free: 60/min, Paid: 600/min.

Signing

All /og requests must be signed with HMAC-SHA256:

  1. Collect all parameters except sig
  2. Sort alphabetically by key
  3. URL-encode each value
  4. Join with &: key1=value1&key2=value2...
  5. Compute sig = HMAC-SHA256(SIGNING_SECRET, canonical) and encode as hex
  6. Append to URL: ...&sig=<sig>

Example (canonical):

format=png&h=630&template=basic&theme=dark&title=Hello&w=1200

(Note: sig is excluded, everything else sorted alphabetically)

If expires is set, it must be included in the signature:

expires=1700000000&format=png&h=630&template=basic&theme=dark&title=Hello&w=1200

Templates

basic

Clean, minimal layout. Left-aligned text with accent color.

Example:

https://api.renderog.app/og?template=basic&title=My%20Startup&subtitle=Build%20fast&theme=dark&sig=...
  • title: Required, large heading
  • subtitle: Optional, smaller secondary text
  • Colors: White on dark background (default), or dark on light (if theme=light)

gradient

Modern gradient background with centered text.

Example:

https://api.renderog.app/og?template=gradient&title=Ship%20It&description=Fast%20deployments&theme=dark&sig=...
  • title: Required
  • description: Optional, line-wrapped body text
  • theme: Affects gradient colors and text contrast

blog

Article-style layout with byline and date placeholders.

Example:

https://api.renderog.app/og?template=blog&title=Next.js%2015%20is%20Here&subtitle=What%27s%20New&theme=dark&sig=...
  • title: Article headline
  • subtitle: Byline or publication name
  • description: Summary text (optional)

product

Product-card layout with icon placeholder and feature list.

Example:

https://api.renderog.app/og?template=product&title=RenderOG&subtitle=OG%20Images%20at%20the%20Edge&theme=light&sig=...
  • title: Product name
  • subtitle: Tagline
  • description: Bullet-point features (optional)

Caching Behavior

Every OG image is cached at Cloudflare's edge for 1 year (s-maxage=31536000). The cache key is the full URL including query parameters.

First render (MISS): 50–100ms depending on image complexity and font subsetting. Cached render (HIT): <5ms.

Cache hits do not count toward your quota and are never billed.

Satori & CSS Constraints

OG images are rendered with Satori (React JSX → SVG → PNG). Templates are written as HTML/CSS strings, not JSX.

Supported CSS

  • Flexbox layout (display: flex, flex-direction, justify-content, align-items, gap, flex-wrap, etc.)
  • Sizing: width, height, min-width, max-width, padding, margin, border-radius
  • Colors: color, background-color, border (solid only)
  • Text: font-size, font-weight (numerical: 400–900), letter-spacing, line-height, text-align, text-transform
  • Positioning: absolute, relative (with top, left, right, bottom)

Not Supported

  • Grid (display: grid does not work)
  • calc() — use fixed dimensions
  • var() or custom properties — inline values only
  • System fonts — must pass font data explicitly (Inter subset is bundled)
  • Remote image URLs — Satori's internal fetch fails on Workers; fetch images in the route handler and inline as base64 data URIs
  • Transforms (transform: rotate(), skew, etc.)
  • Filters (filter: blur(), etc.)
  • Animations — static renders only

Fonts

Built-in: Inter (latin + cyrillic subset, weights 400–700, @font-face included).

For other fonts, pass base64-encoded TTF/OTF data at template render time (API key route). Standard web fonts (Google Fonts, etc.) are accessible via @font-face if you inline the url() as a base64 data URI.

Examples

Minimal OG (curl)

curl "https://api.renderog.app/og?template=basic&title=Hello%20World&w=1200&h=630&sig=abc123def456..."

With Expiry

Signature includes expires (unix seconds, ~1 hour from now):

https://api.renderog.app/og?expires=1723000000&format=png&h=630&template=basic&title=Hello&w=1200&sig=...

If current time > expires, the API returns 403 expired.

Different Format

https://api.renderog.app/og?template=blog&title=Article&format=webp&sig=...

Light Theme

https://api.renderog.app/og?template=product&title=RenderOG&theme=light&w=1200&h=630&sig=...

Performance Notes

  • Cached renders: <5ms, served from Cloudflare's edge in your region
  • Cold renders: 50–150ms depending on CSS complexity
  • Max dimensions: 2400×1260 px (larger images take longer)
  • Wasm initialization: Happens once per Worker instance, not per-request
  • Font subsetting: Inter is pre-subset and bundled; custom fonts add ~10–30ms

Debugging

Not rendering? Use the Playground to preview before signing. Common issues:

  • Empty or wrong text: Check title is provided and URL-encoded
  • Layout broken: Satori only supports flexbox. No grid, no calc().
  • Image not showing: Satori can't fetch remote images. Fetch and inline as data URI instead.
  • Wrong colors: Double-check theme value and ensure CSS color values are valid hex/rgb.

See Error Codes for all status codes and meanings.