DIYgod/RSSHub · critical · Error
Browser Run API not available. This route requires Cloudflar
Error message
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.
What it means
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.
Source
Thrown at lib/utils/playwright.worker.ts:17
// Worker-compatible Playwright using Cloudflare Browser Run.
import type { Browser, Page } from '@cloudflare/playwright';
import { launch } from '@cloudflare/playwright';
import logger from './logger';
type GotoOptions = Parameters<Page['goto']>[1];
let browserBinding: any = null;
export const setBrowserBinding = (binding: any) => {
browserBinding = binding;
};
const getBrowserBinding = () => {
if (!browserBinding) {
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.');
}
return browserBinding;
};
const launchBrowser = async () => {
const browser = await launch(getBrowserBinding(), { keep_alive: 60000 });
const context = await browser.newContext({
ignoreHTTPSErrors: true,
});
return { browser, context };
};
const scheduleClose = (browser: Browser) => {
setTimeout(() => {
void browser.close();
}, 30000);
};
View on GitHub (pinned to bed535e087)
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.
Example fix
// before wrangler dev // after wrangler dev --remote
Defensive patterns
Strategy: validation
Validate before calling
function isBrowserAvailable(): boolean {
return typeof browserBinding !== 'undefined' && browserBinding !== null;
}
// before launching
if (!isBrowserAvailable()) {
return new Response('Run with `wrangler dev --remote` or deploy to Workers', { status: 503 });
} Type guard
const hasBrowserBinding = (env: unknown): env is { BROWSER: unknown } =>
!!env && typeof (env as any)?.BROWSER === 'object'; Try / catch
try {
return await launchBrowser();
} catch (e) {
if (/Browser Run API not available/.test((e as Error).message)) {
return new Response('Browser Run requires --remote mode', { status: 503 });
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Bilibili browser mode did not receive a video list response
- Bilibili browser mode returned unexpected video list API sta
- Bilibili browser mode returned non-JSON response with status
- Got error code ${data.code} while fetching in browser mode:
- No response received from ${apiUrl}
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/d30074d8682162b4.
Report an issue: GitHub.