Skip to content

Instantly share code, notes, and snippets.

@wastemobile
Last active May 15, 2026 00:28
Show Gist options
  • Select an option

  • Save wastemobile/fbfd40f2b6786991f608652983488140 to your computer and use it in GitHub Desktop.

Select an option

Save wastemobile/fbfd40f2b6786991f608652983488140 to your computer and use it in GitHub Desktop.
cloudflare-browser-run
name cloudflare-browser-run
description Use when you need to capture screenshots, extract markdown/PDF/HTML, scrape structured data, or crawl web pages via Cloudflare's headless browser service. Covers Quick Actions (stateless HTTP), Browser Sessions (Puppeteer/Playwright/CDP), and the MCP server. Preferred over local browser tools when JS rendering is required and browser tool costs are high.
version 1.0.0
author Hermes Agent
license MIT
metadata
hermes
tags related_skills
cloudflare
browser
scraping
screenshot
markdown
pdf
web-extract
api
hermes-web-extract-billing-fallback
defuddle
tavily-search

Cloudflare Browser Run

Run headless Chrome on Cloudflare's global network for browser automation, web scraping, testing, and content generation.

Overview

Cloudflare Browser Run (formerly Browser Rendering) provides two integration methods:

  1. Quick Actions — Stateless HTTP endpoints for common tasks (screenshot, markdown, PDF, crawl, etc.). No code deployment needed. Ideal for agents and cron jobs.
  2. Browser Sessions — Full browser control via Puppeteer, Playwright, CDP, or Stagehand. Deploy within Cloudflare Workers or connect from any environment via CDP WebSocket.

When to Use

Use this skill when you need to:

  • Capture screenshots of JS-rendered pages
  • Extract clean markdown from articles or documentation
  • Generate PDFs from URLs or raw HTML
  • Scrape structured data (JSON) from pages using natural language prompts
  • Crawl entire sites asynchronously
  • Retrieve all links or specific HTML elements from a page
  • Perform browser automation when local browser_* tools are unavailable or cost-prohibitive

Don't use for:

  • Simple static pages that web_extract can handle without JS rendering
  • Tasks requiring persistent login sessions across multiple requests (use Browser Sessions instead)
  • Heavy daily crawling beyond free-tier limits (10 min/day)

Environment Setup

Store credentials in your profile's .env:

# Required scopes for CLOUDFLARE_API_TOKEN: Browser Rendering - Edit
CLOUDFLARE_ACCOUNT_ID=your-account-id
CLOUDFLARE_API_TOKEN=your-api-token
CLOUDFLARE_API_BASE_URL=https://api.cloudflare.com/client/v4

How to create the token:

  1. Go to Cloudflare Dashboard → My Profile → API Tokens
  2. Create Token → Custom token
  3. Permissions: Browser RenderingEdit
  4. Account Resources: Include your target account
  5. Copy the token and store it in .env

Verify credentials:

source ~/.hermes/.env
curl -s "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/browser-rendering/content" \
  -H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com"}' | head -c 500

Quick Actions

All Quick Actions are single HTTP POST requests to:

POST https://api.cloudflare.com/client/v4/accounts/{accountId}/browser-rendering/{endpoint}

Common headers:

Authorization: Bearer {CLOUDFLARE_API_TOKEN}
Content-Type: application/json

Available endpoints:

Endpoint Description Use Case
/content Fetch raw HTML Static HTML extraction
/screenshot Capture screenshot Visual capture of JS-rendered pages
/pdf Render PDF Document generation from URL or HTML
/markdown Extract Markdown Clean article/docs extraction
/snapshot Take webpage snapshot Full page state capture
/scrape Scrape HTML elements Targeted element extraction by selector
/json Capture structured data AI-powered extraction via natural language prompt
/links Retrieve links Extract all or filtered links
/crawl Crawl web content (Beta) Multi-page async crawling

/screenshot

Common options:

curl -s "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/browser-rendering/screenshot" \
  -H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "width": 1920,
    "height": 1080,
    "fullPage": false,
    "format": "png"
  }' \
  --output screenshot.png

Parameters:

  • url (string) — Target URL
  • width / height (integer) — Viewport size
  • fullPage (boolean) — Capture full scrollable page
  • format (string) — png, jpeg, webp
  • delay (integer) — Wait N ms after load before capture

/markdown

curl -s "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/browser-rendering/markdown" \
  -H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com"}'

Returns clean markdown extracted from the rendered page. Ideal for articles and documentation.

/pdf

curl -s "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/browser-rendering/pdf" \
  -H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "format": "A4",
    "printBackground": true
  }' \
  --output page.pdf

/json (AI-powered extraction)

curl -s "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/browser-rendering/json" \
  -H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/products",
    "prompt": "Extract all product names and prices as a JSON array"
  }'

/crawl (Beta)

Asynchronous multi-page crawling. Submit a job and poll for results.

# Start crawl
curl -s "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/browser-rendering/crawl" \
  -H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "maxPages": 50,
    "outputFormat": "markdown"
  }'

Limits: Free plan: 5 crawl jobs/day, max 100 pages per job.

Response Headers

Every Quick Actions response includes:

  • X-Browser-Ms-Used — Browser time consumed for that request (in milliseconds)
  • Use this header to track usage against your daily/minute limits

Browser Sessions (CDP / Puppeteer / Playwright)

For full browser control (clicking, form filling, multi-step workflows, persistent sessions):

CDP WebSocket (connect from any environment)

# Get a browser session WebSocket URL
curl -s "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/browser-rendering/sessions" \
  -H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
  -X POST

Connect to the returned webSocketDebuggerUrl using any CDP client, or use Puppeteer/Playwright with the remote endpoint.

Puppeteer

const browser = await puppeteer.connect({
  browserWSEndpoint: 'wss://...'
});

Playwright

const browser = await chromium.connectOverCDP('wss://...');

Limits (Free): 3 concurrent browsers, 1 new instance every 20 seconds, 60s timeout. Limits (Paid): 120 concurrent browsers, 1 new instance per second, 60s timeout.

MCP Server

Cloudflare Browser Run provides an MCP (Model Context Protocol) server for AI agents.

Endpoint: Check the Cloudflare docs for the latest MCP server configuration: https://developers.cloudflare.com/browser-run/mcp-server/

This allows LLMs to control browsers directly via MCP clients without writing HTTP calls.

Limits & Pricing

Workers Free Plan

Feature Limit
Browser hours 10 minutes per day
Concurrent browsers 3 per account (Browser Sessions only)
New browser instances 1 every 20 seconds
Browser timeout 60 seconds
Quick Actions requests 1 every 10 seconds
Crawl jobs 5 per day, max 100 pages each

Workers Paid Plan

Feature Limit / Price
Browser hours 10 hours/month included, then $0.09/hour
Concurrent browsers 10 included (averaged monthly), then $2.00/browser
New browser instances 1 per second
Browser timeout 60 seconds
Quick Actions requests Per-second rate limit
Crawl jobs Higher limits available on request

Important: Browser hours are shared across Quick Actions AND Browser Sessions. A screenshot that takes 3 seconds consumes 3 seconds of your browser hours budget.

Common Pitfalls

  1. Token scope is "Browser Rendering - Edit", not "Browser Run". The permission name still uses the old product name in the Cloudflare dashboard.

  2. 401 Unauthorized: Most commonly caused by using an API Key instead of an API Token, or missing the Browser Rendering - Edit scope.

  3. 429 "Browser time limit exceeded for today": You have hit the Free plan's 10-minute daily cap. Upgrade to Workers Paid or wait until the next day (UTC reset).

  4. 429 "Too many requests": Exceeded the Quick Actions rate limit (Free: 1/10s, Paid: per-second). Add retry logic with exponential backoff.

  5. Screenshot returns empty/black image: The page may not have finished rendering. Add "delay": 2000 or "waitForSelector": "body" to the request.

  6. Crawl job stuck: The /crawl endpoint is async. You must poll the job status endpoint using the returned job ID. Do not assume immediate completion.

  7. Workers Paid but still hitting 10-minute limit: If you upgraded recently, ensure your account's billing plan change has propagated. Contact Cloudflare support if the limit persists after 24 hours.

  8. Underestimating concurrent browser costs: On Paid plans, concurrent browsers are billed based on monthly average, not peak. 15 browsers averaged over a month = $10 extra (5 × $2.00).

Verification Checklist

  • API Token created with Browser Rendering - Edit scope
  • CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN set in .env
  • Quick Actions /content or /screenshot test returns success
  • Response includes X-Browser-Ms-Used header
  • Free plan user: daily usage under 10 minutes
  • Paid plan user: understand browser hours + concurrent browser billing
  • For Browser Sessions: verify WebSocket URL connectivity before scripting
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment