browser-renderring

claude_code 0 companion files
← Back

SKILL.md

---
name: cloudflare-browser-rendering
description: Transform web pages into AI-friendly formats using Cloudflare Browser Rendering API. Extract structured data as JSON, convert to Markdown, capture screenshots, generate PDFs, or scrape elements. Use when working with web pages, scraping data, converting pages to different formats, or when the user mentions URLs, web scraping, screenshots, or PDFs. Requires CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN environment variables.
allowed-tools: Bash(git:*), FileSystem, Bash(npm:*), Bash(yarn:*), Bash(lint:*), Bash(test:*), Bash(build:*), Read, Grep, Glob, Task
---

# Cloudflare Browser Rendering

## Overview
This skill uses Cloudflare's serverless Browser Rendering REST API to interact with web pages. It provides 8 different endpoints to transform and extract data from websites without managing browser infrastructure.

## Prerequisites
Ensure these environment variables are set:
```bash
export CLOUDFLARE_ACCOUNT_ID="your-account-id"
export CLOUDFLARE_API_TOKEN="your-api-token"
```

## Available Endpoints

### 1. Extract Structured Data (`/json`)
**When to use:** User wants specific data extracted from a webpage as JSON.

**How it works:**
- Send URL and natural language prompt describing what to extract
- Optionally provide JSON schema for structured output
- Optionally specify custom AI models (Claude, GPT-4, Workers AI) with failover
- Returns structured JSON data

**Example request:**
```typescript
POST https://api.cloudflare.com/client/v4/accounts/{accountId}/browser-rendering/json
{
  "url": "https://news.ycombinator.com",
  "prompt": "Get the top 5 stories with title, points, and author",
  "response_format": {
    "type": "json_schema",
    "schema": {
      "type": "object",
      "properties": {
        "stories": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "title": { "type": "string" },
              "points": { "type": "number" },
              "author": { "type": "string" }
            }
          }
        }
      }
    }
  },
  "custom_ai": [
    { "model": "claude-sonnet-4-20250514", "provider": "anthropic" },
    { "model": "@cf/meta/llama-3.3-70b-instruct-fp8-fast" }
  ]
}
```

### 2. Convert to Markdown (`/markdown`)
**When to use:** User wants webpage content as clean Markdown for LLM processing or documentation.

**How it works:**
- Renders page and converts to Markdown
- Strips unnecessary HTML/CSS
- Returns clean, readable text

**Example request:**
```typescript
POST https://api.cloudflare.com/client/v4/accounts/{accountId}/browser-rendering/markdown
{
  "url": "https://developers.cloudflare.com/workers/",
  "gotoOptions": { "waitUntil": "networkidle" }
}
```

### 3. Capture HTML (`/content`)
**When to use:** User needs fully rendered HTML after JavaScript execution.

**Example request:**
```typescript
POST https://api.cloudflare.com/client/v4/accounts/{accountId}/browser-rendering/content
{
  "url": "https://example.com",
  "rejectResourceTypes": ["image", "stylesheet", "font"]
}
```

### 4. Take Screenshot (`/screenshot`)
**When to use:** User wants visual capture of a webpage.

**Example request:**
```typescript
POST https://api.cloudflare.com/client/v4/accounts/{accountId}/browser-rendering/screenshot
{
  "url": "https://cloudflare.com",
  "screenshotOptions": {
    "fullPage": true,
    "type": "png"
  },
  "viewport": { "width": 1920, "height": 1080 }
}
```
Returns base64-encoded PNG/JPEG.

### 5. Generate PDF (`/pdf`)
**When to use:** User wants to convert webpage to PDF document.

**Example request:**
```typescript
POST https://api.cloudflare.com/client/v4/accounts/{accountId}/browser-rendering/pdf
{
  "url": "https://example.com/report",
  "pdfOptions": {
    "format": "A4",
    "marginTop": "1cm",
    "marginBottom": "1cm",
    "printBackground": true
  }
}
```
Returns base64-encoded PDF.

### 6. Scrape Elements (`/scrape`)
**When to use:** User wants metadata from specific DOM elements.

**Example request:**
```typescript
POST https://api.cloudflare.com/client/v4/accounts/{accountId}/browser-rendering/scrape
{
  "url": "https://example.com/products"
}
```
Returns element dimensions, positions, and text content.

### 7. Extract Links (`/links`)
**When to use:** User wants all hyperlinks from a page.

**Example request:**
```typescript
POST https://api.cloudflare.com/client/v4/accounts/{accountId}/browser-rendering/links
{
  "url": "https://developers.cloudflare.com"
}
```
Returns array of all links.

### 8. Create Snapshot (`/snapshot`)
**When to use:** User wants both HTML and screenshot in one request.

**Example request:**
```typescript
POST https://api.cloudflare.com/client/v4/accounts/{accountId}/browser-rendering/snapshot
{
  "url": "https://example.com",
  "screenshotOptions": { "fullPage": false }
}
```
Returns `{ html: string, screenshot: base64string }`.

## Implementation Pattern

Use this TypeScript pattern for all endpoints:

```typescript
async function callBrowserRenderingAPI(
  endpoint: "content" | "json" | "markdown" | "screenshot" | "pdf" | "snapshot" | "scrape" | "links",
  params: object
): Promise<any> {
  const accountId = process.env.CLOUDFLARE_ACCOUNT_ID;
  const apiToken = process.env.CLOUDFLARE_API_TOKEN;

  if (!accountId || !apiToken) {
    throw new Error("Missing CLOUDFLARE_ACCOUNT_ID or CLOUDFLARE_API_TOKEN");
  }

  const response = await fetch(
    `https://api.cloudflare.com/client/v4/accounts/${accountId}/browser-rendering/${endpoint}`,
    {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${apiToken}`,
        "Content-Type": "application/json"
      },
      body: JSON.stringify(params)
    }
  );

  if (!response.ok) {
    const error = await response.text();
    throw new Error(`Browser Rendering API error: ${response.status} - ${error}`);
  }

  const result = await response.json();
  
  // Monitor browser time for cost tracking
  const browserTimeUsed = response.headers.get("X-Browser-Ms-Used");
  if (browserTimeUsed) {
    console.log(`Browser time used: ${browserTimeUsed}ms`);
  }

  return result.result;
}
```

## Common Parameters

### Performance Optimization
```typescript
{
  "rejectResourceTypes": ["image", "stylesheet", "font"], // Block unnecessary resources
  "gotoOptions": { 
    "waitUntil": "domcontentloaded", // Don't wait for all resources
    "timeout": 60000 // Custom timeout (ms)
  }
}
```

### Custom User Agent
```typescript
{
  "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/119.0.0.0"
}
```
Note: User agent doesn't bypass bot protection. Requests always identified as bot.

### Cookies
```typescript
{
  "cookies": [
    {
      "name": "session_id",
      "value": "abc123",
      "domain": "example.com"
    }
  ]
}
```

## Decision Guide: Which Endpoint to Use

| User Request | Endpoint | Why |
|--------------|----------|-----|
| "Extract product prices" | `/json` | Structured data extraction |
| "Summarize this article" | `/markdown` then process | Clean text for LLM |
| "Screenshot this page" | `/screenshot` | Visual capture |
| "Save as PDF" | `/pdf` | Document generation |
| "Get all links" | `/links` | Link extraction |
| "Analyze HTML structure" | `/content` | Full DOM access |
| "Get image dimensions" | `/scrape` | Element metadata |
| "Archive this page" | `/snapshot` | HTML + screenshot |

## Best Practices

### 1. Choose the Right Format
- **JSON**: When user wants specific data points
- **Markdown**: When feeding to LLM or need readable text
- **HTML**: When need full DOM for analysis
- **Screenshot**: When visual verification needed
- **PDF**: When creating documents

### 2. Optimize for Cost
```typescript
// Good: Block unnecessary resources
{
  "rejectResourceTypes": ["image", "media", "font", "stylesheet"],
  "gotoOptions": { "waitUntil": "domcontentloaded" }
}

// Bad: Load everything
{
  "gotoOptions": { "waitUntil": "networkidle" }
}
```

### 3. Handle Errors
Always check environment variables and handle API errors:
```typescript
if (!process.env.CLOUDFLARE_ACCOUNT_ID) {
  throw new Error("Set CLOUDFLARE_ACCOUNT_ID environment variable");
}
```

### 4. Monitor Costs
Check `X-Browser-Ms-Used` header in responses:
- Browser time: ~₹0.83/minute (~$0.01/minute)
- Average page: 2-5 seconds = ₹0.03-0.07
- Free tier: 500,000 requests/month

## Common Workflows

### Data Extraction Pipeline
1. Get markdown for quick scan: `/markdown`
2. Extract structured data: `/json` with schema
3. Visual verification: `/screenshot`

### Content Archival
1. Convert to markdown: `/markdown`
2. Generate PDF: `/pdf`
3. Take snapshot: `/snapshot`

### SEO Analysis
1. Extract all links: `/links`
2. Scrape meta elements: `/scrape`
3. Full HTML analysis: `/content`

## Troubleshooting

**Missing environment variables:**
- Verify: `echo $CLOUDFLARE_ACCOUNT_ID`
- Set in `~/.zshrc` or `~/.bashrc`

**401 Unauthorized:**
- Check API token has "Browser Rendering - Edit" permission
- Verify token at https://dash.cloudflare.com/profile/api-tokens

**Timeout errors:**
- Increase `gotoOptions.timeout`
- Use faster `waitUntil: "domcontentloaded"`
- Block unnecessary resources

**Poor extraction quality:**
- Use more specific prompts in `/json` endpoint
- Provide JSON schema for structured output
- Use custom AI models with failover

## Limitations
- Always identified as bot (no bypass)
- XPath selectors not supported (use CSS)
- 30-second default timeout
- No session persistence in REST API

No companion files

Add companion files to enhance this skill

Danger Zone

Deleting this skill will remove all associated files. This action cannot be undone.

Owner
Prasham Trivedi
Created
2/16/2026, 6:50:18 PM
Last Updated
2/16/2026, 6:50:18 PM
🆔 Skill ID
nm2PKyPAAbGnQaRZDsusQ