ScreenshotNeo

BlogComparisons

Cloudflare Browser Rendering vs. a Screenshot API

Compare Cloudflare Browser Run with dedicated screenshot APIs, including code, options, costs, troubleshooting, and when ScreenshotNeo fits best.

By the ScreenshotNeo team29 September 20269 min read

Cloudflare Browser Rendering vs. a Screenshot API

Short answer: Cloudflare Browser Run (formerly Browser Rendering) is a hosted browser platform. Its Screenshot Quick Action is designed for stateless captures, while Browser Sessions let you control a browser with Puppeteer, Playwright, CDP, or Stagehand. A dedicated screenshot API is narrower: you send a URL or HTML document and receive an image or PDF. Choose Cloudflare when you need browser automation and session control. Choose a screenshot API when capture is the main job and you want a simple HTTP integration.

For a dedicated screenshot API, ScreenshotNeo is the first service to try: it removes consent banners and other page clutter, bills only clean captures, and has a $5 paid plan after 1,000 free monthly shots.

What Cloudflare Browser Run provides

Cloudflare currently calls the product Browser Run, although documentation and endpoint paths still use “Browser Rendering.” The product has two integration styles:

  • Quick Actions: stateless tasks such as screenshots, PDFs, and scraping.
  • Browser Sessions: direct browser control through Puppeteer, Playwright, CDP, or Stagehand.

The screenshot Quick Action accepts a URL or supplied HTML. The REST API requires a token with Browser Rendering Edit/Write permission. Cloudflare Workers can call the capability through a Workers Binding instead of storing an API token in application code. The screenshot API documents viewport settings, full-page output, selector capture, navigation behavior, wait conditions, waitForSelector, waitForTimeout, and actionTimeout. The reviewed API reference sets the maximum action timeout at 120,000 milliseconds.

Cloudflare’s own guide summarizes Quick Actions as “Simple, stateless browser tasks like screenshots, PDFs, and scraping.” Read the Browser Run getting-started guide and the screenshot endpoint reference before deploying because permissions, schemas, and account limits can change.

What a dedicated screenshot API provides

A dedicated service packages the browser behind a request such as “render this URL at this viewport and return WebP.” You normally do not manage a browser process, navigation loop, or screenshot storage. This model works well for:

A screenshot workflow turns a URL request into rendered image bytes.
A screenshot workflow turns a URL request into rendered image bytes.
  • Generating social cards, report thumbnails, and preview images.
  • Taking scheduled screenshots of many pages.
  • Rendering a page from a backend job or CI pipeline.
  • Producing PDFs or images without adding Playwright or Puppeteer to your deployment.

ScreenshotOne documents GET and POST requests, full-page screenshots, HTML rendering, PDF output, and caching. screenshot-api.net documents a single GET request that returns image bytes. Their published plans and limits are commercial terms, not independent benchmarks: ScreenshotOne lists up to 100 screenshots per month free and a Basic plan of $17 per month for 2,000 screenshots with a stated 40 requests per minute; screenshot-api.net advertises 100 free renders per month. Recheck those pages before publication.

Decision table

Requirement Better fit Reason
One URL to one image Screenshot API The integration is a single HTTP request and response.
Login flows, clicks, forms, or multiple pages Browser Sessions You need a programmable browser rather than a stateless capture.
Full-page or CSS selector capture Either Cloudflare documents both; dedicated APIs vary by provider.
Worker-native deployment Cloudflare Workers Bindings avoid a separate REST client.
Clean marketing screenshots ScreenshotNeo Consent banners, newsletter popups, and chat widgets are removed before capture.
Transparent billing for failed pages ScreenshotNeo Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed.

Cloudflare screenshot Quick Action: implementation

The REST request is a JSON POST. Store the account ID and API token in environment variables. The endpoint path below follows Cloudflare’s Browser Rendering API shape; use the current endpoint reference for your account and permissions.

cURL

curl -sS -X POST \
  "https://api.cloudflare.com/client/v4/accounts/$CF_ACCOUNT_ID/browser-rendering/screenshot" \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "url": "https://example.com",
    "viewport": {"width": 1440, "height": 900},
    "fullPage": true,
    "waitForTimeout": 1000
  }' \
  -o page.png

Check the HTTP status and response content type in production. An API error may be JSON rather than an image, so do not blindly save every response as a PNG.

Python

import os
import requests

endpoint = (
    f"https://api.cloudflare.com/client/v4/accounts/"
    f"{os.environ['CF_ACCOUNT_ID']}/browser-rendering/screenshot"
)
payload = {
    "url": "https://example.com",
    "viewport": {"width": 1440, "height": 900},
    "fullPage": True,
    "waitForTimeout": 1000,
}
response = requests.post(
    endpoint,
    headers={
        "Authorization": f"Bearer {os.environ['CF_API_TOKEN']}",
        "Content-Type": "application/json",
    },
    json=payload,
    timeout=130,
)
response.raise_for_status()
content_type = response.headers.get("content-type", "")
if "image" not in content_type:
    raise RuntimeError(f"Expected an image, got {content_type}: {response.text[:500]}")
with open("page.png", "wb") as output:
    output.write(response.content)

Node.js

const endpoint = `https://api.cloudflare.com/client/v4/accounts/${process.env.CF_ACCOUNT_ID}/browser-rendering/screenshot`;
const response = await fetch(endpoint, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.CF_API_TOKEN}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    url: 'https://example.com',
    viewport: { width: 1440, height: 900 },
    fullPage: true,
    waitForTimeout: 1000
  })
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
const type = response.headers.get('content-type') || '';
if (!type.includes('image')) throw new Error(`Unexpected content type: ${type}`);
const fs = await import('node:fs/promises');
await fs.writeFile('page.png', Buffer.from(await response.arrayBuffer()));

Important capture options

Viewport and full-page mode

Set viewport width and height explicitly for repeatable output. Use full-page mode when the page height matters, such as documentation or invoices. Full-page captures can be large; prefer a fixed viewport for cards and thumbnails.

Selector capture

Selector capture is useful when you need one chart, article, or product card instead of the entire document. Make sure the selector exists after client-side rendering. A missing selector should be treated as a page failure in your job queue, not as a valid empty image.

Waiting for page readiness

Static navigation completion does not guarantee that a chart or image is ready. Use waitForSelector for a known element, waitForTimeout for a short deterministic delay, or the documented navigation and network behavior when the application needs more time. Keep waits bounded. Cloudflare’s API reference documents a maximum actionTimeout of 120,000 ms.

URL versus HTML

Use a URL when the browser should load an existing page. Use supplied HTML for a self-contained report or template. With HTML, include the CSS and assets needed for the render; external resources can still fail because of authentication, CSP, or network policy.

Browser Sessions versus Quick Actions

Use a Quick Action when each request is independent: open one page, wait for readiness, capture, and finish. Use a Browser Session when you need state across actions. A session can perform a sequence such as open login page, fill credentials, submit, navigate to a report, and capture a chart. That flexibility adds lifecycle management, retries, cleanup, and more opportunities for browser-specific failures.

A dedicated screenshot API is usually the simpler operational boundary for URL-to-image work. You can put it behind a queue, retry failed requests, and store the returned bytes without shipping a browser runtime in your service.

Or skip the browser setup

ScreenshotNeo provides a one-request screenshot API and an MCP server for Claude, Cursor, and other MCP clients. Before capture, it accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets. Each step can be disabled. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and whether the request was billed.

Consent dialogs and overlays can change the usefulness of an automated capture.
Consent dialogs and overlays can change the usefulness of an automated capture.

It also supports full-page capture with lazy images loaded, CSS selector capture, dark mode, 12 device presets plus custom viewports, retina scale, PDF options, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, selectable cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture of 100 URLs per call, a usage API, and an OpenAPI specification. Parameter names used by other screenshot APIs also work, which can simplify migration. See the ScreenshotNeo API documentation.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

The Free plan includes 1,000 shots each month with no card. Paid plans start at $5 for 3,000 shots; yearly billing gives two months free, and every feature is available on every plan. Create a free ScreenshotNeo account.

Reliability, performance, and cost

  • Bound the work: set a timeout below your platform’s request limit and cancel abandoned jobs.
  • Retry selectively: retry network failures and transient 5xx responses; do not retry authentication errors or a consistently missing selector.
  • Cache deterministic pages: use a cache key containing URL, viewport, device, color scheme, and relevant options. ScreenshotNeo lets you choose a cache TTL.
  • Control image size: full-page and retina captures consume more bandwidth and storage. Resize when the destination does not need source resolution.
  • Measure billable work: Cloudflare account limits and pricing depend on the current account terms. ScreenshotOne and screenshot-api.net publish their own quotas. ScreenshotNeo exposes X-Page-Verdict and X-Billed headers so your usage system can distinguish clean captures from non-billable outcomes.
  • Queue bursts: bulk jobs should use a bounded worker pool. Respect the provider’s current rate limits instead of assuming parallel requests are unlimited.

Troubleshooting

Symptom Likely cause Fix
401 or 403 Missing token, wrong account, or insufficient Browser Rendering permission. Create a token with the documented Edit/Write permission and verify the account ID.
JSON saved as an image The request failed but the client wrote the error body to disk. Check status and content-type before writing bytes.
Blank screenshot Page failed, content is below a delayed render, or resources were blocked. Open the URL directly, add a bounded selector wait, and inspect response errors.
Missing chart or image Lazy loading has not completed. Wait for the chart selector or image element and use full-page loading where supported.
Timeout Slow origin, never-ending network activity, or an excessive wait. Reduce page work, use a specific readiness selector, and keep the timeout within the documented maximum.
Different output between runs Responsive layout, fonts, ads, time, or personalized content changed. Fix viewport, timezone, user agent, cookies, and wait condition; block irrelevant requests where available.
Consent dialog in output The service did not dismiss the site’s consent system. Automate the dialog in a browser session, hide the selector, or use ScreenshotNeo’s consent handling.

Security checklist

  1. Keep Cloudflare tokens and ScreenshotNeo access keys in a secret manager.
  2. Do not place credentials in public image URLs unless you use a signed link mechanism.
  3. Treat target URLs as untrusted input. Validate allowed hosts if users can submit URLs.
  4. Be careful when forwarding cookies, Authorization headers, or private HTML to a third-party renderer.
  5. Log request IDs, status, verdict, and timing, but redact tokens and session cookies.

FAQ

Is Cloudflare Browser Run a screenshot API?

It includes a screenshot Quick Action that behaves like one, but the wider product also offers programmable browser sessions.

Which is faster?

The supplied research contains no independent head-to-head benchmark. Measure your own URLs, wait conditions, image sizes, and concurrency.

Can I use Cloudflare from a Worker?

Yes. Cloudflare documents a Workers Binding approach as well as REST access.

Do dedicated APIs support PDFs?

Some do. ScreenshotOne documents PDF output, and ScreenshotNeo supports PDF capture with paper size, margins, landscape mode, and page ranges.

When should I choose Browser Sessions?

Choose them when one capture requires navigation, authentication, clicks, form entry, or state shared across several browser actions.

What is the lowest-cost way to start with ScreenshotNeo?

The Free plan includes 1,000 screenshots per month without a card. Paid plans begin at $5 for 3,000 screenshots.

Conclusion

Cloudflare Browser Run is the stronger fit when screenshotting is one step in a larger browser automation workflow. A dedicated screenshot API is the cleaner boundary for repeatable URL-to-image or URL-to-PDF jobs. Compare the exact capture options, integration model, quotas, billing rules, and failure behavior for your pages. For a clean, managed capture request with non-billable failed loads and an AI-agent MCP option, start with ScreenshotNeo’s free account.