Cf Browser

web MCP Server

Open-source Cloudflare Browser Rendering proxy — 10 MCP tools for Claude Code (content, screenshot, PDF, markdown, scrape, JSON AI extraction, links, a11y, crawl)

Verified
webweb
6 views6 stars1 forksMIT

Why This Matters

Discovered via github-topic:mcp-server and last synced 3mo ago.

Verified
Source
github-topic:mcp-server
Stars
6
Last synced
3mo ago
Install
Check source

Install

Install instructions not detected yet

Check the source repository for the latest setup steps.

View source instructions
34
Tools
0
Resources
0
Prompts
Standard I/O
Transport

Available Tools (34)

browser_pdf

url, format

browser_click

url, selector

browser_content

url

browser_crawl_status

job_id, wait

Cache

Response

browser_scrape

url, selectors[]

browser_type

url, selector, text

browser_markdown

url

browser_crawl

url, limit

browser_screenshot

url, width, height

browser_a11y

url

browser_submit_form

url, fields

Package

Language

browser_links

url

browser_interact

url, actions[]

DELETE

browser_json

url, prompt

browser_evaluate

url, script

Returns

Description

Route

Method

POST

`{url, fields, submit_selector?, wait_for?, ...}`

JSON

Interaction routes (`/click`, `/type`, `/evaluate`, `/interact`, `/submit-form`) require the `BROWSER` binding. They return 501 if the binding is not configured. If these routes return 404 instead, the Worker deployment is stale; redeploy and verify `/health` reports `version: "2.0.1"`. Response shapes are normalized across Worker, SDK, and MCP: - `/scrape` returns `{"elements":[{"selector":"...", "results":[...]}]}` even if the upstream API returns a raw list. - `/links` returns an array of `{href, text}` objects; bare URL strings are promoted to `{href, text: null}`. - `/a11y` is derived from `/snapshot`, strips base64 screenshot payloads, and adds `type: "accessibility_snapshot"`. ### Authenticated requests All endpoints accept optional `cookies` and `headers` fields for accessing authenticated pages: ```bash curl -X POST https://cf-browser.example.workers.dev/markdown \ -H "Authorization: Bearer YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://app.example.com/dashboard", "cookies": [{"name": "session_id", "value": "abc123", "domain": ".example.com"}], "headers": {"X-Custom-Auth": "token"} }' ``` ### Request examples ```bash # Get markdown curl -X POST https://cf-browser.example.workers.dev/markdown \ -H "Authorization: Bearer YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://react.dev"}' # Screenshot with viewport curl -X POST https://cf-browser.example.workers.dev/screenshot \ -H "Authorization: Bearer YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com", "width": 1280, "height": 720}' \ -o screenshot.png # Accessibility snapshot curl -X POST https://cf-browser.example.workers.dev/a11y \ -H "Authorization: Bearer YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com"}' # AI extraction curl -X POST https://cf-browser.example.workers.dev/json \ -H "Authorization: Bearer YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://news.ycombinator.com", "prompt": "Extract top 5 stories with title and score"}' ``` ### Cache behavior - Set `"no_cache": true` in the request body to bypass cache - Cached responses include `X-Cache: HIT` header - Text content (HTML, Markdown, JSON) is stored in KV - Binary content (PNG, PDF) is stored in R2 - Completed crawl results are persisted to R2 ### Rate limiting - Default: 60 requests per minute per API key - Response headers: `X-RateLimit-Limit`, `X-RateLimit-Remaining` - Exceeded: HTTP 429 with `Retry-After` header ## Python SDK ```bash pip install cf-browser ``` ```python # Direct mode — no Worker needed from cf_browser import CFBrowserDirect async with CFBrowserDirect( account_id="your-cf-account-id", api_token="your-cf-api-token", ) as browser: md = await browser.markdown("https://example.com") # Worker mode — via deployed Worker from cf_browser import CFBrowser async with CFBrowser( base_url="https://cf-browser.example.workers.dev", api_key="your-key", ) as browser: # Read a page markdown = await browser.markdown("https://react.dev") # Take a screenshot png_bytes = await browser.screenshot("https://example.com", width=1280, height=720) # AI-powered extraction data = await browser.json_extract( "https://news.ycombinator.com", prompt="Extract the top 5 stories with title and score", ) # Accessibility snapshot (LLM-friendly, screenshot stripped) tree = await browser.a11y("https://example.com") # Scrape by CSS selectors elements = await browser.scrape("https://example.com", selectors=["h1", ".price"]) # Authenticated scraping with cookies md = await browser.markdown( "https://app.example.com/dashboard", cookies=[{"name": "session", "value": "abc", "domain": ".example.com"}], ) # Async crawl job_id = await browser.crawl("https://example.com", limit=10) result = await browser.crawl_wait(job_id, timeout=120) ``` ### SDK methods **Read-only (Direct + Worker mode):**

bytes

PDF document

str

Job ID

Method

Returns

Component

Free Tier

dict

Fill and submit form

None

Delete cached crawl result

Skill

Command

Workers

100K requests/day

Tool

Input

GET

KV

100K reads/day

R2

10GB storage