Crawlio Browser
About
100-tool browser automation for AI agents via MCP. Screenshots, DOM inspection, network capture, form filling, cookie management, tab orchestration, session recording, and structured data extraction via Chrome extension. One-command setup: npx crawlio-browser init auto-configures
Details
- Author
- Crawlio-app
- Downloads
- 402
- Categories
- Automation, Web Scraping
Jump to
- 100 tools: 93 browser + 3 extraction + 3 recording + 1 compiler
- Framework-aware intelligence: detects 17 frameworks at runtime
- Evidence-based analysis with typed CoverageGap records
- Session recording and replay, compilable into SKILL.md automations
- Auto-settling: actionability checks and progressive backoff after mutations
- Tethered IPC bridge with WebSocket, heartbeat, and auto-reconnect
Setting up with Highlight
This MCP is not yet compatible with Highlight’s one-click setup. However, you can still use it with Highlight by following these steps:
- Download and install Highlight from highlightai.com/download
- Navigate to the plugins tab and select "Add Custom Plugin"
-
Configure the plugin with the settings below
Plugin Name
Crawlio BrowserCommand (node, npx, python, etc.)Please refer to the README for specific instructions on how to obtain API keys or other required environment variables.
- Enable "Start Automatically" if you want the plugin to start when Highlight launches
From the repository
Install the Chrome extension, then run npx crawlio-browser init to auto-configure for 14 MCP clients. Alternatively, use manual configuration per client (e.g., Claude Desktop, Cursor, Windsurf). Transport modes include stdio (JSON‑RPC over stdin/stdout), Portal HTTP (Streamable HTTP), and Portal SSE (Server-Sent Events). Portal mode is recommended for Claude Code as it persists across session restarts.
search
Search available commands by keyword — both browser automation (via bridge.send) and Crawlio HTTP endpoints (via crawlio.api). Returns matching command names, descriptions, and parameter schemas. Use this to discover what commands are available before writing execute() code.
execute
Execute JavaScript code with access to the browser bridge, Crawlio HTTP client, and smart object. Use search() first to discover available commands and their parameters. IMPORTANT WARNINGS: - smart.screenshot() does NOT exist. For screenshots: bridge.send({ type: 'take_screenshot' }). - For structured page evidence, prefer smart.extractPage() — runs 7 ops in parallel with typed gaps[]. - capture_page returns a ~1KB shaped summary. For raw data, use stop_network_capture or get_console_logs. - Use smart.waitForIdle() instead of sleep(). Use smart.scrollCapture() instead of manual scroll loops. - smart.snapshot() takes no options or { interactive: true } — there is no { compact: true } option. - For cross-page navigation, use smart.navigate(url) — never location.href = "..." (breaks CDP). Available in scope: - bridge.send(command, timeout?) — send command to browser extension via WebSocket command must have a `type` field matching a command name (e.g. { type: 'list_tabs' }) - crawlio.api(method, path, body?) — generic HTTP to ControlServer e.g. await crawlio.api('GET', '/status') e.g. await crawlio.api('POST', '/start', { url: 'https://example.com' }) e.g. await crawlio.api('POST', '/export', { format: 'zip', destinationPath: '/tmp/site.zip' }) e.g. await crawlio.api('PATCH', '/settings', { settings: { maxConcurrent: 8 } }) Returns { status: number, data: unknown } - crawlio.getStatus() — shortcut for GET /status - crawlio.startCrawl(url) — shortcut for POST /start - crawlio.getEnrichment(url?) — shortcut for GET /enrichment - crawlio.getCrawledURLs(params?) — shortcut for GET /crawled-urls - crawlio.postEnrichment(url, data) — shortcut for POST /enrichment/bundle - sleep(ms) — async wait (max 30s) - TIMEOUTS — per-command timeout constants - compileRecording(session, { name, description? }) — compile RecordingSession to SKILL.md Returns { skillMarkdown, name, pageCount, interactionCount } - ocrScreenshot(opts?) — extract text from current page via macOS Vision.framework OCR (macOS only) opts: { fullPage?: boolean, selector?: string } Returns { regions: [{ text, confidence, bounds }], regionsLimited? } - smart — auto-waiting wrappers and framework-specific data accessors: smart.evaluate(expr) → {result, type} — access .result for value. Never JSON.parse() the return directly. smart.click(selector, opts?) — poll + click + 500ms settle (accepts CSS or snapshot [ref=X]) smart.type(selector, text, opts?) — poll + type + 300ms settle smart.navigate(url, opts?) — navigate + 1000ms settle smart.waitFor(selector, timeout?) — poll until actionable smart.snapshot(opts?) — capture accessibility snapshot (opts: { interactive: true } for clickable elements only — NO compact option) smart.scrollCapture(opts?) — state-aware page scroll with screenshots, stops at page bottom smart.waitForIdle(timeout?) — wait for DOM mutations to settle (500ms quiet window) smart.extractPage(opts?) — capture_page + perf + security + fonts + meta + accessibility + mobileReadiness. Returns { capture, performance, security, fonts, meta, accessibility, mobileReadiness, gaps[] }. opts: { trace: true } adds _trace. smart.comparePages(urlA, urlB, opts?) — navigate to each URL, run extractPage(), return { siteA, siteB, scaffold }. scaffold has dimensions[], sharedFields, missingFields, metrics. smart.finding({ claim, evidence, sourceUrl, confidence, method, dimension? }) — create validated Finding, accumulate in session. Confidence auto-capped if dimension has active gap with reducesConfidence. smart.findings() — return all accumulated Finding[] from current session. smart.clearFindings() — reset accumulated findings and session gaps. smart.detectTables(opts?) — find repeating data patterns in the page. Returns TableCandidate[] (selector, score, rowCount, sampleText). Uses class-frequency scoring. smart.extractTable(selector, opts?) — extract structured data from a container. Returns { columns, rows, totalRows, truncated }. opts: { maxRows: 200 }. smart.waitForNetworkIdle(opts?) — wait for all network requests to settle (CDP-level, catches fetch/XHR/images/CSS/fonts). Returns { status, elapsed }. opts: { timeout: 15000, idleTime: 500 }. smart.extractData(opts?) — compound: detectTables + extractTable + JSON-LD. Returns { tables, structuredData, url }. smart.parseTrackingPixels() — parse captured network data for tracking pixel fires (Facebook, GA4, TikTok, LinkedIn, Pinterest). Returns { totalPixelFires, vendors, pixels, events, unrecognizedTrackingUrls }. smart.validateTracking() — validate tracking events against per-vendor parameter schemas (Facebook 18 standard + GA4 recommended). Returns { events, issues, errorCount, warningCount, infoCount, isHealthy }. Each issue has severity (error/warning/info), code, message, recommendation, and optional parameter. smart.inspectDataLayer() — inspect tracker runtime state via CDP (fbq queue, GA4 dataLayer, GTM containers, TikTok ttq). Returns DataLayerState with null for absent trackers. No content script needed. smart.detectDuplicates() — detect duplicate pixel fires grouped by vendor+pixelId+eventName+URL. Excludes PageView (legitimate SPA behavior). Returns DuplicateCluster[] with count and timestamps. smart.detectTechnologies(opts?) — detect technologies via fingerprint matching against CDP signals (headers, scripts, JS globals, meta, cookies, URL). Returns TechnographicResult { technologies[], categories, totalDetected, highConfidenceCount, signalsUsed }. Each technology has numeric confidence (0-100, additive), version, matchedSignals[]. opts: { confidenceThreshold: 1 }. smart.diffSnapshots(before?) — Myers diff current ARIA snapshot against baseline. If before omitted, uses last cached snapshot. Returns { diff, additions, removals, unchanged, changed }. Framework namespaces (injected based on detected framework): smart.react.{getVersion,getRootCount,hasProfiler,isHookInstalled} smart.vue.{getVersion,getAppCount,getConfig,isDevMode} smart.angular.{getVersion,isDebugMode,isIvy,getRootCount,getState} smart.svelte.{getVersion,getMeta,isDetected} smart.redux.{isInstalled,getStoreState} smart.alpine.{getVersion,getStoreKeys,getComponentCount} smart.nextjs.{getData,getRouter,getSSRMode,getRouteManifest} smart.nuxt.{getData,getConfig,isSSR} smart.remix.{getContext,getRouteData} smart.gatsby.{getData,getPageData} smart.shopify.{getShop,getCart} smart.wordpress.{isWP,getRestUrl,getPlugins} smart.laravel.{getCSRF} | smart.django.{getCSRF} | smart.drupal.{getSettings} smart.jquery.{getVersion} Example (HTTP API): const { data } = await crawlio.api('GET', '/status'); return data; Example (browser): const tabs = await bridge.send({ type: 'list_tabs' }, 5000); return tabs; Example (smart — auto-waiting click): await smart.click('#submit-btn'); return await smart.snapshot(); Example (smart — framework data): const nextData = await smart.nextjs?.getData(); return { page: nextData?.page, buildId: nextData?.buildId }; Example (session recording + compile): const s = await bridge.send({ type: 'start_recording', maxDurationSec: 120 }); // ... interact with page ... const session = await bridge.send({ type: 'stop_recording' }); const skill = compileRecording(session, { name: 'my-flow' }); return skill; IMPORTANT: Keep scripts fast (<15s). Each smart.click costs ~1-2s. Never loop 5+ clicks — use smart.evaluate to read DOM data in bulk instead. IMPORTANT: smart.evaluate returns {result, type}. Access .result for the value. Never JSON.stringify inside evaluate then JSON.parse outside — just return objects directly.
connect_tab
Pin a specific browser tab for all subsequent commands. Optional — without this, tools auto-connect to the active tab. Three modes: (1) provide a URL to find or create a tab, (2) provide a tabId to connect to a specific tab, (3) no args to pin the active tab. Starts CDP capture automatically.
Claude Desktop / Cursor
Paste into your MCP client config file to install this server.
{
"mcpServers": {
"crawlio browser": {
"crawlio-browser": {
"command": "npx",
"args": [
"-y",
"crawlio-browser"
]
}
}
}
}
McpServers
{
"crawlio-browser": {
"command": "npx",
"args": [
"-y",
"crawlio-browser"
]
}
}
Crawlio Agent
Documentation | API Reference | Chrome Extension
MCP server that gives AI full control of a live Chrome browser via CDP. 100 tools (93 browser + 3 extraction + 3 recording + 1 compiler) with framework-aware intelligence, typed evidence infrastructure, and confidence-tracked findings — captures what static crawlers can't see.
> Note: This repo supersedes crawlio-browser-mcp. All development now happens here.
Links:
- Chrome Web Store
- Documentation
- Website
When to use Crawlio Agent
Use Crawlio Agent when your AI needs to interact with a real browser — SPAs, authenticated pages, dynamic content, JS-rendered frameworks. Unlike headless browser tools, Crawlio Agent connects to your actual Chrome via a lightweight extension, giving the AI access to your logged-in sessions, cookies, and full browser state.
Crawlio Agent vs headless browser tools: Headless tools launch a separate browser process. Crawlio Agent connects to your existing Chrome — no separate browser, no login flows, full access to your tabs and sessions.
Quick Start
1. Install the Chrome Extension
2. Run the init wizard:
npx crawlio-browser init
That's it. Auto-detects and configures 14 MCP clients: Claude Code, Cursor, VS Code, Codex, Gemini CLI, Claude Desktop, ChatGPT Desktop, Windsurf, Cline, Zed, Goose, OpenCode, MCPorter, and Cline CLI.
Init wizard options
npx crawlio-browser init # Default: code mode, stdio transport
npx crawlio-browser init --full # Full mode (100 individual tools)
npx crawlio-browser init --portal # Portal mode (persistent HTTP server)
npx crawlio-browser init --cloudflare # Add Cloudflare MCP (89 tools, no wrangler)
npx crawlio-browser init --dry-run # Show what would happen
npx crawlio-browser init --yes # Skip prompts (CI / scripted installs)
npx crawlio-browser init -a claude # Target specific MCP client
Transport Modes
| Mode | Command / URL | Protocol | Best For |
|------|--------------|----------|----------|
| stdio | npx crawlio-browser | JSON-RPC over stdin/stdout | Claude Desktop, Cursor, Windsurf — client manages process lifecycle |
| Portal (HTTP) | POST http://127.0.0.1:3001/mcp | MCP Streamable HTTP | Claude Code, ChatGPT Desktop — server survives session restarts |
| Portal (SSE) | GET /sse + POST /message | Server-Sent Events | Legacy clients needing SSE transport |
Portal mode is recommended for Claude Code — the server persists across context compaction and session restarts. On macOS, --portal installs a launchd agent for auto-start on login.
Manual setup (any client)
<details>
<summary><b>Per-client manual config</b></summary>
Claude Desktop — add to claude_desktop_config.json:
{ "mcpServers": { "crawlio-browser": { "command": "npx", "args": ["-y", "crawlio-browser"] } } }
Claude Code (Portal Mode) — start npx crawlio-browser --portal, then add to .mcp.json:
{ "mcpServers": { "crawlio-browser": { "type": "http", "url": "http://127.0.0.1:3001/mcp" } } }
Claude Code (stdio):
claude mcp add crawlio-browser -- npx -y crawlio-browser
Cursor — add to .cursor/mcp.json:
{ "mcpServers": { "crawlio-browser": { "command": "npx", "args": ["-y", "crawlio-browser"] } } }
Windsurf — add to Windsurf Settings > MCP:
{ "mcpServers": { "crawlio-browser": { "command": "npx", "args": ["-y", "crawlio-browser"] } } }
Cline (VS Code) — add to settings.json:
{ "cline.mcpServers": { "crawlio-browser": { "command": "npx", "args": ["-y", "crawlio-browser"] } } }
ChatGPT Desktop — Settings > Integrations > MCP:
URL: http://127.0.0.1:3001/mcp | Type: Streamable HTTP
</details>
How It Works
AI Client (stdio/http) --> MCP Server (Node.js) --> Chrome Extension (MV3)
crawlio-browser WebSocket -> CDP
The MCP server communicates with the Chrome extension via WebSocket. The extension controls the browser through Chrome DevTools Protocol (CDP).
Capabilities
Framework-Aware Intelligence
Every execute call probes the browser for framework signatures and injects a shape-shifting smart object with framework-native accessors. React state, Vue reactivity, Next.js routing, Shopify cart data — 17 framework namespaces across 4 tiers, detected at runtime and rebuilt on every navigation. The AI doesn't query a generic DOM; it queries the framework's own data structures.
Evidence-Based Analysis
Method Mode adds higher-order methods and a typed evidence system on top of Code Mode. smart.extractPage() runs 7 parallel operations in a single call — page capture, performance metrics, security state, font detection, meta extraction, accessibility audit, and mobile-readiness check. Failed operations produce typed CoverageGap records instead of silent nulls. Findings created with smart.finding() get their confidence automatically adjusted when supporting data is missing. The result: structured, auditable research output with gap tracking and confidence propagation.
Session Recording & Replay
Record browser interactions as structured data, then compile them into reusable SKILL.md automations. 12 interaction tools are automatically intercepted during recording — clicks, typing, navigation, scrolling — each capturing args, result, timing, and page URL. One compileRecording() call converts the session into a deterministic automation script.
Auto-Settling & Actionability
Every mutative action (click, type, navigate, select_option) runs actionability checks before acting — polling visibility, dimensions, enabled state, and overlay detection. After the action, a progressive backoff settle delay ([0, 20, 100, 100, 500]ms) waits for DOM mutations to quiesce. The AI doesn't need manual sleep() calls between actions.
Architecture: JIT Context Runtime
The JIT Context MCP Runtime is a layered execution architecture where each layer absorbs a category of complexity that would otherwise fall on the model. The model sees three tools and a clean SDK. Everything beneath that surface is the runtime absorbing reality.
…
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.


