| 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 |
|
Run headless Chrome on Cloudflare's global network for browser automation, web scraping, testing, and content generation.
Cloudflare Browser Run (formerly Browser Rendering) provides two integration methods:
- Quick Actions — Stateless HTTP endpoints for common tasks (screenshot, markdown, PDF, crawl, etc.). No code deployment needed. Ideal for agents and cron jobs.
- Browser Sessions — Full browser control via Puppeteer, Playwright, CDP, or Stagehand. Deploy within Cloudflare Workers or connect from any environment via CDP WebSocket.
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_extractcan 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)
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/v4How to create the token:
- Go to Cloudflare Dashboard → My Profile → API Tokens
- Create Token → Custom token
- Permissions:
Browser Rendering→Edit - Account Resources: Include your target account
- 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 500All 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 |
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.pngParameters:
url(string) — Target URLwidth/height(integer) — Viewport sizefullPage(boolean) — Capture full scrollable pageformat(string) —png,jpeg,webpdelay(integer) — Wait N ms after load before capture
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.
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.pdfcurl -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"
}'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.
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
For full browser control (clicking, form filling, multi-step workflows, persistent sessions):
# 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 POSTConnect to the returned webSocketDebuggerUrl using any CDP client, or use Puppeteer/Playwright with the remote endpoint.
const browser = await puppeteer.connect({
browserWSEndpoint: 'wss://...'
});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.
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.
| 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 |
| 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.
-
Token scope is "Browser Rendering - Edit", not "Browser Run". The permission name still uses the old product name in the Cloudflare dashboard.
-
401 Unauthorized: Most commonly caused by using an API Key instead of an API Token, or missing the
Browser Rendering - Editscope. -
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).
-
429 "Too many requests": Exceeded the Quick Actions rate limit (Free: 1/10s, Paid: per-second). Add retry logic with exponential backoff.
-
Screenshot returns empty/black image: The page may not have finished rendering. Add
"delay": 2000or"waitForSelector": "body"to the request. -
Crawl job stuck: The
/crawlendpoint is async. You must poll the job status endpoint using the returned job ID. Do not assume immediate completion. -
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.
-
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).
- API Token created with
Browser Rendering - Editscope -
CLOUDFLARE_ACCOUNT_IDandCLOUDFLARE_API_TOKENset in.env - Quick Actions
/contentor/screenshottest returns success - Response includes
X-Browser-Ms-Usedheader - 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