Fork of Playwright that was modified to be compatible with Cloudflare Workers and Browser Run (formerly Browser Rendering).
🏷️ Upstream Playwright version: 1.58.2
Create a Cloudflare Worker
npm create cloudflare@latest -- cf-playwright-workerThis package is released on npmjs.com at @cloudflare/playwright. To install it in your project:
npm i -s @cloudflare/playwright📄 Place this in wrangler.toml
compatibility_flags = [ "nodejs_compat" ]
browser = { binding = "MYBROWSER" }Browser Run now has full CDP support,
so starting with @cloudflare/playwright version 1.3.0, the library uses the
standard CDP (Chrome DevTools Protocol) internally to communicate with Browser
Run.
Everything should work the same way, but if you encounter any issues, please
report them. You can also
downgrade to a previous playwright version by using compatibility_date prior to
2026-03-17 or by adding the no_websocket_standard_binary_type flag:
compatibility_date = "2026-03-16"# orcompatibility_flags = ["nodejs_compat", "no_websocket_standard_binary_type", ...]See cloudflare/puppeteer#193 and cloudflare/workerd#6442 for details.
You can find a full running example here Cloudflare Playwright running example
import{launch}from'@cloudflare/playwright';exportdefault{asyncfetch(request,env): Promise<Response>{const browser =awaitlaunch(env.MYBROWSER);constpage=awaitbrowser.newPage();awaitpage.goto('https://demo.playwright.dev/todomvc');constTODO_ITEMS=['buy some cheese','feed the cat','book a doctors appointment'];constnewTodo=page.getByPlaceholder('What needs to be done?');for(constitemofTODO_ITEMS){awaitnewTodo.fill(item);awaitnewTodo.press('Enter');}constimg=awaitpage.screenshot();awaitbrowser.close();returnnewResponse(img,{headers: {'Content-Type': 'image/png',},});}}satisfiesExportedHandler<Env>;importfsfrom"fs";import{launch}from"@cloudflare/playwright";exportdefault{asyncfetch(request,env): Promise<Response>{const browser =awaitlaunch(env.MYBROWSER);constpage=awaitbrowser.newPage();awaitpage.context().tracing.start({screenshots: true,snapshots: true});// ... do something, screenshot for example// For now, fs only supports writing into /tmpawaitpage.context().tracing.stop({path: "/tmp/trace.zip"});awaitbrowser.close();constfile=awaitfs.promises.readFile("/tmp/trace.zip");returnnewResponse(file,{status: 200,headers: {"Content-Type": "application/zip",},});}}satisfiesExportedHandler<Env>;import{launch}from"@cloudflare/playwright";import{expect}from"@cloudflare/playwright/test";exportdefault{asyncfetch(request,env): Promise<Response>{const browser =awaitlaunch(env.MYBROWSER);constpage=awaitbrowser.newPage();awaitpage.goto("https://demo.playwright.dev/todomvc");constTODO_ITEMS=["buy some cheese","feed the cat","book a doctors appointment",];constnewTodo=page.getByPlaceholder("What needs to be done?");for(constitemofTODO_ITEMS){awaitnewTodo.fill(item);awaitnewTodo.press("Enter");}awaitexpect(page.getByTestId("todo-title")).toHaveCount(TODO_ITEMS.length);awaitPromise.all(TODO_ITEMS.map((value,index)=>expect(page.getByTestId("todo-title").nth(index)).toHaveText(value)));}}satisfiesExportedHandler<Env>;To build Playwright for Cloudflare:
npm ci
git submodule update --init
cd packages/playwright-cloudflare
npm run buildTo run the TodoMVC example:
- launch it with
wrangler:
cd packages/playwright-cloudflare/examples/todomvc
npm ci
npx wrangler dev --remote- press
bto open the browser
The following capabilities are not fully supported, but we’re actively working on them.
- Playwright Test except Assertions
- Components
- Firefox, Android and Electron, as well as different versions of Chrome
- Videos
This is not an exhaustive list — expect rapid changes as we work toward broader parity with the original feature set. You can also check latest test results for a granular up to date list of the features that are fully supported