Cloudflare Browser Rendering - Complete Reference
Production-ready knowledge domain for building browser automation workflows with Cloudflare Browser Rendering.
Status: Production Ready ✅ Last Updated: 2025-10-22 Dependencies: cloudflare-worker-base (for Worker setup) Latest Versions: @cloudflare/puppeteer@1.0.4, @cloudflare/playwright@1.0.0, wrangler@4.43.0
Table of Contents
- Quick Start (5 minutes)
- Browser Rendering Overview
- Puppeteer API Reference
- Playwright API Reference
- Session Management
- Common Patterns
- Pricing & Limits
- Known Issues Prevention
- Production Checklist
Quick Start (5 minutes)
1. Add Browser Binding
wrangler.jsonc:
{
"name": "browser-worker",
"main": "src/index.ts",
"compatibility_date": "2023-03-14",
"compatibility_flags": ["nodejs_compat"],
"browser": {
"binding": "MYBROWSER"
}
}
Why nodejs_compat? Browser Rendering requires Node.js APIs and polyfills.
2. Install Puppeteer
npm install @cloudflare/puppeteer
3. Take Your First Screenshot
import puppeteer from "@cloudflare/puppeteer";
interface Env {
MYBROWSER: Fetcher;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const { searchParams } = new URL(request.url);
const url = searchParams.get("url") || "https://example.com";
// Launch browser
const browser = await puppeteer.launch(env.MYBROWSER);
const page = await browser.newPage();
// Navigate and capture
await page.goto(url);
const screenshot = await page.screenshot();
// Clean up
await browser.close();
return new Response(screenshot, {
headers: { "content-type": "image/png" }
});
}
};
4. Deploy
npx wrangler deploy
Test at: https://your-worker.workers.dev/?url=https://example.com
CRITICAL:
- Always pass
env.MYBROWSERtopuppeteer.launch()(not undefined) - Always call
browser.close()when done (or usebrowser.disconnect()for session reuse) - Use
nodejs_compatcompatibility flag
Browser Rendering Overview
What is Browser Rendering?
Cloudflare Browser Rendering provides headless Chromium browsers running on Cloudflare's global network. Use familiar tools like Puppeteer and Playwright to automate browser tasks:
- Screenshots - Capture visual snapshots of web pages
- PDF Generation - Convert HTML/URLs to PDFs
- Web Scraping - Extract content from dynamic websites
- Testing - Automate frontend tests
- Crawling - Navigate multi-page workflows
Two Integration Methods
| Method | Best For | Complexity |
|---|---|---|
| Workers Bindings | Complex automation, custom workflows, session management | Advanced |
| REST API | Simple screenshot/PDF tasks | Simple |
This skill covers Workers Bindings (the advanced method with full Puppeteer/Playwright APIs).
Puppeteer vs Playwright
| Feature | Puppeteer | Playwright |
|---|---|---|
| API Familiarity | Most popular | Growing adoption |
| Package | @cloudflare/puppeteer@1.0.4 | @cloudflare/playwright@1.0.0 |
| Session Management | ✅ Advanced APIs | ⚠️ Basic |
| Browser Support | Chromium only | Chromium only (Firefox/Safari not yet supported) |
| Best For | Screenshots, PDFs, scraping | Testing, frontend automation |
Recommendation: Use Puppeteer for most use cases. Playwright is ideal if you're already using it for testing.
Puppeteer API Reference
puppeteer.launch()
Launch a new browser instance.
Signature:
await puppeteer.launch(binding: Fetcher, options?: LaunchOptions): Promise<Browser>
Parameters:
binding(required) - Browser binding fromenv.MYBROWSERoptions(optional):keep_alive(number) - Keep browser alive for N milliseconds (max: 600000 = 10 minutes)
Returns: Promise<Browser> - Browser instance
Example:
const browser = await puppeteer.launch(env.MYBROWSER, {
keep_alive: 60000 // Keep alive for 60 seconds
});
CRITICAL: Must pass env.MYBROWSER binding. Error "Cannot read properties of undefined (reading 'fetch')" means the binding wasn't passed.
puppeteer.connect()
Connect to an existing browser session.
Signature:
await puppeteer.connect(binding: Fetcher, sessionId: string): Promise<Browser>
Use Cases:
- Reuse existing browser sessions for performance
- Share browser instance across multiple Workers
- Reduce startup time
Example:
const sessionId = "478f4d7d-e943-40f6-a414-837d3736a1dc";
const browser = await puppeteer.connect(env.MYBROWSER, sessionId);
puppeteer.sessions()
List currently running browser sessions.
Signature:
await puppeteer.sessions(binding: Fetcher): Promise<SessionInfo[]>
Returns:
interface SessionInfo {
sessionId: string;
startTime: number;
connectionId?: string; // Present if worker is connected
connectionStartTime?: number;
}
Example:
const sessions = await puppeteer.sessions(env.MYBROWSER);
// Find sessions without active connections
const freeSessions = sessions.filter(s => !s.connectionId);
puppeteer.history()
List recent sessions (both open and closed).
Signature:
await puppeteer.history(binding: Fetcher): Promise<HistoryEntry[]>
Returns:
interface HistoryEntry {
sessionId: string;
startTime: number;
endTime?: number;
closeReason?: number;
closeReasonText?: string; // "NormalClosure", "BrowserIdle", etc.
}
Use Case: Monitor usage patterns and debug session issues.
puppeteer.limits()
Check current account limits and available sessions.
Signature:
await puppeteer.limits(binding: Fetcher): Promise<LimitsInfo>
Returns:
interface LimitsInfo {
activeSessions: Array<{ id: string }>;
maxConcurrentSessions: number;
allowedBrowserAcquisitions: number;
timeUntilNextAllowedBrowserAcquisition: number; // milliseconds
}
Example:
const limits = await puppeteer.limits(env.MYBROWSER);
if (limits.allowedBrowserAcquisitions === 0) {
return new Response("Rate limit reached", { status: 429 });
}
Browser API
Methods available on the Browser object returned by launch() or connect().
browser.newPage()
Create a new page (tab) in the browser.
Signature:
await browser.newPage(): Promise<Page>
Example:
const page = await browser.newPage();
await page.goto("https://example.com");
Performance Tip: Reuse browser instances and open multiple tabs instead of launching new browsers.
browser.sessionId()
Get the current browser session ID.
Returns: string - Session ID
Example:
const sessionId = browser.sessionId();
console.log("Current session:", sessionId);
browser.close()
Close the browser and terminate the session.
Signature:
await browser.close(): Promise<void>
When to use: When you're completely done with the browser and want to free resources.
browser.disconnect()
Disconnect from the browser WITHOUT closing it.
Signature:
await browser.disconnect(): Promise<void>
When to use: Session reuse - allows another Worker to connect to the same session later.
Example:
// Keep session alive for reuse
const sessionId = browser.sessionId();
await browser.disconnect(); // Don't close, just disconnect
// Later: puppeteer.connect(env.MYBROWSER, sessionId)