web-access-claude-skill
Give Claude Code full internet access with three-layer channel dispatch, CDP browser automation, and parallel sub-agent task splitting
Best use case
web-access-claude-skill is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Give Claude Code full internet access with three-layer channel dispatch, CDP browser automation, and parallel sub-agent task splitting
Teams using web-access-claude-skill should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/web-access-claude-skill/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How web-access-claude-skill Compares
| Feature / Agent | web-access-claude-skill | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Give Claude Code full internet access with three-layer channel dispatch, CDP browser automation, and parallel sub-agent task splitting
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
Related Guides
SKILL.md Source
# Web Access Skill for Claude Code
> Skill by [ara.so](https://ara.so) — Daily 2026 Skills collection.
A skill that gives Claude Code complete internet access using three-layer channel dispatch (WebSearch / WebFetch / CDP), Chrome DevTools Protocol browser automation via a local proxy, parallel sub-agent task splitting, and cross-session site experience accumulation.
## What This Project Does
Claude Code ships with `WebSearch` and `WebFetch` but lacks:
- **Dispatch strategy** — knowing *when* to use which tool
- **Browser automation** — clicking, scrolling, file upload, dynamic pages
- **Accumulated site knowledge** — domain-specific patterns reused across sessions
Web Access fills all three gaps with:
| Capability | Detail |
|---|---|
| Auto tool selection | WebSearch / WebFetch / curl / Jina / CDP chosen per scenario |
| CDP Proxy | Connects directly to your running Chrome, inherits login state |
| Three click modes | `/click` (JS), `/clickAt` (real mouse events), `/setFiles` (upload) |
| Parallel dispatch | Multiple targets → sub-agents share one Proxy, tab-isolated |
| Site experience store | Per-domain URL patterns, quirks, traps — persisted across sessions |
| Media extraction | Pull image/video URLs from DOM, screenshot any video frame |
## Installation
**Option A — Let Claude install it:**
```
帮我安装这个 skill:https://github.com/eze-is/web-access
```
or in English:
```
Install this skill for me: https://github.com/eze-is/web-access
```
**Option B — Manual:**
```bash
git clone https://github.com/eze-is/web-access ~/.claude/skills/web-access
```
The skill file is `~/.claude/skills/web-access/SKILL.md`. Claude Code loads all `SKILL.md` files under `~/.claude/skills/` automatically.
## Prerequisites
### Node.js 22+
```bash
node --version # must be >= 22
```
### Enable Chrome Remote Debugging
1. Open `chrome://inspect/#remote-debugging` in your Chrome
2. Check **Allow remote debugging for this browser instance**
3. Restart Chrome if prompted
### Verify Dependencies
```bash
bash ~/.claude/skills/web-access/scripts/check-deps.sh
```
Expected output:
```
✅ Node.js 22.x found
✅ Chrome DevTools reachable at localhost:9222
✅ curl available
```
## CDP Proxy — Core Component
The proxy is a lightweight Node.js WebSocket bridge between Claude and your Chrome instance.
### Start the Proxy
```bash
# Start in background (auto-exits after 20 min idle)
node ~/.claude/skills/web-access/scripts/cdp-proxy.mjs &
# Confirm it's running
curl -s http://localhost:3456/ping
# → {"status":"ok"}
```
### Full HTTP API Reference
```bash
# ── Tab management ──────────────────────────────────────────
# Open new tab, returns tab ID
curl -s "http://localhost:3456/new?url=https://example.com"
# → {"targetId":"ABC123","url":"https://example.com"}
# Close a tab
curl -s "http://localhost:3456/close?target=ABC123"
# → {"closed":true}
# ── Page content ────────────────────────────────────────────
# Execute JavaScript, returns result
curl -s -X POST "http://localhost:3456/eval?target=ABC123" \
-d 'document.title'
# → {"result":"Example Domain"}
# Get full page HTML
curl -s -X POST "http://localhost:3456/eval?target=ABC123" \
-d 'document.documentElement.outerHTML'
# ── Interaction ─────────────────────────────────────────────
# JS click (fast, works for most buttons)
curl -s -X POST "http://localhost:3456/click?target=ABC123" \
-d 'button.submit'
# Real mouse click via CDP (use for upload triggers, canvas elements)
curl -s -X POST "http://localhost:3456/clickAt?target=ABC123" \
-d '.upload-btn'
# File upload via input element
curl -s -X POST "http://localhost:3456/setFiles?target=ABC123" \
-H "Content-Type: application/json" \
-d '{"selector":"input[type=file]","files":["/tmp/photo.png"]}'
# ── Navigation ──────────────────────────────────────────────
# Scroll to bottom
curl -s "http://localhost:3456/scroll?target=ABC123&direction=bottom"
# Scroll to top
curl -s "http://localhost:3456/scroll?target=ABC123&direction=top"
# ── Visual ──────────────────────────────────────────────────
# Screenshot to file
curl -s "http://localhost:3456/screenshot?target=ABC123&file=/tmp/shot.png"
# Screenshot returned as base64
curl -s "http://localhost:3456/screenshot?target=ABC123"
# → {"base64":"iVBORw0KGgo..."}
```
## Three-Layer Channel Dispatch
The skill teaches Claude to pick the right tool automatically:
```
Task type → Tool choice
─────────────────────────────────────────
General search query → WebSearch
Static page / docs / API → WebFetch or Jina
Login-gated / dynamic page → CDP Proxy
Heavy JS / SPA → CDP Proxy
Video / canvas interaction → CDP Proxy (clickAt)
Bulk text extraction → Jina (token-efficient)
Raw HTTP / custom headers → curl
```
### Jina Usage (Token-Efficient Reads)
```bash
# Jina converts any URL to clean markdown — great for docs/articles
curl -s "https://r.jina.ai/https://docs.example.com/api"
```
## Code Examples
### Example 1: Open a Page and Extract Data
```javascript
// Claude runs this flow via CDP Proxy
// 1. Open tab
const tabRes = await fetch('http://localhost:3456/new?url=https://news.ycombinator.com');
const { targetId } = await tabRes.json();
// 2. Wait for load, then extract top story titles
const evalRes = await fetch(`http://localhost:3456/eval?target=${targetId}`, {
method: 'POST',
body: `
Array.from(document.querySelectorAll('.titleline > a'))
.slice(0, 10)
.map(a => ({ title: a.textContent, href: a.href }))
`
});
const { result } = await evalRes.json();
console.log(JSON.parse(result));
// 3. Clean up
await fetch(`http://localhost:3456/close?target=${targetId}`);
```
### Example 2: Login-Gated Page (Uses Existing Chrome Session)
```javascript
// Chrome already has the user logged in — CDP inherits cookies automatically
async function scrapeAuthenticatedPage(url) {
// Open tab in the user's real Chrome — no login needed
const { targetId } = await fetch(`http://localhost:3456/new?url=${url}`)
.then(r => r.json());
// Wait for dynamic content
await fetch(`http://localhost:3456/eval?target=${targetId}`, {
method: 'POST',
body: `new Promise(r => setTimeout(r, 2000))`
});
// Extract content
const { result } = await fetch(`http://localhost:3456/eval?target=${targetId}`, {
method: 'POST',
body: `document.querySelector('.main-content')?.innerText`
}).then(r => r.json());
await fetch(`http://localhost:3456/close?target=${targetId}`);
return result;
}
```
### Example 3: File Upload Automation
```javascript
async function uploadFile(pageUrl, filePath) {
const { targetId } = await fetch(`http://localhost:3456/new?url=${pageUrl}`)
.then(r => r.json());
// Wait for page
await new Promise(r => setTimeout(r, 1500));
// Click the upload trigger button (real mouse event — required for some SPAs)
await fetch(`http://localhost:3456/clickAt?target=${targetId}`, {
method: 'POST',
body: '.upload-trigger-button'
});
await new Promise(r => setTimeout(r, 500));
// Set file on the (possibly hidden) input
await fetch(`http://localhost:3456/setFiles?target=${targetId}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
selector: 'input[type=file]',
files: [filePath]
})
});
// Submit
await fetch(`http://localhost:3456/click?target=${targetId}`, {
method: 'POST',
body: 'button[type=submit]'
});
// Screenshot to verify
await fetch(`http://localhost:3456/screenshot?target=${targetId}&file=/tmp/upload-result.png`);
await fetch(`http://localhost:3456/close?target=${targetId}`);
}
```
### Example 4: Parallel Research with Sub-Agents
```javascript
// Instruct Claude to dispatch parallel sub-agents like this:
const targets = [
'https://product-a.com',
'https://product-b.com',
'https://product-c.com',
'https://product-d.com',
'https://product-e.com'
];
// Each sub-agent opens its own tab (tab-isolated, same Proxy)
const results = await Promise.all(
targets.map(async (url) => {
const { targetId } = await fetch(`http://localhost:3456/new?url=${url}`)
.then(r => r.json());
await new Promise(r => setTimeout(r, 2000));
const { result } = await fetch(`http://localhost:3456/eval?target=${targetId}`, {
method: 'POST',
body: `({
title: document.title,
description: document.querySelector('meta[name=description]')?.content,
h1: document.querySelector('h1')?.textContent,
pricing: document.querySelector('[class*="pric"]')?.innerText?.slice(0,200)
})`
}).then(r => r.json());
await fetch(`http://localhost:3456/close?target=${targetId}`);
return { url, data: JSON.parse(result) };
})
);
console.table(results);
```
### Example 5: Video Frame Screenshot
```javascript
async function screenshotVideoAt(pageUrl, timestampSeconds) {
const { targetId } = await fetch(`http://localhost:3456/new?url=${pageUrl}`)
.then(r => r.json());
await new Promise(r => setTimeout(r, 3000));
// Seek video to timestamp
await fetch(`http://localhost:3456/eval?target=${targetId}`, {
method: 'POST',
body: `
const v = document.querySelector('video');
v.currentTime = ${timestampSeconds};
v.pause();
`
});
await new Promise(r => setTimeout(r, 500));
// Capture the frame
await fetch(`http://localhost:3456/screenshot?target=${targetId}&file=/tmp/frame-${timestampSeconds}s.png`);
await fetch(`http://localhost:3456/close?target=${targetId}`);
}
```
## Common Patterns
### Pattern: Check Proxy Before CDP Tasks
```bash
# Always verify proxy is up before a CDP workflow
curl -s http://localhost:3456/ping || \
node ~/.claude/skills/web-access/scripts/cdp-proxy.mjs &
```
### Pattern: Use Jina for Documentation
```bash
# Cheaper and cleaner than WebFetch for text-heavy pages
curl -s "https://r.jina.ai/https://api.anthropic.com/docs"
```
### Pattern: Prefer WebSearch for Discovery, CDP for Execution
```
1. WebSearch → find the right URLs
2. WebFetch → read static/public content
3. CDP → interact, authenticate, dynamic content
```
### Pattern: Extract All Media URLs
```javascript
// Get all images and videos on current page
const media = await fetch(`http://localhost:3456/eval?target=${targetId}`, {
method: 'POST',
body: `({
images: Array.from(document.images).map(i => i.src),
videos: Array.from(document.querySelectorAll('video source, video[src]'))
.map(v => v.src || v.getAttribute('src'))
})`
}).then(r => r.json());
```
## Troubleshooting
### Proxy won't start
```bash
# Check if port 3456 is already in use
lsof -i :3456
# Kill existing proxy
kill $(lsof -ti :3456)
# Restart
node ~/.claude/skills/web-access/scripts/cdp-proxy.mjs &
```
### Chrome not reachable
```bash
# Verify Chrome remote debugging is on
curl -s http://localhost:9222/json/version
# Should return Chrome version JSON
# If empty — go to chrome://inspect/#remote-debugging and enable it
```
### `/clickAt` has no effect
- The element may need scrolling into view first:
```bash
curl -s -X POST "http://localhost:3456/eval?target=ID" \
-d 'document.querySelector(".btn").scrollIntoView()'
```
- Then retry `/clickAt`
### Page content is empty / JS not rendered
```bash
# Add a wait after /new before /eval
curl -s -X POST "http://localhost:3456/eval?target=ID" \
-d 'new Promise(r => setTimeout(r, 3000))'
# Then fetch content
```
### File upload input not found
Some SPAs render `<input type=file>` only after the trigger click. Always:
1. `/clickAt` the visible upload button first
2. Wait 500ms
3. Then `/setFiles`
### Sub-agent tabs interfering
Each sub-agent should store its own `targetId` and never share it. The Proxy is stateless per-tab.
## Proxy Auto-Shutdown
The proxy exits automatically after **20 minutes of no requests**. For long-running tasks:
```bash
# Keep-alive ping in background
while true; do curl -s http://localhost:3456/ping > /dev/null; sleep 300; done &
```
## Site Experience Store
The skill accumulates domain knowledge in a local JSON store. When Claude visits `twitter.com`, it reads any saved notes about:
- Known working URL patterns
- Login flow quirks
- Selectors that are stable vs dynamic
- Rate limiting behavior
This persists across Claude sessions. The store lives at:
```
~/.claude/skills/web-access/data/site-experience.json
```
You can inspect or edit it manually to add your own domain knowledge.
## Project Structure
```
~/.claude/skills/web-access/
├── SKILL.md ← This skill file (loaded by Claude)
├── scripts/
│ ├── cdp-proxy.mjs ← CDP Proxy server (Node.js 22+)
│ └── check-deps.sh ← Dependency checker
└── data/
└── site-experience.json ← Accumulated domain knowledge
```
## Capability Summary for Task Routing
| User says | Claude should use |
|---|---|
| "Search for X" | WebSearch |
| "Read this URL" | WebFetch or Jina |
| "Go to my dashboard on X" | CDP (login state) |
| "Click the submit button on X" | CDP `/click` or `/clickAt` |
| "Upload this file to X" | CDP `/setFiles` |
| "Research these 5 products" | Parallel sub-agents via CDP |
| "Extract images from X" | CDP `/eval` + DOM query |
| "Screenshot X at 1:23 in the video" | CDP `/eval` seek + `/screenshot` |Related Skills
token-dashboard-claude-analytics
Local token cost analytics dashboard for Claude Code sessions — reads JSONL transcripts and provides per-prompt cost breakdowns, heatmaps, and usage insights.
permiso-accessibility-permissions
Permission dialog UI for macOS accessibility and privacy settings, replicating the Codex Computer Use guided permissions flow
openclaude-multi-llm
Use Claude Code's full tool system with any OpenAI-compatible LLM — GPT-4o, DeepSeek, Gemini, Ollama, and 200+ models via environment variable configuration.
oh-story-claudecode-writing
网文写作 skill 包,覆盖长篇与短篇网络小说的扫榜、拆文、写作、去AI味全流程
holyclaude-ai-workstation
Deploy a full AI coding workstation with Claude Code, web UI, headless browser, and 5 AI CLIs in a single Docker container
free-code-claude-cli
Build and use free-code, the open-source fork of Claude Code CLI with telemetry removed, guardrails stripped, and all experimental features unlocked.
everything-claude-code-harness
Agent harness performance system for Claude Code and other AI coding agents — skills, instincts, memory, hooks, commands, and security scanning
deepclaude-proxy
Use Claude Code's autonomous agent loop with DeepSeek V4 Pro, OpenRouter, or any Anthropic-compatible backend at up to 17x lower cost.
codeburn-claude-cost-dashboard
Interactive TUI dashboard for visualizing Claude Code token usage, costs, and task breakdowns by project, model, and activity type.
clui-cc-claude-overlay
Command Line User Interface for Claude Code — a floating macOS desktop overlay with multi-tab sessions, permission approval UI, voice input, and skills marketplace.
clawgod-claude-code-patch
Runtime patch for Claude Code that unlocks hidden features, removes restrictions, and enables advanced capabilities like multi-agent swarms and computer use.
claude-skill-app-onboarding-questionnaire
Claude Code skill that designs and builds high-converting questionnaire-style app onboarding flows modelled on proven conversion patterns from top subscription apps like Noom, Headspace, and Duolingo.