Guide ·
How to Take Screenshots with Cloudflare Browser Run (2026)
Browser Run is the new name for Cloudflare Browser Rendering (renamed on April 15, 2026): a headless Chrome on Cloudflare's network that you call with one HTTP request or from a Worker. Below is a request that works, how to tell a real PNG from an error, and what to change when the image comes back blank, cut off or covered.
Disclosure: SnapshotFlow publishes this blog and sells a screenshot API, compared briefly at the end. Cloudflare facts come from its docs and changelog, checked on November 4, 2026.
Quick start: your first screenshot with curl
You need your Account ID from the Cloudflare dashboard and a custom API token with the Browser Run - Edit permission. Then:
This follows Cloudflare's full-page example, with two changes: waitUntil is set to networkidle0 instead of the default domcontentloaded (more on that below), and response headers are saved to headers.txt so you can check the result and the billed browser time. Some Cloudflare examples still use the old /browser-rendering/screenshot path; new code should use /browser-run/.
Check that you got an image, not an error
curl saves whatever comes back to screenshot.png, including a JSON error. Three quick checks:
If the status is not 200 or the content type is JSON, run cat screenshot.png to read the error message. The most common ones are a token without the Browser Run - Edit permission, a quality value sent with PNG (400), and the two kinds of 429 covered in fix it by symptom. Keep the X-Browser-Ms-Used value: you will need it for the cost estimate.
The same screenshot from a Worker
Inside a Worker you do not need an API token. Add a browser binding named BROWSER in wrangler.json, use a compatibility date of 2026-03-24 or later, and call quickAction:
Before you deploy this: a public Worker that screenshots any ?url= lets anyone spend your browser hours. Add authentication and an allowlist of hosts. quickAction also does not run in local development; use npx wrangler dev --remote.
Fix it by symptom
Find what you see in the image or the response, then apply the change. Each snippet is a fragment of the JSON body from the quick start.
A spinner, skeleton or empty dashboard is in the image
The default waitUntil is domcontentloaded, which fires before API data and many images arrive. The most reliable fix is to wait for an element that appears only after the data has loaded, such as a table row or a chart, instead of guessing a delay:
Replace the selector with one from your page. Navigation and selector waits are each capped at 60 seconds. The same problem in Puppeteer is covered in Puppeteer screenshot blank or cut off.
Images at the bottom of a full-page capture are missing
fullPage captures the whole height but does not scroll like a person, so images that load on scroll stay empty. Add scrollPage:
More on lazy loading in full-page screenshots.
400 error after you set quality
PNG is the default and has no quality setting. Set the type too:
WebP is usually the smallest; see WebP screenshots.
429 Too many requests
You sent requests faster than the per-second limit (1 every 10 seconds on Workers Free, 30 per second on Workers Paid). Cloudflare's troubleshooting guide says to read the Retry-After header, wait that long and retry:
For steady volume, queue the captures instead of firing them at once; see our batch screenshot guide.
429 Browser time limit exceeded for today
Different cause, different fix. The Workers Free plan's 10 minutes of browser time per day are used up, and retrying will not help: the error lasts until the next UTC day. Move to Workers Paid to continue sooner, and redeploy your Worker if you just upgraded and still see it.
The same image comes back after the page changed
Identical requests are cached for cacheTTL seconds, 5 by default. For monitoring, pass ?cacheTTL=0 in the URL. For link previews that hit the same page all day, raise it (max 86,400) so you do not re-render every time.
A block page or challenge instead of the site
Browser Run adds headers you cannot remove, including Web Bot Auth signatures, and the docs say changing userAgent does not bypass bot protection. Sites that block automated traffic will block these requests. If the site is yours, Cloudflare suggests a WAF skip rule. See also why some websites blur or block screenshots.
A cookie banner covers the page
There is no single option for this. You hide the banner with CSS and block its script, per consent tool. For example, for a site that uses OneTrust:
That works for sites you know. When the URLs come from your users, see the last section.
Screenshot options cheat sheet
| Goal | Browser Run option | Note |
|---|---|---|
| Full scrollable page | screenshotOptions.fullPage | Add scrollPage for lazy images |
| Viewport and sharpness | viewport.width, height, deviceScaleFactor | Default 1920×1080; use 2 for crisp text |
| Format and quality | screenshotOptions.type (png, jpeg, webp), quality | quality with PNG returns 400 |
| One element | selector | CSS selector |
| Wait for the page | gotoOptions.waitUntil, waitForSelector, waitForTimeout | Default domcontentloaded |
| Logged-in pages | cookies, authenticate, setExtraHTTPHeaders | Basic auth or tokens |
| Block requests | rejectResourceTypes, rejectRequestPattern | Regex patterns |
| Change the page | addStyleTag, addScriptTag | Hide overlays, freeze animations |
| Transparent background | screenshotOptions.omitBackground | Useful with html input |
| Cache | cacheTTL query parameter | Default 5 s, max 86,400 s, 0 disables |
| Keep going on slow events | bestAttempt: true | Continues when awaited events time out |
Browser Run limits in November 2026
| Limit | Workers Free | Workers Paid |
|---|---|---|
| Browser time | 10 minutes per day | 10 hours per month included, then $0.09 per hour |
| Quick Action requests | 1 every 10 seconds | 30 per second |
| Concurrent browsers (sessions only) | 3 | 200 per account (10 included, then $2 each) |
| Navigation timeout | 30 s default, 60 s max | |
| After the daily free limit | 429 until the next UTC day | Not applicable |
These have moved a lot this year: the April rename post raised Workers Paid concurrency from 30 to 120 and mentioned a REST limit increase from 3 to 10 requests per second; the current limits page lists 200 and 30. Paid limits can be raised further on request.
Estimated monthly cost
Quick Actions are billed for browser time only. Cloudflare totals usage in seconds and rounds the month to the nearest hour; requests that fail with a waitForTimeout error are not charged. Browser time depends on the page, so the table uses two scenarios, 5 and 10 seconds per capture. Swap in the X-Browser-Ms-Used value from your own headers: monthly hours = captures × ms ÷ 3,600,000.
| Monthly screenshots | 1,000 | 10,000 | 50,000 |
|---|---|---|---|
| Browser Run, 5 s per capture | $5.00 (1 h, inside 10 included) | $5.36 (14 h) | $10.31 (69 h) |
| Browser Run, 10 s per capture | $5.00 (3 h) | $6.62 (28 h) | $16.61 (139 h) |
| Browser Run, Workers Free | $0, if spread to about 120 a day (estimate at 5 s each) | Not possible | Not possible |
| SnapshotFlow (per successful capture) | $15 (Basic, 2,000 included) | $69 (Growth) | $249 (Scale) |
Workers Paid rows: $5 monthly minimum plus $0.09 per browser hour above 10. Browser Sessions (Puppeteer, Playwright, CDP) also pay for concurrent browsers above 10. SnapshotFlow prices from our pricing page.
For pages that load cleanly, Browser Run costs a fraction of any per-screenshot API, ours included. If that is your workload, it is the better deal.
When the URLs are other people's sites
The picture changes when users paste links to sites you do not control: link previews, competitor monitoring, reports, evidence. Each site uses its own consent tool, overlay and ad stack, and the addStyleTag and rejectRequestPattern rules from the troubleshooting section become a list you maintain per site.
Here is the same page, IKEA Germany's homepage, captured twice with SnapshotFlow on November 4, 2026. The only difference between the two requests is block_cookie_banners=true&block_ads=true. The IKEA logo and product photos are blurred in both images. (We did not run this comparison on Browser Run.)


block_cookie_banners=true: no site-specific selectors.Banner blocking uses Ghostery's cookie lists, so it covers the common consent tools, not every overlay. A fundraising popup or a newsletter modal is not a cookie banner; for those there is hide_selectors. What changes is how much of that list you maintain yourself.
| Browser Run | SnapshotFlow | |
|---|---|---|
| Cookie banners, ads, trackers | Your own CSS and request patterns, per site | block_cookie_banners, block_ads, block_trackers |
| Default wait | domcontentloaded | networkidle2 |
| Text for an LLM with the image | Separate /markdown call, or /snapshot for HTML + screenshot | extract_content=true with response_type=base64: image and Markdown in one JSON |
| Several URLs, background jobs | One request per URL | POST /batch (up to 10), async=true + webhook_url |
| Visual changes between captures | Build it yourself | GET /diff (Growth and Scale) |
| Billing and throughput | Browser time; 30 requests per second | Per successful capture, cache hits free; 40 to 150 per minute |
Pick Browser Run if you are on Workers, capture your own or known pages, or need the lowest bill at volume; for agents that log in and click, compare cloud browsers in Browserbase alternatives. Pick SnapshotFlow if screenshots of third-party sites are a product feature and you would rather not maintain banner rules, batching, webhooks and change detection yourself.
Moving a request over is mostly renaming: screenshotOptions.fullPage → full_page, type → format, viewport.* → width, height, device_scale_factor, waitForSelector → wait_for_selector, addStyleTag → styles or hide_selectors, setExtraHTTPHeaders → headers, cacheTTL=0 → cache=false. The full list is in the API docs.
FAQ
Is Cloudflare Browser Rendering the same as Browser Run?
Yes. Cloudflare renamed Browser Rendering to Browser Run on April 15, 2026. The documented REST path is now /browser-run/screenshot, while some examples and the API reference still use /browser-rendering/. The API token needs the Browser Run - Edit permission.
Is Cloudflare Browser Run free?
There is a free allowance. Workers Free includes 10 minutes of browser time per day and one Quick Action request every 10 seconds; after the daily limit you get a 429 error until the next UTC day. Workers Paid has a $5 monthly minimum, includes 10 browser hours a month and charges $0.09 for each extra hour.
How much does one Browser Run screenshot cost?
Quick Actions are billed by browser time, not per request. If a capture uses 5 seconds of browser time, one browser hour covers 720 captures, so each screenshot beyond the included 10 hours costs about $0.000125. Each response includes an X-Browser-Ms-Used header with the real figure for your page.
Why is my Browser Run screenshot blank or half-loaded?
The default gotoOptions.waitUntil is domcontentloaded, which fires before many images, fonts and client-side data have loaded. Use waitForSelector on an element that appears only after the data loads, or set waitUntil to networkidle0 or networkidle2. For missing images at the bottom of full-page captures, add scrollPage.
How do I fix a 429 error from Browser Run?
There are two kinds. 429 Too many requests means you sent requests too fast: read the Retry-After header, wait that long and retry. 429 Browser time limit exceeded for today means the Workers Free daily limit is used up: it lasts until the next UTC day, or until you move to Workers Paid.
Sources
Checked on November 4, 2026. Cloudflare has changed Browser Run limits several times this year, so confirm before you commit.
- Changelog: Browser Rendering is now Browser Run (April 15, 2026)
- Browser Run /screenshot endpoint and Quick Actions overview
- API reference: screenshot parameters
- Browser Run pricing, limits and 429 troubleshooting and timeouts
- Automatic request headers and bot identification
- Workers pricing
- SnapshotFlow pricing and API docs
Screenshots of third-party sites
Try your URL in the playground
Paste the page that gave you a banner-covered or half-loaded capture and toggle cookie-banner and ad blocking. If the result is what your product needs, the same request runs from your code with 300 free screenshots and no card.
- Cookie-banner, ad and tracker blocking with one parameter each
- PNG, JPEG, WebP or PDF; full page or one element
- Markdown in the same response, batches of 10, webhooks and pixel diffs
- Pay only for successful captures; cache hits are free