MCP server
WebSkrap ships a Model Context Protocol
server. MCP clients such as Claude Desktop, Claude Code, and Codex can call it to
drive a real browser directly. It runs over stdio and exposes fetch tools for
one-shot scraping plus browser_* tools for persistent interactive sessions.
Both fetch and stealth_fetch run the same CDP-leak-free Patchright stealth
path the CLI uses (headless Chrome, networkidle wait), so JS-heavy and
anti-bot pages that block naive scrapers still load. They return clean visible
page text by default, with no HTML tags, scripts, or CSS noise, so the model
spends tokens on content instead of markup (typically 5-10x fewer tokens than
raw HTML). Use stealth_fetch for finer fingerprint/WebRTC/UA control. Pass
text_only=false when you need the HTML.
Install
pip install webskrap
webskrap installRun the server:
webskrap-mcpYou can also run it as a module:
python -m webskrap.mcp_serverTools
| Tool | Purpose |
|---|---|
fetch |
Fetch a URL with the Patchright stealth driver (waits for networkidle). |
stealth_fetch |
Same stealth driver with finer fingerprint/WebRTC/UA controls. |
search |
Find URLs for a query on Bing (default) or DuckDuckGo, with the stealth_fetch stealth controls. |
doctor |
Check that Patchright and Chromium can launch. |
browser_open |
Start (or reuse) a persistent headless browser session. |
browser_goto |
Navigate the session's current page. |
browser_snapshot |
Aria snapshot of the page with eN element refs. |
browser_interact |
Click, fill, type, select, hover, check, or uncheck an element. |
browser_press |
Press a keyboard key on the page. |
browser_screenshot |
Screenshot the current page to a PNG file. |
browser_eval |
Evaluate JavaScript and return the result. |
browser_close |
Close a session (delete_data removes its profile). |
browser_list |
List sessions and whether each is running. |
Both fetch tools return status, final_url, title, ok, headers, and the
page content in text (capped by max_chars, with text_length and
text_truncated reporting the full size). By default text is clean visible
text; set text_only to false to get raw HTML.
Both also auto-decline cookie banners before reading the page, and report which
strategy fired in cookie_notice_declined. Pass decline_cookies: false to
leave the notice in place.
Tool arguments
fetch accepts:
| Argument | Default | Notes |
|---|---|---|
url |
required | URL to load. |
profile |
desktop-chrome |
Profile label; native Patchright defaults remain authoritative. |
channel |
chrome |
Browser channel; use chromium on Linux ARM64. |
wait_until |
networkidle |
commit, domcontentloaded, load, or networkidle. |
resource_policy |
all |
all, lite, or documents. |
timeout_ms |
60000 |
Navigation timeout. |
max_chars |
20000 |
Maximum returned text characters. |
text_only |
true |
Return clean visible text; set false for raw HTML. |
decline_cookies |
true |
Click a cookie consent notice's reject button after load. |
Example arguments:
{
"url": "https://example.com",
"profile": "desktop-chrome",
"resource_policy": "lite",
"wait_until": "load",
"max_chars": 5000
}stealth_fetch accepts the same URL/profile/timeout/output-size controls plus
Patchright options:
{
"url": "https://example.com",
"channel": "chrome",
"headless": false,
"patchright_context_profile": false,
"reduce_fingerprint_surface": false,
"mask_headless_user_agent": false,
"webrtc_ip_handling_policy": null
}When user_data_dir is set, it must be relative to
~/.webskrap/profiles. Set WEBSKRAP_MCP_PROFILE_DIR in the MCP server
environment to move that root. Absolute paths, .. traversal, and symlinks
resolving outside the root are rejected. This confinement applies only to MCP
tool input; Python callers can still choose any SessionConfig.user_data_dir.
search takes query, engine (bing by default, or ddg), max_results, and the
channel, profile, fingerprint and user_data_dir arguments stealth_fetch
takes. It returns hits (title, url, snippet) with the engine's
click-tracking unwrapped, plus hits_total and hits_truncated. Google is
not offered. A blocked error means the engine served a bot challenge.
Switch engine or exit IP instead of retrying.
Interactive browser tools
The browser_* tools drive the same persistent sessions as
webskrap browser in the
CLI: browser_open launches a detached headless Chromium that keeps running
between tool calls (and between MCP server restarts), and every other tool
reconnects to it over CDP. Sessions are named (session, default default)
and store their profile under ~/.webskrap/browser/<name>/
(root overridable with WEBSKRAP_BROWSER_DIR), so cookies and logins persist.
A typical flow:
browser_openwith an optionalurl.browser_snapshot, where each element carries a ref like[ref=e15].browser_interactwithaction: "click"andtarget: "e15"(or any Playwright selector).fillandtypetake one entry invalues;selecttakes one or more.browser_evalorbrowser_screenshotto read results.browser_closewhen done (delete_data: trueto drop the profile).
Snapshots are truncated to max_chars (default 20000) and report
snapshot_truncated; refs describe the current DOM, so take a fresh snapshot
after the page changes. Failed actions return a one-line error.
Screenshot output is confined
browser_screenshot writes only under ./webskrap-output, relative to the
directory the server runs in. Set WEBSKRAP_OUTPUT_DIR to move that root, and
point it somewhere you are willing to have written to, not a source tree or
$HOME.
path is a relative destination inside that root. Nested paths work
(runs/today/page.png, directories created as needed); absolute paths, ..
traversal, and symlinks leaving the root are rejected before the browser is
touched. The model driving these tools reads untrusted pages, so its file
destinations are treated as untrusted input.
Chromium sandbox
MCP sessions keep Chromium's OS sandbox. Hosts that cannot sandbox must set
WEBSKRAP_CHROMIUM_SANDBOX=0 in the server's environment; it is deliberately
not a tool argument, so a page cannot talk the model into weakening renderer
isolation. Session profiles under ~/.webskrap/browser/<name>/ are created
0700 on POSIX.
Limitations, the same as the CLI: one page per session, bundled Chromium only,
and no tools for tabs, network mocking, tracing, or video. MCP sessions are
always headless. The CLI additionally offers back, forward, reload, and
headed mode.
Register with a client
Claude Code
claude mcp add webskrap -- webskrap-mcpClaude Desktop
{
"mcpServers": {
"webskrap": {
"command": "webskrap-mcp"
}
}
}Codex
Add a server entry to ~/.codex/config.toml:
[mcp_servers.webskrap]
command = "webskrap-mcp"
args = []Stealth
stealth_fetch uses the Patchright driver and accepts the same controls as the
Stealth guide, including
channel, headless, user_data_dir, patchright_context_profile,
reduce_fingerprint_surface, mask_headless_user_agent, and
webrtc_ip_handling_policy.
For headless best-effort stealth from MCP, use real Chrome and opt in only to the native browser controls you need:
{
"url": "https://example.com",
"channel": "chrome",
"headless": true,
"user_data_dir": "headless-profile",
"mask_headless_user_agent": true,
"patchright_context_profile": true,
"webrtc_ip_handling_policy": "disable_non_proxied_udp"
}