Puppeteer
Puppeteer ↗ is one of the most popular libraries that abstract the lower-level DevTools protocol from developers and provides a high-level API that you can use to easily instrument Chrome/Chromium and automate browsing sessions. Puppeteer is used for tasks like creating screenshots, crawling pages, and testing web applications.
Puppeteer typically connects to a local Chrome or Chromium browser using the DevTools port. Refer to the Puppeteer API documentation on the Puppeteer.connect() method ↗ for more information.
The Workers team forked a version of Puppeteer and patched it to connect to the Workers Browser Rendering API instead. After connecting, the developers can then use the full Puppeteer API ↗ as they would on a standard setup.
Our version is open sourced and can be found in Cloudflare's fork of Puppeteer ↗. The npm can be installed from npmjs ↗ as @cloudflare/puppeteer ↗:
npm i -D @cloudflare/puppeteeryarn add -D @cloudflare/puppeteerpnpm add -D @cloudflare/puppeteerOnce the browser binding is configured and the @cloudflare/puppeteer library is installed, Puppeteer can be used in a Worker:
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); },};import puppeteer from "@cloudflare/puppeteer";
interface Env { MYBROWSER: Fetcher;}
export default { async fetch(request, env): Promise<Response> { 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); },} satisfies ExportedHandler<Env>;This script launches ↗ the env.MYBROWSER browser, opens a new page ↗, goes to ↗ https://example.com/ ↗, gets the page load metrics ↗, closes ↗ the browser and prints metrics in JSON.
If users omit the browser.close() statement, it will stay open, ready to be connected to again and re-used but it will, by default, close automatically after 1 minute of inactivity. Users can optionally extend this idle time up to 10 minutes, by using the keep_alive option, set in milliseconds:
const browser = await puppeteer.launch(env.MYBROWSER, { keep_alive: 600000 });Using the above, the browser will stay open for up to 10 minutes, even if inactive.
To specify a custom user agent in Puppeteer, use the page.setUserAgent() method. This is useful if the target website serves different content based on the user agent.
await page.setUserAgent( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36");Puppeteer provides multiple methods for selecting elements on a page. While CSS selectors work as expected, XPath selectors are not supported due to security constraints in the Workers runtime.
Instead of using Xpath selectors, you can use CSS selectors or page.evaluate() to run XPath queries in the browser context:
const innerHtml = await page.evaluate(() => { return ( // @ts-ignore this runs on browser context new XPathEvaluator() .createExpression("/html/body/div/h1") // @ts-ignore this runs on browser context .evaluate(document, XPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue .innerHTML );});In order to facilitate browser session management, we've added new methods to puppeteer:
puppeteer.sessions() lists the current running sessions. It will return an output similar to this:
[ { "connectionId": "2a2246fa-e234-4dc1-8433-87e6cee80145", "connectionStartTime": 1711621704607, "sessionId": "478f4d7d-e943-40f6-a414-837d3736a1dc", "startTime": 1711621703708 }, { "sessionId": "565e05fb-4d2a-402b-869b-5b65b1381db7", "startTime": 1711621703808 }]Notice that the 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 free. While a connection is active, no other workers may connect to that session.
puppeteer.history() lists recent sessions, both open and closed. It's useful to get a sense of 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 closed explicitly with browser.close() by the client, while session 478f4d7d-e943-40f6-a414-837d3736a1dc was closed due to reaching the maximum idle time (check limits).
You should also be able to access this information in the dashboard, albeit with a slight delay.
puppeteer.limits() lists your active limits:
{ "activeSessions": [ { "id": "478f4d7d-e943-40f6-a414-837d3736a1dc" }, { "id": "565e05fb-4d2a-402b-869b-5b65b1381db7" } ], "allowedBrowserAcquisitions": 1, "maxConcurrentSessions": 2, "timeUntilNextAllowedBrowserAcquisition": 0}activeSessionslists the IDs of the current open sessionsmaxConcurrentSessionsdefines how many browsers can be open at the same timeallowedBrowserAcquisitionsspecifies if a new browser session can be opened according to the rate limits in placetimeUntilNextAllowedBrowserAcquisitiondefines the waiting period before a new browser can be launched.
The full Puppeteer API can be found in the Cloudflare's fork of Puppeteer ↗.
Was this helpful?
- Resources
- API
- New to Cloudflare?
- Directory
- Sponsorships
- Open Source
- Support
- Help Center
- System Status
- Compliance
- GDPR
- Company
- cloudflare.com
- Our team
- Careers
- © 2025 Cloudflare, Inc.
- Privacy Policy
- Terms of Use
- Report Security Issues
- Trademark