home / skills / cloudflare / moltworker / cloudflare-browser

cloudflare-browser skill

/skills/cloudflare-browser

This skill enables headless browser control via Cloudflare Browser Rendering for screenshots, navigation, scraping, and video capture in Cloudflare Workers.

npx playbooks add skill cloudflare/moltworker --skill cloudflare-browser

Review the files below or copy the command above to add this skill to your agents.

Files (4)
SKILL.md
2.9 KB
---
name: cloudflare-browser
description: Control headless Chrome via Cloudflare Browser Rendering CDP WebSocket. Use for screenshots, page navigation, scraping, and video capture when browser automation is needed in a Cloudflare Workers environment. Requires CDP_SECRET env var and cdpUrl configured in browser.profiles.
---

# Cloudflare Browser Rendering

Control headless browsers via Cloudflare's Browser Rendering service using CDP (Chrome DevTools Protocol) over WebSocket.

## Prerequisites

- `CDP_SECRET` environment variable set
- Browser profile configured in openclaw.json with `cdpUrl` pointing to the worker endpoint:
  ```json
  "browser": {
    "profiles": {
      "cloudflare": {
        "cdpUrl": "https://your-worker.workers.dev/cdp?secret=..."
      }
    }
  }
  ```

## Quick Start

### Screenshot
```bash
node /path/to/skills/cloudflare-browser/scripts/screenshot.js https://example.com output.png
```

### Multi-page Video
```bash
node /path/to/skills/cloudflare-browser/scripts/video.js "https://site1.com,https://site2.com" output.mp4
```

## CDP Connection Pattern

The worker creates a page target automatically on WebSocket connect. Listen for Target.targetCreated event to get the targetId:

```javascript
const WebSocket = require('ws');
const CDP_SECRET = process.env.CDP_SECRET;
const WS_URL = `wss://your-worker.workers.dev/cdp?secret=${encodeURIComponent(CDP_SECRET)}`;

const ws = new WebSocket(WS_URL);
let targetId = null;

ws.on('message', (data) => {
  const msg = JSON.parse(data.toString());
  if (msg.method === 'Target.targetCreated' && msg.params?.targetInfo?.type === 'page') {
    targetId = msg.params.targetInfo.targetId;
  }
});
```

## Key CDP Commands

| Command | Purpose |
|---------|---------|
| Page.navigate | Navigate to URL |
| Page.captureScreenshot | Capture PNG/JPEG |
| Runtime.evaluate | Execute JavaScript |
| Emulation.setDeviceMetricsOverride | Set viewport size |

## Common Patterns

### Navigate and Screenshot
```javascript
await send('Page.navigate', { url: 'https://example.com' });
await new Promise(r => setTimeout(r, 3000)); // Wait for render
const { data } = await send('Page.captureScreenshot', { format: 'png' });
fs.writeFileSync('out.png', Buffer.from(data, 'base64'));
```

### Scroll Page
```javascript
await send('Runtime.evaluate', { expression: 'window.scrollBy(0, 300)' });
```

### Set Viewport
```javascript
await send('Emulation.setDeviceMetricsOverride', {
  width: 1280,
  height: 720,
  deviceScaleFactor: 1,
  mobile: false
});
```

## Creating Videos

1. Capture frames as PNGs during navigation
2. Use ffmpeg to stitch: `ffmpeg -framerate 10 -i frame_%04d.png -c:v libx264 -pix_fmt yuv420p output.mp4`

## Troubleshooting

- **No target created**: Race condition - wait for Target.targetCreated event with timeout
- **Commands timeout**: Worker may have cold start delay; increase timeout to 30-60s
- **WebSocket hangs**: Verify CDP_SECRET matches worker configuration

Overview

This skill lets you control headless Chrome through Cloudflare Browser Rendering using the Chrome DevTools Protocol (CDP) over a WebSocket. It integrates with Cloudflare Workers to provide page navigation, screenshots, scraping, and frame capture for video generation. Configuration requires a CDP_SECRET environment variable and a cdpUrl in your browser profile.

How this skill works

The worker creates a page target when a CDP WebSocket connects; the skill listens for Target.targetCreated to obtain the targetId and then sends CDP commands to that target. Common commands include Page.navigate, Page.captureScreenshot, Runtime.evaluate, and Emulation.setDeviceMetricsOverride. Frames captured as PNGs can be stitched into video using ffmpeg.

When to use it

  • Take render-accurate screenshots of pages that require JavaScript execution
  • Automate navigation and scraping where server-side fetches are insufficient
  • Capture sequences of frames for time-lapse or multi-page videos
  • Emulate specific viewport sizes or device metrics inside Cloudflare Workers
  • Run transient headless browser tasks without managing your own Chromium instances

Best practices

  • Set CDP_SECRET in your environment and configure cdpUrl in browser.profiles before connecting
  • Wait for Target.targetCreated and handle a reasonable timeout to avoid race conditions
  • Increase command timeouts (30–60s) to accommodate worker cold starts
  • Capture multiple frames and use ffmpeg locally or in a pipeline to create videos
  • Use Emulation.setDeviceMetricsOverride to ensure consistent viewport and pixel ratios

Example use cases

  • Generate PNG screenshots of dynamic pages for previews or thumbnails
  • Run JavaScript evaluations to extract rendered DOM content for scraping
  • Scroll and capture long pages by sending Runtime.evaluate scroll commands and stitching images
  • Produce a short MP4 by capturing ordered frames during navigation and running ffmpeg
  • Test responsive layouts by programmatically changing viewport dimensions

FAQ

What environment variables and config are required?

Set CDP_SECRET in the environment and add a browser profile with cdpUrl that points to your worker endpoint including the secret.

How do I detect the page target to send commands to?

Listen for the Target.targetCreated event on the WebSocket and use params.targetInfo.targetId when type === 'page'.

Why do commands sometimes timeout?

Workers can cold-start; increase your command timeout to 30–60 seconds and add retries for reliability.