Skip to content

BrowserRendering

Source: src/Cloudflare/BrowserRendering/BrowserRendering.ts

A Cloudflare Browser Rendering binding for launching headless browser sessions from Workers via @cloudflare/puppeteer.

import puppeteer from "@cloudflare/puppeteer";
import * as Effect from "effect/Effect";
const Browser = Cloudflare.BrowserRendering({ name: "BROWSER" });
Cloudflare.Worker(
"BrowserWorker",
{ main: import.meta.filename },
Effect.gen(function* () {
const browserRendering = yield* Cloudflare.BrowserRendering.bind(
yield* Browser,
);
return {
fetch: browserRendering.withBrowser(puppeteer, (browser) =>
Effect.gen(function* () {
const page = yield* Effect.tryPromise(() => browser.newPage());
yield* Effect.tryPromise(() => page.goto("https://example.com"));
const title = yield* Effect.tryPromise(() => page.title());
return Response.json({ title });
}),
),
};
}).pipe(Effect.provide(Cloudflare.BrowserRenderingBindingLive)),
);
const Browser = yield* Cloudflare.BrowserRendering({ name: "BROWSER" });

Example

export const Worker = Cloudflare.Worker("Worker", {
main: "./src/worker.ts",
bindings: {
BROWSER: Cloudflare.BrowserRendering(),
},
});
export type WorkerEnv = Cloudflare.InferEnv<typeof Worker>;
// { BROWSER: Fetcher }

Async-style worker with the raw runtime binding

import puppeteer from "@cloudflare/puppeteer";
import type { WorkerEnv } from "../alchemy.run.ts";
export default {
async fetch(request: Request, env: WorkerEnv) {
const browser = await puppeteer.launch(env.BROWSER);
const page = await browser.newPage();
await page.goto("https://example.com");
const screenshot = await page.screenshot();
await browser.close();
return new Response(screenshot, {
headers: { "content-type": "image/png" },
});
},
};