This wraps the Browserless API for headless Chrome automation, giving Claude access to scraping, screenshots, PDF generation, and browser interaction. The skill covers the full range: CSS selector extraction, custom Puppeteer scripts for clicking and typing, stealth mode for bypassing bot detection, and even Lighthouse performance audits. It's useful when you need to grab data from JavaScript-heavy sites, capture visual states, or automate form submissions. The function endpoint is the most flexible, letting you write raw Puppeteer code for complex interactions. All requests route through Browserless's hosted service, so you need a token but don't have to manage Chrome instances yourself.
npx -y skills add vm0-ai/vm0-skills --skill browserless --agent claude-codeInstalls into .claude/skills of the current project.
If requests fail, run zero doctor check-connector --env-name BROWSERLESS_TOKEN or zero doctor check-connector --url https://production-sfo.browserless.io/scrape --method POST
Extract structured JSON using CSS selectors:
Write to /tmp/browserless_request.json:
{
"url": "https://example.com",
"elements": [
{"selector": "h1"},
{"selector": "p"}
]
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/scrape?token=$BROWSERLESS_TOKEN" --header "Content-Type: application/json" -d @/tmp/browserless_request.json
With wait options:
Write to /tmp/browserless_request.json:
{
"url": "https://news.ycombinator.com",
"elements": [{"selector": ".titleline > a"}],
"gotoOptions": {
"waitUntil": "networkidle2",
"timeout": 30000
}
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/scrape?token=$BROWSERLESS_TOKEN" --header "Content-Type: application/json" -d @/tmp/browserless_request.json | jq '.data[0].results[:3]'
Full page screenshot:
Write to /tmp/browserless_request.json:
{
"url": "https://example.com",
"options": {
"fullPage": true,
"type": "png"
}
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/screenshot?token=$BROWSERLESS_TOKEN" --header "Content-Type: application/json" -d @/tmp/browserless_request.json --output screenshot.png
Element screenshot:
Write to /tmp/browserless_request.json:
{
"url": "https://example.com",
"options": {
"type": "png"
},
"selector": "h1"
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/screenshot?token=$BROWSERLESS_TOKEN" --header "Content-Type: application/json" -d @/tmp/browserless_request.json --output element.png
With viewport size:
Write to /tmp/browserless_request.json:
{
"url": "https://example.com",
"viewport": {
"width": 1920,
"height": 1080
},
"options": {
"type": "jpeg",
"quality": 80
}
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/screenshot?token=$BROWSERLESS_TOKEN" --header "Content-Type: application/json" -d @/tmp/browserless_request.json --output screenshot.jpg
Write to /tmp/browserless_request.json:
{
"url": "https://example.com",
"options": {
"format": "A4",
"printBackground": true,
"margin": {
"top": "1cm",
"bottom": "1cm"
}
}
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/pdf?token=$BROWSERLESS_TOKEN" --header "Content-Type: application/json" -d @/tmp/browserless_request.json --output page.pdf
Get fully rendered HTML after JavaScript execution:
Write to /tmp/browserless_request.json:
{
"url": "https://example.com",
"gotoOptions": {
"waitUntil": "networkidle0"
}
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/content?token=$BROWSERLESS_TOKEN" --header "Content-Type: application/json" -d @/tmp/browserless_request.json
Run Puppeteer code with full interaction support:
Click element:
Write to /tmp/browserless_function.js:
export default async ({ page }) => {
await page.goto("https://example.com");
await page.click("a");
return { data: { url: page.url() }, type: "application/json" };
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/function?token=$BROWSERLESS_TOKEN" -H "Content-Type: application/javascript" -d @/tmp/browserless_function.js
Type into input:
Write to /tmp/browserless_function.js:
export default async ({ page }) => {
await page.goto("https://duckduckgo.com");
await page.waitForSelector("input[name=q]");
await page.type("input[name=q]", "hello world");
const val = await page.$eval("input[name=q]", e => e.value);
return { data: { typed: val }, type: "application/json" };
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/function?token=$BROWSERLESS_TOKEN" -H "Content-Type: application/javascript" -d @/tmp/browserless_function.js
Form submission:
Write to /tmp/browserless_function.js:
export default async ({ page }) => {
await page.goto("https://duckduckgo.com");
await page.type("input[name=q]", "test query");
await page.keyboard.press("Enter");
await page.waitForNavigation();
return { data: { title: await page.title() }, type: "application/json" };
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/function?token=$BROWSERLESS_TOKEN" -H "Content-Type: application/javascript" -d @/tmp/browserless_function.js
Extract data with custom script:
Write to /tmp/browserless_function.js:
export default async ({ page }) => {
await page.goto("https://news.ycombinator.com");
const links = await page.$$eval(".titleline > a", els => els.slice(0,5).map(a => ({title: a.innerText, url: a.href})));
return { data: links, type: "application/json" };
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/function?token=$BROWSERLESS_TOKEN" -H "Content-Type: application/javascript" -d @/tmp/browserless_function.js
Bypass bot detection:
Write to /tmp/browserless_request.json:
{
"url": "https://example.com",
"browserWSEndpoint": false,
"cookies": false,
"content": true,
"screenshot": false
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/unblock?token=$BROWSERLESS_TOKEN" --header "Content-Type: application/json" -d @/tmp/browserless_request.json
Enable stealth mode to avoid detection:
Write to /tmp/browserless_request.json:
{
"url": "https://example.com",
"elements": [{"selector": "body"}]
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/scrape?token=$BROWSERLESS_TOKEN&stealth=true" --header "Content-Type: application/json" -d @/tmp/browserless_request.json
Fetch a URL and get content in native format. Can bundle all resources (CSS, JS, images) as zip:
Basic export:
Write to /tmp/browserless_request.json:
{
"url": "https://example.com"
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/export?token=$BROWSERLESS_TOKEN" --header "Content-Type: application/json" -d @/tmp/browserless_request.json --output page.html
Export with all resources as ZIP:
Write to /tmp/browserless_request.json:
{
"url": "https://example.com",
"includeResources": true
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/export?token=$BROWSERLESS_TOKEN" --header "Content-Type: application/json" -d @/tmp/browserless_request.json --output webpage.zip
Run Lighthouse audits for accessibility, performance, SEO, best practices:
Full audit:
Write to /tmp/browserless_request.json:
{
"url": "https://example.com"
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/performance?token=$BROWSERLESS_TOKEN" --header "Content-Type: application/json" -d @/tmp/browserless_request.json | jq '.data.categories | to_entries[] | {category: .key, score: .value.score}'
Specific category (accessibility, performance, seo, best-practices, pwa):
Write to /tmp/browserless_request.json:
{
"url": "https://example.com",
"config": {
"extends": "lighthouse:default",
"settings": {
"onlyCategories": ["performance"]
}
}
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/performance?token=$BROWSERLESS_TOKEN" --header "Content-Type: application/json" -d @/tmp/browserless_request.json | jq '.data.audits | to_entries[:5][] | {audit: .key, score: .value.score, display: .value.displayValue}'
Specific audit (e.g., unminified-css, first-contentful-paint):
Write to /tmp/browserless_request.json:
{
"url": "https://example.com",
"config": {
"extends": "lighthouse:default",
"settings": {
"onlyAudits": ["first-contentful-paint", "largest-contentful-paint"]
}
}
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/performance?token=$BROWSERLESS_TOKEN" --header "Content-Type: application/json" -d @/tmp/browserless_request.json | jq '.data.audits'
Create a persistent browser session that can be connected to via WebSocket:
Write to /tmp/browserless_request.json:
{
"ttl": 300000,
"stealth": false,
"headless": true
}
Then run:
curl -s -X POST "https://production-sfo.browserless.io/session?token=$BROWSERLESS_TOKEN" --header "Content-Type: application/json" -d @/tmp/browserless_request.json
Response includes:
id - Session ID for subsequent operationsconnect - WebSocket URL for Puppeteer/Playwright connectionstop - Full URL to stop/delete the session (use this exact URL)browserQL - BrowserQL query endpointttl - Time-to-live in milliseconds (default: 300000 = 5 minutes)Use the session with Puppeteer:
const puppeteer = require('puppeteer-core');
const browser = await puppeteer.connect({
browserWSEndpoint: '<connect-url-from-response>' // Use the 'connect' URL from response
});
Stop a running session before its timeout expires using the stop URL from the creation response:
curl -s -X DELETE "<stop-url-from-response>"
Example (replace <stop-url-from-response> with the actual stop URL from session creation):
curl -s -X DELETE "https://production-sfo.browserless.io/e/<encoded-path>/session/<session-id>?token=<your-token>"
Response:
{
"success": true,
"message": "Session <session-id> was successfully removed",
"sessionId": "<session-id>",
"timestamp": "2026-01-01T07:41:36.933Z"
}
| Endpoint | Method | Description |
|---|---|---|
/scrape | POST | Extract data with CSS selectors |
/screenshot | POST | Capture screenshots (PNG/JPEG) |
/pdf | POST | Generate PDF documents |
/content | POST | Get rendered HTML |
/function | POST | Execute custom Puppeteer code |
/unblock | POST | Bypass bot protection |
/export | POST | Export page with resources as ZIP |
/performance | POST | Lighthouse audits (a11y, perf, SEO) |
/session | POST | Create persistent browser session |
/session/{id} | DELETE | Stop persistent session |
Control page navigation:
{
"gotoOptions": {
"waitUntil": "networkidle2",
"timeout": 30000
}
}
waitUntil values:
load - Wait for load eventdomcontentloaded - Wait for DOMContentLoadednetworkidle0 - No network connections for 500msnetworkidle2 - Max 2 network connections for 500ms{
"waitForTimeout": 1000,
"waitForSelector": {"selector": ".loaded", "timeout": 5000},
"waitForFunction": {"fn": "() => document.ready", "timeout": 5000}
}
{
"viewport": {
"width": 1920,
"height": 1080,
"deviceScaleFactor": 2
}
}
| Parameter | Description |
|---|---|
token | API token (required) |
stealth | Enable stealth mode (true/false) |
blockAds | Block advertisements |
proxy | Use proxy server |
Scrape response:
{
"data": [
{
"selector": "h1",
"results": [
{
"text": "Example Domain",
"html": "Example Domain",
"attributes": [{"name": "class", "value": "title"}],
"width": 400,
"height": 50,
"top": 100,
"left": 50
}
]
}
]
}
networkidle2 for most pages, networkidle0 for SPAsjpeg with quality 80 for smaller filesproduction-sfo.browserless.io (US West)production-lon.browserless.io (Europe)juliusbrussee/caveman
mattpocock/skills
shadcn/improve
obra/superpowers
forrestchang/andrej-karpathy-skills
vercel-labs/skills