Cloudflare Browser Rendering
einverne/dotfiles
Guide for implementing Cloudflare Browser Rendering - a headless browser automation API for screenshots, PDFs, web scraping, and testing.
Extract structured data from websites and produce an executable Playwright script plus extracted data.
$ npx skills add actionbook/actionbook --skill extract -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install actionbook/actionbook extract --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/actionbook/actionbook.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/extract .claude/skills/extract && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "extract" agent skill from https://github.com/actionbook/actionbook/tree/main/skills/extract into .claude/skills/extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "extract", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/actionbook/actionbook/tree/main/skills/extractType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add actionbook/actionbook --skill extract -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install actionbook/actionbook extract --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/actionbook/actionbook.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/extract .agents/skills/extract && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "extract" agent skill from https://github.com/actionbook/actionbook/tree/main/skills/extract into .agents/skills/extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "extract", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add actionbook/actionbook --skill extract -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install actionbook/actionbook extract --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/actionbook/actionbook.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/extract .cursor/skills/extract && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "extract" agent skill from https://github.com/actionbook/actionbook/tree/main/skills/extract into .cursor/skills/extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "extract", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/actionbook/actionbook.git --path skills/extract--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add actionbook/actionbook --skill extract -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install actionbook/actionbook extract --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/actionbook/actionbook.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/extract .gemini/skills/extract && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "extract" agent skill from https://github.com/actionbook/actionbook/tree/main/skills/extract into .gemini/skills/extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "extract", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install actionbook/actionbook extractInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add actionbook/actionbook --skill extract -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/actionbook/actionbook.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/extract .github/skills/extract && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "extract" agent skill from https://github.com/actionbook/actionbook/tree/main/skills/extract into .github/skills/extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "extract", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add actionbook/actionbook --skill extract -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install actionbook/actionbook extract --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/actionbook/actionbook.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/extract .opencode/skills/extract && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "extract" agent skill from https://github.com/actionbook/actionbook/tree/main/skills/extract into .opencode/skills/extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "extract", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
extractExtract structured data from websites and produce an executable Playwright script plus extracted data.
Extract is an agent skill from actionbook/actionbook. Extract structured data from websites and produce an executable Playwright script plus extracted data. Use when the user wants to scrape, extract, pull, collect, or harvest data from any website — product listings, tables, search results, feeds, profiles, or any repeating content.
Its SKILL.md is about 3.4k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Sales & Support, covering Web scraping, Schema markup and E-commerce operations. It works with Playwright. The repository describes itself as: Let your AI agent get the sources behind logins and paywalls. The licence is Apache-2.0.
6 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 0e31254. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
nodeFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Extract loads about 3.4k tokens when it runs. Until then it costs about 72 tokens; SKILL.md has 1,005 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from actionbook/actionbook at commit 0e31254, republished under its Apache-2.0 licence (© actionbook). 1,005 words, ~3,375 tokens.
.claude/skills/extract/SKILL.md (or your agent's skills folder).Activate when the user wants to obtain data from a website:
The deliverable is always two artifacts:
.cjs file that reproduces the extraction without Actionbook at runtime.Use Actionbook as a conditional accelerator, not a mandatory step. The goal is reliable selectors in the shortest path.
User request
│
├─► actionbook search "<site> <intent>"
│ ├─ Results with Health Score ≥ 70% ──► actionbook get "<ID>" ──► use selectors
│ └─ No results / low score ──► Fallback
│
└─► Fallback: actionbook browser open <url>
├─ actionbook browser snapshot (accessibility tree → find selectors)
├─ actionbook browser screenshot (visual confirmation)
└─ manual selector discovery via DOM inspectionPriority order for selector sources:
| Priority | Source | When |
|---|---|---|
| 1 | actionbook get | Site is indexed, health score ≥ 70% |
| 2 | actionbook browser snapshot | Not indexed or selectors outdated |
| 3 | DOM inspection via screenshot + snapshot | Complex SPA / dynamic content |
Non-negotiable rule: if search + get already provides usable selectors for required fields, start from get selectors and do not jump to full fallback (snapshot/screenshot) by default. Exception: lightweight mechanism probes (for hydration/virtualization/pagination) are allowed when runtime behavior may affect script correctness. Escalate to snapshot/screenshot only when probes/sample validation indicate selector gaps or instability.
Websites use patterns that break naive scraping. The generated Playwright script must account for these:
Pages may render a shell first, then stream or hydrate content.
// Wait for hydration to complete — not just DOMContentLoaded
await page.waitForSelector('[data-item]', { state: 'attached' });
await page.waitForFunction(() => {
const items = document.querySelectorAll('[data-item]');
return items.length > 0 && !document.querySelector('[data-pending]');
});Detection cues: React root with data-reactroot, Next.js __NEXT_DATA__, empty containers that fill after JS runs. If actionbook browser text "<selector>" returns empty but the screenshot shows content, hydration hasn't completed.
Only visible rows exist in the DOM. Scrolling renders new rows and destroys old ones.
// Scroll-and-collect loop for virtualized lists (scroll container aware)
const allItems = [];
const maxScrolls = 50;
let scrolls = 0;
const container = await page.$('<scroll-container-selector>');
if (!container) throw new Error('Scroll container not found');
let previousTop = await container.evaluate(el => el.scrollTop);
while (scrolls < maxScrolls) {
const items = await page.$$eval('[data-row]', rows =>
rows.map(r => ({ text: r.textContent.trim() }))
);
for (const item of items) {
if (!allItems.find(i => i.text === item.text)) allItems.push(item);
}
await container.evaluate(el => el.scrollBy(0, 600));
await page.waitForTimeout(300);
const currentTop = await container.evaluate(el => el.scrollTop);
if (currentTop === previousTop) break;
previousTop = currentTop;
scrolls += 1;
}Detection cues: Container has fixed height with overflow: auto/scroll, row count in DOM is much smaller than stated total, rows have transform: translateY(...) or position: absolute; top: ...px.
New content appends when the user scrolls near the bottom.
// Scroll to bottom until no new content loads (with no-growth tolerance)
let itemCount = 0;
let noGrowthStreak = 0;
const maxScrolls = 80;
let scrolls = 0;
while (scrolls < maxScrolls && noGrowthStreak < 3) {
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
await page.waitForTimeout(1200);
const newCount = await page.$$eval('.item', els => els.length);
if (newCount > itemCount) {
itemCount = newCount;
noGrowthStreak = 0;
} else {
noGrowthStreak += 1;
}
scrolls += 1;
}Detection cues: Intersection Observer in page JS, "Load more" button, sentinel element at bottom, network requests firing on scroll.
Multi-page results behind "Next" buttons or numbered pages.
// Click-through pagination (navigation-aware, SPA-safe)
const allData = [];
const maxPages = 50;
let pageIndex = 0;
while (pageIndex < maxPages) {
const pageData = await page.$$eval('.result-item', items =>
items.map(el => ({ title: el.querySelector('h3')?.textContent?.trim() }))
);
allData.push(...pageData);
const nextBtn = await page.$('a.next-page:not([disabled])');
if (!nextBtn) break;
const previousUrl = page.url();
const previousFirstItem = await page
.$eval('.result-item', el => el.textContent?.trim() || '')
.catch(() => '');
await nextBtn.click();
// Post-click detection only: advance must be caused by this click
const advanced = await Promise.any([
page
.waitForURL(url => url.toString() !== previousUrl, { timeout: 5000 })
.then(() => true),
page
.waitForFunction(
prev => {
const first = document.querySelector('.result-item');
return !!first && (first.textContent || '').trim() !== prev;
},
previousFirstItem,
{ timeout: 5000 }
)
.then(() => true),
]).catch(() => false);
if (!advanced) break;
await page.waitForLoadState('networkidle').catch(() => {});
pageIndex += 1;
}Identify from the user request:
# Try Actionbook index first
actionbook search "<site> <data-description>" --domain <domain>
# If good results (health ≥ 70%), get full selectors
actionbook get "<ID>"Use this routing strictly:
Path A (default when get is good): requested fields are covered by get selectors and quality is acceptable.
get selectors and move to script draft quickly.browser text, quick scroll checks) before finalizing script strategy.snapshot / screenshot) before first draft unless probe/sample validation shows mismatch.get selectors and mark source as actionbook_get.Path B (partial / unstable): get exists but required fields are missing, selector resolves 0 elements, or validation fails.
Path C (no usable coverage): search/get has no usable result.
Path A mechanism detection timing:
actionbook browser open "<url>" (if current tab context is unknown/stale)Fallback discovery by path:
Path B targeted fallback (only failed fields/steps):
actionbook browser open "<url>" # if not already open
actionbook browser snapshot # focus on failed field/container mapping
# actionbook browser screenshot # optional visual confirmation for failed areaPath C full fallback (no usable coverage):
actionbook browser open "<url>"
actionbook browser snapshot
actionbook browser screenshotMechanism probes (run when script strategy needs confirmation):
# Hydration / streaming check
actionbook browser text "<container-selector>"
# Infinite scroll quick signal (explicit before/after decision)
actionbook browser eval "document.querySelectorAll('<item-selector>').length" # before
actionbook browser click "<scroll-container-selector-or-body>" # focus scroll context
actionbook browser eval "const c=document.querySelector('<scroll-container-selector>') || document.scrollingElement; c.scrollBy(0, c.clientHeight || window.innerHeight);"
actionbook browser eval "document.querySelectorAll('<item-selector>').length" # after
# If count increases, treat page as lazy-load/infinite-scroll.Fallback trigger conditions:
actionbook get cannot map all required fields.actionbook get selectors return empty/unstable values in sample run.Write a standalone Playwright script (extract_<domain>_<slug>.cjs) that:
load — see mechanisms above).JSON.stringify / CSV).maxPages, maxScrolls, timeout budget) to avoid infinite loops.Script template:
// extract_<domain>_<slug>.cjs
// Generated by Actionbook extract skill
// Usage: node extract_<domain>_<slug>.cjs
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('<URL>', { waitUntil: 'domcontentloaded' });
// -- wait for readiness --
await page.waitForSelector('<container>', { state: 'visible' });
// -- extract --
const data = await page.$$eval('<item-selector>', items =>
items.map(el => ({
// fields mapped from user request
}))
);
// -- output --
const fs = require('fs');
fs.writeFileSync('output.json', JSON.stringify(data, null, 2));
console.log(`Extracted ${data.length} items → output.json`);
await browser.close();
})();Run the script to confirm it works:
node extract_<domain>_<slug>.cjsValidation rules:
| Check | Pass condition |
|---|---|
| Script exits 0 | No runtime errors |
| Output file exists | Non-empty file written |
| Record count > 0 | At least one item extracted |
| No null/empty fields | Every declared field has a value in ≥ 90% of records |
| Data matches page | Spot-check first and last record against actionbook browser text |
If validation fails, inspect the output, adjust selectors or wait strategy, and re-run.
Present to the user:
.cjs file they can re-run anytime.Every extract invocation produces:
| Artifact | Path | Format |
|---|---|---|
| Playwright script | ./extract_<domain>_<slug>.cjs | Standalone Node.js script using playwright |
| Extracted data | ./output.json (default) or user-specified path | JSON array of objects (default), CSV, or user-specified |
The script must be re-runnable — a user should be able to execute it later without Actionbook installed, as long as Node.js + Playwright are available in the runtime environment.
When multiple selector types are available from actionbook get:
| Priority | Type | Reason |
|---|---|---|
| 1 | data-testid | Stable, test-oriented, rarely changes |
| 2 | aria-label | Accessibility-driven, semantically meaningful |
| 3 | CSS selector | Structural, may break on redesign |
| 4 | XPath | Last resort, most brittle |
| Error | Action |
|---|---|
actionbook search returns no results | Fall back to snapshot + screenshot |
| Selector returns 0 elements | Re-snapshot, compare with screenshot, update selector |
| Script times out | Add longer waitForTimeout, check for anti-bot measures |
| Partial data (some fields empty) | Check if content is lazy-loaded; add scroll/wait |
| Anti-bot / CAPTCHA | Inform user; suggest running with headless: false or using their own browser session via actionbook setup extension mode |
© actionbook, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in skills/extract of actionbook/actionbook.
Open the folder on GitHubat commit 0e31254
We found 2 copies of this SKILL.md (exact, near-identical or edited) in other folders, from 2 other GitHub owners. This page covers the copy in actionbook/actionbook, which our catalogue first saw on October 7, 2026.
Extract next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Extract this skillactionbook/actionbook | 1.6k | 2 repos | ~3.4k | Automated safety check: Pass | Apache-2.0 | |
| Cloudflare Browser Renderingeinverne/dotfiles | 121 | — | ~4.9k | Automated safety check: Pass | GPL-3.0 | |
| Playwright Bowserdisler/bowser | 265 | — | ~1.1k | Automated safety check: Notes | None | |
| Anti Detect Browserantibrow/anti-detect-browser-skills | 914 | — | ~9.8k | Automated safety check: Warn | MIT | |
| Cloudflare Browser Renderingsecondsky/claude-skills | 227 | — | ~4k | Automated safety check: Pass | MIT | |
| Using Webctloaustegard/claude-skills | 150 | — | ~1.4k | Automated safety check: Pass | MIT |
einverne/dotfiles
Guide for implementing Cloudflare Browser Rendering - a headless browser automation API for screenshots, PDFs, web scraping, and testing.
disler/bowser
Headless browser automation using Playwright CLI. An agent skill from disler/bowser.
antibrow/anti-detect-browser-skills
Drive Chromium from standard Playwright APIs with a real-device fingerprint applied in the kernel, one persistent isolated profile per identity, and a per-profile proxy whose exit IP sets timezone…
secondsky/claude-skills
Cloudflare Browser Rendering with Puppeteer/Playwright. An agent skill from secondsky/claude-skills.
oaustegard/claude-skills
Browser automation via webctl CLI in Claude.ai containers with authenticated proxy support.
brightdata/skills
Generate working code that routes HTTP requests through Bright Data proxy networks (Datacenter, ISP, Residential, Mobile) and help users decide which network and IP pool type to use (shared pool…
actionbook/actionbook
Activate when the user needs to interact with any website — browser automation, web scraping, screenshots, form filling, UI testing, monitoring, or building AI agents.
actionbook/actionbook
Run browser-based web tests against websites using Actionbook CLI.
actionbook/actionbook
Browser action engine. An agent skill from actionbook/actionbook.
actionbook/actionbook
View, search, and download academic papers from arXiv. An agent skill from actionbook/actionbook.
actionbook/actionbook
CRITICAL: Use for json-ui component rendering and development.
actionbook/actionbook
Deep research and analysis tool. An agent skill from actionbook/actionbook.
Works with
Extract structured data from websites and produce an executable Playwright script plus extracted data. Extract is an agent skill from actionbook/actionbook. Extract structured data from websites and produce an executable Playwright script plus extracted data.
Extract fits situations like: the user wants to scrape; harvest data from any website — product listings; any repeating content.
Run `npx skills add actionbook/actionbook --skill extract -a claude-code`. Or copy the skill folder (skills/extract in actionbook/actionbook) into .claude/skills/extract in your project. Claude Code loads it when a task matches its description.
Run `npx skills add actionbook/actionbook --skill extract -a codex`. Or copy the skill folder (skills/extract in actionbook/actionbook) into .agents/skills/extract in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add actionbook/actionbook --skill extract -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/extract, .gemini/skills/extract, .github/skills/extract and .opencode/skills/extract in your project.
Going by SKILL.md and its folder, Extract needs the command-line tools its instructions call (node).
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Extract is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.4k tokens (SKILL.md is roughly 14k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Extract: Cloudflare Browser Rendering (einverne/dotfiles, 121 stars), Playwright Bowser (disler/bowser, 265 stars), Anti Detect Browser (antibrow/anti-detect-browser-skills, 914 stars) and Cloudflare Browser Rendering (secondsky/claude-skills, 227 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
actionbook (a GitHub organization) maintains it in actionbook/actionbook, which has 1,609 GitHub stars. The repository holds 13 skills in this directory. The repository was last updated on September 8, 2026.
Source: actionbook/actionbook on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.