Puppeteer Renderer

December 5, 2025 ยท View on GitHub

Puppeteer (Chrome headless) based web page renderer.

Renders web pages to HTML, PDF, or screenshots (PNG/JPEG/WebP). Supports both GET and POST requests.

Requirements

  • Node.js >= 24
  • Chromium or Docker

Getting Started

Docker

docker run -d --name renderer -p 8080:3000 ghcr.io/zenato/puppeteer-renderer:latest

Local Development

pnpm install
pnpm dev

Server runs on port 3000 by default.

Build Docker Image Locally

docker build . --file ./Dockerfile --tag local/puppeteer-renderer --build-arg SCOPE=puppeteer-renderer
docker run -d --name renderer -p 8080:3000 local/puppeteer-renderer

API Endpoints

Rendering Endpoints

These endpoints support both GET (query parameters) and POST (JSON body).

EndpointDescription
GET/POST /htmlRenders page and returns HTML
GET/POST /screenshotCaptures page screenshot
GET/POST /pdfGenerates PDF from page

Utility Endpoints

EndpointDescription
GET /healthHealth check. Returns { "status": "ok" }

Rendering Options

The following options apply to /html, /screenshot, and /pdf endpoints.

Note: For complex options like headers, cookies, and nested objects, use POST with JSON body. GET requests support dot notation for simple nested values (e.g., viewport.width=1920).

Common Options

ParameterTypeDefaultDescription
urlstringrequiredTarget URL
timeoutnumber30000Navigation timeout (ms)
waitUntilstring'networkidle2'When to consider navigation done
viewport.widthnumber800Viewport width
viewport.heightnumber600Viewport height
devicestring-Device emulation (e.g., 'iPhone 14 Pro')
userAgentstring-Custom user agent
headersobject-Custom HTTP headers
cookiesarray-Cookies to set
credentials.usernamestring-HTTP basic auth username
credentials.passwordstring-HTTP basic auth password
emulateMediaTypestring-'screen' or 'print'
waitForSelectorstring-Wait for element before capture
waitForSelectorTimeoutnumber30000Selector wait timeout (ms)
disableCachebooleantrueDisable page cache

Screenshot Options

ParameterTypeDefaultDescription
typestring'png''png', 'jpeg', or 'webp'
qualitynumber-Quality (0-100, jpeg/webp only)
fullPagebooleanfalseCapture full page
clipobject-Clip region { x, y, width, height }
omitBackgroundbooleanfalseTransparent background
encodingstring'binary''binary' or 'base64'
animationTimeoutnumber0Wait for animations (ms)

PDF Options

ParameterTypeDefaultDescription
filenamestring-Custom filename
contentDispositionstring'attachment''attachment' or 'inline'
scalenumber1.0Scale (0.1 - 2.0)
formatstring-Paper format (A4, Letter, etc.)
landscapebooleanfalseLandscape orientation
printBackgroundbooleanfalsePrint background graphics
marginobject-Margins { top, right, bottom, left }
displayHeaderFooterbooleanfalseShow header/footer
headerTemplatestring-Header HTML template
footerTemplatestring-Footer HTML template

Usage Examples

GET Request

# HTML
curl "http://localhost:3000/html?url=https://example.com"

# Screenshot with viewport
curl "http://localhost:3000/screenshot?url=https://example.com&viewport.width=1920&viewport.height=1080"

# PDF
curl "http://localhost:3000/pdf?url=https://example.com&filename=report.pdf" -o report.pdf

POST Request

# Screenshot with device emulation
curl -X POST http://localhost:3000/screenshot \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "device": "iPhone 14 Pro",
    "fullPage": true,
    "type": "webp",
    "quality": 90
  }' -o screenshot.webp

# PDF with custom headers and cookies
curl -X POST http://localhost:3000/pdf \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/dashboard",
    "headers": { "Authorization": "Bearer token123" },
    "cookies": [{ "name": "session", "value": "abc", "domain": "example.com" }],
    "printBackground": true,
    "format": "A4"
  }' -o dashboard.pdf

# Wait for specific element
curl -X POST http://localhost:3000/screenshot \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "waitForSelector": "#main-content",
    "waitForSelectorTimeout": 10000
  }' -o screenshot.png

Error Response

All errors return JSON:

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "URL is required"
  }
}

Error codes: VALIDATION_ERROR, NAVIGATION_ERROR, TIMEOUT_ERROR, SELECTOR_NOT_FOUND, BROWSER_ERROR, INTERNAL_ERROR

Environment Variables

VariableDescription
PORTServer port (default: 3000)
IGNORE_HTTPS_ERRORSSet to 'true' to ignore SSL errors
PUPPETEER_ARGSAdditional Chromium arguments (separated by --)

Integration with Express

See puppeteer-renderer-middleware for integrating with existing Express apps.

import express from 'express'
import renderer from 'puppeteer-renderer-middleware'

const app = express()

app.use('/render-proxy', renderer({
  url: 'http://localhost:3000',
}))

app.listen(8080)

License

MIT

Copyright (c) 2017-present, Yeongjin Lee