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',
},
});
}