Cloudflare Browser Run Keeps Client Jobs on Approved Hosts

Limit client browser jobs to approved hosts, budget for required CDNs, and let reviewers watch through read-only Live View.

Monday, September 14, 2026Omid Saffari
Cloudflare Browser Run Keeps Client Jobs on Approved Hosts

On September 14, 2026, Cloudflare Browser Run added two controls that change how you can deliver browser automation to a client: a session can stay inside an approved hostname list, and a reviewer can watch through Live View without getting interactive control. You can name up to 50 hostnames directly or attach up to four shared domain sets, but the useful part is the operating boundary, not the size of the list.

The change is two boundaries, not one

A Browser Run session is a remote Chrome instance. Your code drives it with Puppeteer, Playwright, or Chrome DevTools Protocol, usually called CDP.

The new session guardrails decide which destination hostnames that browser may request over HTTP or HTTPS. The policy is fixed when the session starts and stays in force for that session's lifetime.

The new read-only setting for Live View does a different job. It decides what one person using one generated viewing link may do. A read-only viewer can see the session, but can't navigate, type, click, or evaluate JavaScript.

BoundaryWhat it controlsScopeWhat it does not promise
Session guardrailHTTP and HTTPS destination hostnamesThe whole browser sessionA universal network sandbox beyond the documented HTTP and HTTPS boundary
Read-only Live ViewNavigation, input, and JavaScript evaluationOne generated viewer connectionRead-only control for your automation or for other connections to the session

That distinction matters. The automation still controls the browser. The reviewer only observes it. At the same time, the browser's HTTP and HTTPS requests stay inside the session allowlist, no matter which Live View connection is open.

Architectural cutaway of a guarded Browser Run session reaching an approved site and asset host while a reviewer watches from a read-only booth
The hostname boundary belongs to the session. The read-only boundary belongs to one viewer connection.

This turns browser work into a client review workflow

Imagine an agency generating a report inside a client's web app. The browser needs the client's main hostname, an authentication hostname, an API, a font host, and perhaps an image CDN. The client also wants to see the run before approving the output.

You can now handle those as two separate decisions:

  1. The technical owner approves the destinations the session needs.
  2. The client receives a view-only Live View URL and watches the job run.

The reviewer doesn't receive an interactive browser. The job doesn't receive an open destination list. That is a cleaner handoff than treating one shared browser link as both a demonstration tool and an access-control decision.

It is still not a complete security system. Cloudflare documents hostname controls for HTTP and HTTPS requests, so don't describe this as a general-purpose network sandbox. A Live View URL also contains a signed JWT, which means the complete URL is a credential. Read-only removes interaction, but it still exposes whatever appears on the page.

The real work is maintaining the asset list

The obvious hostname is rarely the whole page.

A production page may redirect during login, call a separate API, load scripts from one host, images from another, and fonts from a third. Cloudflare tells you to include all of those dependencies. Miss one and the browser gets a 403 for that request, with cf-mitigated: guardrails and cf-brapi-guardrails-reason: not-in-allowlist in the response headers.

That makes allowlist upkeep a real delivery cost. Every client redesign, identity-provider change, analytics swap, or CDN move can become a policy change and a new validation run. There is no honest universal labor number for that work. You should measure it on your own jobs.

Cloudflare gives you two ways to carry the list:

  • allowedDomains is the direct option, with up to 50 hostname patterns in the session launch call.
  • allowedDomainSets accepts up to four shared lists. Those can include Cloudflare's common-cdns set or HTTPS URLs that return a plain-text hostname list.

The shared list is useful when many client jobs need the same approved services. It also has timing rules. Cloudflare caches a hosted list for up to one hour, and an update affects only sessions started after the refreshed list is read. A running session never changes policy underneath you.

There is another trade-off in common-cdns: Cloudflare maintains it and may change it over time. That saves list maintenance, but it is not a fixed allowlist. If a contract or audit requires a stable set of destinations, use explicit hostnames or your own hosted list.

Four teams that can use this now

An agency technical lead can separate approval from control

Allow the client's app and its required dependencies, run the browser job, then generate a read-only Live View link for the account lead or client reviewer. They can watch the evidence appear without clicking into the app or changing the run. The payoff is a review step that doesn't quietly become an operator handoff.

A SaaS founder can make a self-contained PDF stay self-contained

If you already generate a screenshot or PDF from trusted inline HTML, launch the session with an empty allowedDomains array and no domain sets. The HTML still renders, but it cannot fetch an external API, script, image, or font over HTTP or HTTPS. The payoff is a simpler claim you can test: this render did not request outside web content.

This specific control is not available on Quick Actions, including the shortcut endpoints people often use for screenshots and PDFs. You need a Browser Session through Puppeteer, Playwright, or CDP to use it.

A platform team can own one dependency policy

Host a plain-text list over HTTPS, place one hostname pattern on each line, and reference that URL through allowedDomainSets. Multiple session launchers can use the same list. The payoff is one maintenance point, with the important rule that one invalid line rejects the entire hosted list.

A security reviewer can ask for a failing test

Don't stop at showing the configuration. Attempt one request to a hostname that is not allowed, then save the 403 status and the two guardrail headers with the review record. The payoff is evidence that the negative path worked, not a screenshot of an object that looked correct.

Set up one guarded review session

This is a technical walk because the feature lives at session creation. The code below is taken from the Cloudflare pages read for this piece.

  1. Install a compatible client and bind the browser

    Cloudflare requires @cloudflare/puppeteer 1.4.0 or later for guardrails. Its Puppeteer install command is:

    Bash
    npm i -D @cloudflare/puppeteer

    Your Worker also needs a browser binding. Cloudflare's Wrangler example names it MYBROWSER:

    Jsonc
    {
    	"$schema": "./node_modules/wrangler/config-schema.json",
    	"name": "browser-rendering",
    	"main": "src/index.ts",
    	"workers_dev": true,
    	"compatibility_flags": ["nodejs_compat_v2"],
    	"browser": {
    		"binding": "MYBROWSER"
    	}
    }

    Check the installed package version. The older Puppeteer overview still labels 1.1.0 as current, but the newer guardrails page requires 1.4.0 or later. Follow the feature requirement.

  2. Launch with the destination policy

    Cloudflare's guarded Puppeteer example permits the apex domain, its subdomains, and the shared common-cdns set:

    JavaScript
    import puppeteer from "@cloudflare/puppeteer";
    
    export async function startGuardedSession(env) {
    	const browser = await puppeteer.launch(env.MYBROWSER, {
    		guardrails: {
    			allowedDomains: ["example.com", "*.example.com"],
    			allowedDomainSets: ["common-cdns"],
    		},
    	});
    
    	return browser;
    }

    Replace the example values only after inventorying the page's redirects, APIs, scripts, images, and fonts. Notice that *.example.com does not include example.com, which is why both entries appear.

  3. Prove an unapproved host is blocked

    Request one hostname outside the list. The expected result is HTTP 403 with cf-mitigated: guardrails and cf-brapi-guardrails-reason: not-in-allowlist. Also test the approved page through its complete login and render path. A negative test proves the boundary; a positive test proves the job still works.

  4. Generate a view-only review link

    With the session ID available, Cloudflare's REST example creates a tab view whose viewer cannot interact:

    Bash
    curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/browser-rendering/devtools/browser/$SESSION_ID/live_view" \
    	--request POST \
    	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
    	--json '{
    		"mode": "tab",
    		"guardrails": {
    			"mode": "readonly"
    		}
    	}'

    Generate this URL in trusted server-side code and share it through a trusted channel. The default connection-start deadline is five minutes. You can set expiresInMs as low as 60,000 milliseconds or as high as 3,600,000 milliseconds, which is one hour.

The repeated word guardrails can be confusing here. In the session launch, it carries allowedDomains and controls destinations. In the Live View URL request, it carries mode: readonly and controls that viewer. You need both settings if you want both boundaries.

The feature can move a job onto a different bill

Cloudflare's current Browser Run pricing has no separate line for each allowlist entry. The money moves when your integration method changes.

Quick Actions are billed for browser hours only, but they cannot use these guardrails. Browser Sessions can use guardrails, and they are billed for browser hours plus concurrent browsers. If a shortcut PDF or screenshot workflow now needs hostname restrictions, moving it to Puppeteer, Playwright, or CDP changes both the implementation and the cost model.

On Workers Paid, the included usage is 10 browser hours per month and 10 concurrent browsers. Extra browser time is $0.09 per hour. Extra concurrency is $2.00 per browser, based on the monthly average of each day's peak.

The useful planning formula is:

extra usage cost = max(0, browser hours - 10) × $0.09 + max(0, average daily peak browsers - 10) × $2.00

Cloudflare's own example uses 50 browser hours and an average of 15 concurrent browsers. That produces $3.60 for 40 extra hours, plus $10.00 for five extra browsers, or $13.60 in extra usage charges. That is not a guardrail fee. It is the Browser Session bill attached to the path that supports guardrails.

Workers Free includes 10 browser minutes per day and three concurrent browsers. That can cover a small proof, but it is not much room for a client workflow with repeated review runs.

If you already use Browser Sessions, the billing categories do not change. Your new cost is mostly operational: collecting asset hosts, testing blocked and permitted paths, and keeping the list current. If you are still comparing managed browser approaches, the broader agent-browser guide puts those usage lines in context.

Where this still breaks

The easiest failure is a page that works in development and loses a font, image, login redirect, or API call after the allowlist goes live. A broad wildcard can make that failure disappear while weakening the boundary you meant to create.

Cloudflare allows one wildcard per hostname pattern. Prefer *.example.com for subdomains and list the apex separately. A prefix pattern such as *example.com can also match a lookalike such as evilexample.com, so it is the wrong shortcut for a tight client policy.

Read-only Live View has its own limit. It protects one viewer connection, not the session from its operator, and not another connection from controlling it. Puppeteer and Playwright cannot drive the read-only connection because the required commands are blocked. That is useful for a reviewer and useless as an automation credential, exactly as it should be.

Quick Actions and Kitesurf remain outside the guardrails feature. Teams using either one are unaffected until they decide the hostname boundary is worth changing integration paths.

The Monday move

Pick one real client job with a stable destination set. Don't start with your messiest login flow.

Inventory every hostname used by the successful path, including redirects and asset hosts. Launch a guarded Browser Session, confirm the intended output, then deliberately request one unapproved hostname and save the 403 evidence. Finally, give a teammate a read-only Live View link and confirm they can watch but not interact.

Record four things from that pilot: the required hostname count, the time spent maintaining it, the number of legitimate requests you initially blocked, and the average concurrent-browser peak. Those four values tell you whether this is a clean control or an expensive promise for that workflow.

Act this week if you deliver browser jobs to clients, the required hosts are knowable, and observation without control solves a real approval problem. Wait if your dependencies change constantly or your job still lives on Quick Actions and you have not priced the Browser Session move. If you do not run Browser Sessions or share live browser work, this release does not change your Monday.

If you want more operator-level explanations of platform changes, join the newsletter.

Last Updated
Sep 14, 2026
Category
Explained

Prefer this site in Google

Add omidsaffari.com as a preferred source in Google Search

Mark omidsaffari.com as preferred and Google lifts it in Top Stories, AI Overviews and AI Mode for you.

GPT-Live-1 Changes the Budget for AI Phone Calls

GPT-Live-1 Changes the Budget for AI Phone Calls

Understand GPT-Live-1 phone-agent costs: the voice layer, backend reasoning, telephony, and the interruption handling worth testing.Sep 14, 2026Explained
ChatGPT Appshots Cut Context Copying on Windows

ChatGPT Appshots Cut Context Copying on Windows

Use ChatGPT Appshots on Windows to share an app window, reduce context copying, and check what text and images enter the chat.Sep 14, 2026Explained
Vercel FastAPI Cuts Function Use for Static Files

Vercel FastAPI Cuts Function Use for Static Files

Vercel now serves eligible FastAPI assets from its CDN. See which requests stop using Functions and which protected paths still need them.Sep 13, 2026Explained
OpenAI API Key Expiry Needs a Rotation Plan

OpenAI API Key Expiry Needs a Rotation Plan

OpenAI now lets teams expire project API keys. Plan replacement and verification before scheduled agents lose access.Sep 13, 2026Explained
Vercel Connect Gives Shared Credentials a Clear Owner

Vercel Connect Gives Shared Credentials a Clear Owner

Vercel Connect lets Pro and Enterprise teams restrict connector management. See how to assign owners and keep agent setup moving.Sep 13, 2026Explained
Cloudflare AI Search Can Index R2 Files Without Renaming

Cloudflare AI Search Can Index R2 Files Without Renaming

Cloudflare AI Search now indexes extensionless R2 files with valid Content-Type metadata. See which ingestion steps you can remove.Sep 12, 2026Explained
Vercel Sandbox Gives Larger Agent Jobs More Disk Room

Vercel Sandbox Gives Larger Agent Jobs More Disk Room

See which repository, build, and data jobs fit Vercel Sandbox’s larger disk, plus what to measure before retrying a storage-heavy agent run.Sep 12, 2026Explained
Cloudflare Workflows: Budget for Shorter Run History

Cloudflare Workflows: Budget for Shorter Run History

New Paid Workflows keep completed and errored state for seven days by default. Set retention before old failures disappear.Sep 11, 2026Explained
Newsletter

One letter, every Sunday.Working systems, not hot takes.

Weekly. No spam. Unsubscribe anytime.