{"record":{"id":"d30074d8682162b4","repo":"DIYgod/RSSHub","slug":"browser-run-api-not-available-this-route-requires","errorCode":null,"errorMessage":"Browser Run API not available. This route requires Cloudflare Browser Run which is only available in remote mode. Use `wrangler dev --remote` or deploy to Cloudflare Workers.","messagePattern":"Browser Run API not available\\. This route requires Cloudflare Browser Run which is only available in remote mode\\. Use `wrangler dev --remote` or deploy to Cloudflare Workers\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"lib/utils/playwright.worker.ts","lineNumber":17,"sourceCode":"// Worker-compatible Playwright using Cloudflare Browser Run.\nimport type { Browser, Page } from '@cloudflare/playwright';\nimport { launch } from '@cloudflare/playwright';\n\nimport logger from './logger';\n\ntype GotoOptions = Parameters<Page['goto']>[1];\n\nlet browserBinding: any = null;\n\nexport const setBrowserBinding = (binding: any) => {\n    browserBinding = binding;\n};\n\nconst getBrowserBinding = () => {\n    if (!browserBinding) {\n        throw new Error('Browser Run API not available. This route requires Cloudflare Browser Run which is only available in remote mode. Use `wrangler dev --remote` or deploy to Cloudflare Workers.');\n    }\n    return browserBinding;\n};\n\nconst launchBrowser = async () => {\n    const browser = await launch(getBrowserBinding(), { keep_alive: 60000 });\n    const context = await browser.newContext({\n        ignoreHTTPSErrors: true,\n    });\n    return { browser, context };\n};\n\nconst scheduleClose = (browser: Browser) => {\n    setTimeout(() => {\n        void browser.close();\n    }, 30000);\n};\n","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/utils/playwright.worker.ts#L1-L35","documentation":"playwright.worker.ts lazily resolves a Cloudflare Browser Run binding via getBrowserBinding(); if no binding has been registered with setBrowserBinding it throws. Browser Run only exists when the Worker runs remotely (Cloudflare's edge) because the API is provided by the platform, not by local wrangler.","triggerScenarios":"A route that imports playwright.worker.ts is invoked while `wrangler dev` is running without `--remote`, or in a unit test that never calls setBrowserBinding, or in a deployed Worker whose wrangler.toml lacks the browser binding.","commonSituations":"Local development with `wrangler dev` (default is local); forgetting to add `browser: { binding: \"BROWSER\" }` to wrangler config; running the Worker bundle under miniflare directly without injecting the binding.","solutions":["Run the Worker remotely: `wrangler dev --remote`.","Deploy to Cloudflare Workers where the Browser Run API is available.","Ensure wrangler.toml/wrangler.jsonc declares the browser binding and that setBrowserBinding(env.BROWSER) is called in fetch.","For local tests, inject a fake binding via setBrowserBinding(fake) before exercising the route."],"exampleFix":"// before\nwrangler dev\n// after\nwrangler dev --remote","handlingStrategy":"validation","validationCode":"function isBrowserAvailable(): boolean {\n  return typeof browserBinding !== 'undefined' && browserBinding !== null;\n}\n// before launching\nif (!isBrowserAvailable()) {\n  return new Response('Run with `wrangler dev --remote` or deploy to Workers', { status: 503 });\n}","typeGuard":"const hasBrowserBinding = (env: unknown): env is { BROWSER: unknown } =>\n  !!env && typeof (env as any)?.BROWSER === 'object';","tryCatchPattern":"try {\n  return await launchBrowser();\n} catch (e) {\n  if (/Browser Run API not available/.test((e as Error).message)) {\n    return new Response('Browser Run requires --remote mode', { status: 503 });\n  }\n  throw e;\n}","preventionTips":["Always call setBrowserBinding(env.BROWSER) at the top of fetch when the binding exists.","Standardise on `wrangler dev --remote` for any local work that touches Browser Run.","Declare the browser binding in wrangler config so env.BROWSER is populated in deployed Workers."],"tags":["cloudflare-workers","playwright","browser","wrangler","binding"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}