Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Comprehensive Cloudflare platform skill covering Workers, D1, R2, KV, AI, Durable Objects, and security.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/browser-rendering/patterns.md
1# Browser Rendering Patterns23## Basic Worker45```typescript6import puppeteer from "@cloudflare/puppeteer";78export default {9async fetch(request, env) {10const browser = await puppeteer.launch(env.MYBROWSER);11try {12const page = await browser.newPage();13await page.goto("https://example.com");14return new Response(await page.content());15} finally {16await browser.close(); // ALWAYS in finally17}18}19};20```2122## Session Reuse2324Keep sessions alive for performance:25```typescript26let sessionId = await env.SESSION_KV.get("browser-session");27if (sessionId) {28browser = await puppeteer.connect(env.MYBROWSER, sessionId);29} else {30browser = await puppeteer.launch(env.MYBROWSER, { keep_alive: 600000 });31await env.SESSION_KV.put("browser-session", browser.sessionId(), { expirationTtl: 600 });32}33// Don't close browser to keep session alive34```3536## Common Operations3738| Task | Code |39|------|------|40| Screenshot | `await page.screenshot({ type: "png", fullPage: true })` |41| PDF | `await page.pdf({ format: "A4", printBackground: true })` |42| Extract data | `await page.evaluate(() => document.querySelector('h1').textContent)` |43| Fill form | `await page.type('#input', 'value'); await page.click('button')` |44| Wait nav | `await Promise.all([page.waitForNavigation(), page.click('a')])` |4546## Parallel Scraping4748```typescript49const pages = await Promise.all(urls.map(() => browser.newPage()));50await Promise.all(pages.map((p, i) => p.goto(urls[i])));51const titles = await Promise.all(pages.map(p => p.title()));52```5354## Playwright Selectors5556```typescript57import { launch } from "@cloudflare/playwright";58const browser = await launch(env.MYBROWSER);59await page.getByRole("button", { name: "Sign in" }).click();60await page.getByLabel("Email").fill("[email protected]");61await page.getByTestId("submit-button").click();62```6364## Incognito Contexts6566Isolated sessions without multiple browsers:67```typescript68const ctx1 = await browser.createIncognitoBrowserContext();69const ctx2 = await browser.createIncognitoBrowserContext();70// Each has isolated cookies/storage71```7273## Quota Check7475```typescript76const limits = await puppeteer.limits(env.MYBROWSER);77if (limits.remaining < 60000) return new Response("Quota low", { status: 429 });78```7980## Error Handling8182```typescript83try {84await page.goto(url, { timeout: 30000, waitUntil: "networkidle0" });85} catch (e) {86if (e.message.includes("timeout")) return new Response("Timeout", { status: 504 });87if (e.message.includes("Session limit")) return new Response("Too many sessions", { status: 429 });88} finally {89if (browser) await browser.close();90}91```92