Skip to main content

Cloudflare Browser Rendering Usage Guide [To Be Updated]

Introduction

I've accumulated some knowledge while learning Cloudflare Browser Rendering. Source: Puppeteer

For more knowledge about cloudflare + puppeteer, see this docs/api/puppeteer.page.md

Get Page Load Metrics and Return as JSON

import puppeteer from "@cloudflare/puppeteer";

export default {
async fetch(request, env) {
const browser = await puppeteer.launch(env.MYBROWSER);
const page = await browser.newPage();
await page.goto("https://example.com");
const metrics = await page.metrics();
await browser.close();
return Response.json(metrics);
},
};

Keep Alive

If the user omits the browser.close() statement, it will remain open, ready to connect again and be reused, but by default it will automatically close after 1 minute of inactivity.

Users can optionally extend this idle time up to 10 minutes using the keep_alive option (set in milliseconds):

const browser = await puppeteer.launch(env.MYBROWSER, { keep_alive: 600000 });

With the above, the browser will stay open for up to 10 minutes, even when inactive.

Session Management

Get Open Sessions

puppeteer.sessions() lists currently running sessions. It will return output similar to:

[
{
"connectionId": "2a2246fa-e234-4dc1-8433-87e6cee80145",
"connectionStartTime": 1711621704607,
"sessionId": "478f4d7d-e943-40f6-a414-837d3736a1dc",
"startTime": 1711621703708
},
{
"sessionId": "565e05fb-4d2a-402b-869b-5b65b1381db7",
"startTime": 1711621703808
}
]

Note that session 478f4d7d-e943-40f6-a414-837d3736a1dc has an active Worker connection (connectionId=2a2246fa-e234-4dc1-8433-87e6cee80145),

while session 565e05fb-4d2a-402b-869b-5b65b1381db7 is idle. When a connection is active, other workers cannot connect to that session.

Get Recent Sessions

puppeteer.history() lists recent sessions, including open and closed ones. Useful for understanding your current usage.

[
{
"closeReason": 2,
"closeReasonText": "BrowserIdle",
"endTime": 1711621769485,
"sessionId": "478f4d7d-e943-40f6-a414-837d3736a1dc",
"startTime": 1711621703708
},
{
"closeReason": 1,
"closeReasonText": "NormalClosure",
"endTime": 1711123501771,
"sessionId": "2be00a21-9fb6-4bb2-9861-8cd48e40e771",
"startTime": 1711123430918
}
]

Session 2be00a21-9fb6-4bb2-9861-8cd48e40e771 was explicitly closed by the client using browser.close(), while session 478f4d7d-e943-40f6-a414-837d3736a1dc was closed due to reaching maximum idle time (check limits).

You should also be able to access this information in the dashboard, though with a slight delay.

Active Limits

puppeteer.limits() lists your active limits:

{
"activeSessions": [
"478f4d7d-e943-40f6-a414-837d3736a1dc",
"565e05fb-4d2a-402b-869b-5b65b1381db7"
],
"allowedBrowserAcquisitions": 1,
"maxConcurrentSessions": 2,
"timeUntilNextAllowedBrowserAcquisition": 0
}
  • activeSessions lists IDs of currently open sessions
  • maxConcurrentSessions defines how many browsers can be open simultaneously
  • allowedBrowserAcquisitions specifies whether a new browser session can be opened based on existing rate limits
  • timeUntilNextAllowedBrowserAcquisition defines the wait time before a new browser can be started.

Fetch HTML Content

Code: browser-worker

Usage: https://xxx.com/?url=https://runnable.run

import puppeteer from "@cloudflare/puppeteer";

export default {
async fetch(request, env) {
const { searchParams } = new URL(request.url);
let url = searchParams.get("url");

const browser = await puppeteer.launch(env.MYBROWSER);
const page = await browser.newPage();
await page.goto(url);
const pageHtml = await page.content();
await browser.close();
return new Response(pageHtml, {
headers: {
'Content-Type': 'text/html'
},
});
},
};


async function handleRequest(request, env){
const { searchParams } = new URL(request.url);
let url = searchParams.get("url");

const browser = await puppeteer.launch(env.MYBROWSER);
const page = await browser.newPage();
await page.goto(url);
const pageHtml = await page.content();
await browser.close();
return new Response(pageHtml, {
headers: {
'Content-Type': 'text/html',
},
});
}