agent-skill/Scrapling-Skill/references/mcp-server.md
The Scrapling MCP server exposes thirteen tools over the MCP protocol. It supports CSS-selector-based content narrowing (reducing tokens by extracting only relevant elements before returning results), three levels of scraping capability (plain HTTP, browser-rendered, and stealth/anti-bot bypass), persistent browser session management, and page screenshots returned as real image content blocks. Fetch tools come in two modes: one-shot tools (fetch, bulk_fetch, stealthy_fetch, bulk_stealthy_fetch) each launch and close their own browser, while session_fetch and session_make_request work through sessions opened with open_session/open_request_session.
All scraping tools return a ResponseModel with fields: status (int), content (list of strings), url (str). The screenshot tool returns a list of MCP content blocks: an ImageContent (the screenshot bytes) followed by a TextContent (the post-redirect URL).
make_request -- HTTP request, any method (single URL)Fast HTTP request with browser fingerprint impersonation (TLS, headers). Supports GET (default), POST, PUT, and DELETE via the method parameter. Suitable for static pages with no/low bot protection.
Key parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
url | str | required | URL to fetch |
method | "GET" / "POST" / "PUT" / "DELETE" | "GET" | HTTP method |
data | dict or str or null | null | Request body (form data). POST/PUT/DELETE only |
json | dict or list or null | null | Request body (JSON). POST/PUT/DELETE only |
extraction_type | "markdown" / "html" / "text" | "markdown" | Output format |
css_selector | str or null | null | CSS selector to narrow content (applied after main_content_only) |
main_content_only | bool | true | Restrict to <body> content |
impersonate | str | "chrome" | Browser fingerprint to impersonate |
proxy | str or null | null | Proxy URL, e.g. "http://user:pass@host:port" |
proxy_auth | dict or null | null | {"username": "...", "password": "..."} |
auth | dict or null | null | HTTP basic auth, same format as proxy_auth |
timeout | number | 30 | Seconds before timeout |
retries | int | 3 | Retry attempts on failure |
retry_delay | int | 1 | Seconds between retries |
stealthy_headers | bool | true | Generate realistic browser headers and Google referer |
http3 | bool | false | Use HTTP/3 (may conflict with impersonate) |
follow_redirects | bool or "safe" | "safe" | Follow redirects. "safe" rejects redirects to internal/private IPs |
max_redirects | int | 30 | Max redirects (-1 for unlimited) |
headers | dict or null | null | Custom request headers |
cookies | dict or null | null | Request cookies |
params | dict or null | null | Query string parameters |
verify | bool | true | Verify HTTPS certificates |
bulk_get -- HTTP GET request (multiple URLs)Async concurrent GET-only version of make_request. Same parameters except url is replaced by urls (list of strings) and there are no method/data/json parameters. All URLs are fetched in parallel. Returns a list of ResponseModel.
fetch -- Browser fetch (single URL)Opens a Chromium browser via Playwright to render JavaScript. Suitable for dynamic/SPA pages with no/low bot protection.
Key parameters (beyond shared ones):
| Parameter | Type | Default | Description |
|---|---|---|---|
url | str | required | URL to fetch |
extraction_type | str | "markdown" | "markdown" / "html" / "text" |
css_selector | str or null | null | Narrow content before extraction |
main_content_only | bool | true | Restrict to <body> |
headless | bool | true | Run browser hidden (true) or visible (false) |
proxy | str or dict or null | null | String URL or {"server": "...", "username": "...", "password": "..."} |
timeout | number | 30000 | Timeout in milliseconds |
wait | number | 0 | Extra wait (ms) after page load before extraction |
wait_selector | str or null | null | CSS selector to wait for before extraction |
wait_selector_state | str | "attached" | State for wait_selector: "attached" / "visible" / "hidden" / "detached" |
network_idle | bool | false | Wait until no network activity for 500ms |
disable_resources | bool | false | Block fonts, images, media, stylesheets, etc. for speed |
google_search | bool | true | Set a Google referer header |
real_chrome | bool | false | Use locally installed Chrome instead of bundled Chromium |
cdp_url | str or null | null | Connect to existing browser via CDP URL |
extra_headers | dict or null | null | Additional request headers |
useragent | str or null | null | Custom user-agent (auto-generated if null) |
cookies | list or null | null | Playwright-format cookies |
timezone_id | str or null | null | Browser timezone, e.g. "America/New_York" |
locale | str or null | null | Browser locale, e.g. "en-GB" |
This is a one-shot tool: it always launches its own browser. To fetch through a persistent session, use session_fetch.
bulk_fetch -- Browser fetch (multiple URLs)Concurrent browser version of fetch. Same parameters except url is replaced by urls (list of strings). Each URL opens in a separate browser tab. Returns a list of ResponseModel.
stealthy_fetch -- Stealth browser fetch (single URL)Anti-bot bypass fetcher with fingerprint spoofing. Use this for sites with Cloudflare Turnstile/Interstitial or other strong protections.
Additional parameters (beyond those in fetch):
| Parameter | Type | Default | Description |
|---|---|---|---|
solve_cloudflare | bool | false | Automatically solve Cloudflare Turnstile/Interstitial challenges |
hide_canvas | bool | false | Add noise to canvas operations to prevent fingerprinting |
block_webrtc | bool | false | Force WebRTC to respect proxy settings (prevents IP leak) |
allow_webgl | bool | true | Keep WebGL enabled (disabling is detectable by WAFs) |
additional_args | dict or null | null | Extra Playwright context args (overrides Scrapling defaults) |
All parameters from fetch are also accepted. Like fetch, this is a one-shot tool that launches its own browser; use session_fetch for a stealthy session.
bulk_stealthy_fetch -- Stealth browser fetch (multiple URLs)Concurrent stealth version. Same parameters as stealthy_fetch except url is replaced by urls (list of strings). Returns a list of ResponseModel.
open_session -- Create a persistent browser sessionOpens a browser session that stays alive across multiple session_fetch calls, avoiding the overhead of launching a new browser each time. It holds the browser-level configuration only; per-request options are passed to session_fetch. For plain HTTP requests without a browser, use open_request_session instead. Returns a SessionCreatedModel with session_id, session_type, created_at, is_alive, settings (the session's effective configuration for the AI agent; empty for CDP sessions), and message.
Key parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
session_type | "dynamic" / "stealthy" | required | Type of browser session to create |
session_id | str or null | null | Custom ID for the session. If omitted, a random 12-char hex ID is generated. Raises if already in use |
headless | bool | true | Run browser hidden or visible |
hide_canvas | bool | false | (Stealthy only) Canvas fingerprint noise |
block_webrtc | bool | false | (Stealthy only) Block WebRTC IP leak |
allow_webgl | bool | true | (Stealthy only) Keep WebGL enabled |
Plus the other browser-level session parameters (proxy, real_chrome, cdp_url, locale, timezone_id, useragent, cookies, executable_path, additional_args). Per-request options (timeout, wait, google_search, network_idle, disable_resources, wait_selector, wait_selector_state, extra_headers, solve_cloudflare) are not set here; pass them to session_fetch.
One session_fetch works with either browser session type; solve_cloudflare only applies to a stealthy session.
open_request_session -- Create a persistent HTTP requests sessionOpens an HTTP session (no browser) that stays alive across multiple session_make_request calls, keeping cookies, connections, and the browser fingerprint between requests. Returns the same SessionCreatedModel receipt and shows in list_sessions as a static session.
| Parameter | Type | Default | Description |
|---|---|---|---|
session_id | str or null | null | Custom ID for the session. If omitted, a random 12-char hex ID is generated. Raises if already in use |
impersonate | str | "chrome" | Browser fingerprint to impersonate on every request |
proxy | str or null | null | Proxy URL used for every request, e.g. "http://user:pass@host:port" |
session_fetch -- Fetch through an open browser session (single URL)Fetches one URL through a browser session opened with open_session (dynamic or stealthy). The session holds the browser-level configuration; every parameter here applies to this request only. Raises on a requests session; use session_make_request there instead.
| Parameter | Type | Default | Description |
|---|---|---|---|
url | str | required | URL to fetch |
session_id | str | required | ID of an open session created with open_session |
extraction_type | str | "markdown" | "markdown" / "html" / "text" |
css_selector | str or null | null | Narrow content before extraction |
main_content_only | bool | true | Restrict to <body> |
wait | number | 0 | Extra wait (ms) after page load before extraction |
timeout | number | 30000 | Timeout in milliseconds |
google_search | bool | true | Set a Google referer header |
network_idle | bool | false | Wait until no network activity for 500ms |
load_dom | bool | true | Wait for the page's JavaScript to fully load and execute |
disable_resources | bool | false | Block fonts, images, media, stylesheets, etc. for speed |
wait_selector | str or null | null | CSS selector to wait for before extraction |
wait_selector_state | str | "attached" | State for wait_selector: "attached" / "visible" / "hidden" / "detached" |
extra_headers | dict or null | null | Additional request headers |
blocked_domains | list or null | null | Domain names to block for this request (subdomains matched too) |
solve_cloudflare | bool | false | (Stealthy sessions only) Auto-solve Cloudflare challenges; errors on a dynamic session |
session_make_request -- HTTP request through an open requests sessionMakes an HTTP request (any method) through a session opened with open_request_session, reusing its cookies, connections, and browser fingerprint across calls. Same parameters as make_request plus a required session_id, minus the session-level impersonate, proxy, and proxy_auth. Raises on a browser session.
close_session -- Close a persistent sessionCloses a session (browser or requests) and frees its resources. Always close sessions when done.
| Parameter | Type | Default | Description |
|---|---|---|---|
session_id | str | required | Session ID from open_session |
Returns a SessionClosedModel with session_id and message.
list_sessions -- List active sessionsReturns a list of SessionInfo objects, each with session_id, session_type, created_at, is_alive, and settings (same as open_session returns).
No parameters.
screenshot -- Capture a page screenshotNavigates to a URL inside an existing browser session and returns the screenshot as an MCP ImageContent block (the bytes the model can see directly, not a base64 string in JSON) followed by a TextContent block carrying the post-redirect URL.
Requires an open browser session. Call open_session first, then pass the session_id here. Both dynamic and stealthy sessions are accepted.
| Parameter | Type | Default | Description |
|---|---|---|---|
url | str | required | URL to navigate to and capture |
session_id | str | required | ID of an open browser session created with open_session |
image_type | "png" / "jpeg" | "png" | Image format. Use "jpeg" for smaller payloads |
full_page | bool | false | Capture the full scrollable page instead of just the viewport |
quality | int or null | null | JPEG quality 0-100. Raises if passed with image_type="png" |
wait | number | 0 | Extra wait (ms) after page load before capture |
wait_selector | str or null | null | CSS selector to wait for before capture |
wait_selector_state | str | "attached" | State for wait_selector: "attached" / "visible" / "hidden" / "detached" |
network_idle | bool | false | Wait until no network activity for 500ms |
timeout | number | 30000 | Timeout in milliseconds |
| Scenario | Tool |
|---|---|
| Static page, no bot protection | make_request |
| Multiple static pages | bulk_get |
| JavaScript-rendered / SPA page | fetch |
| Multiple JS-rendered pages | bulk_fetch |
| Cloudflare or strong anti-bot protection | stealthy_fetch (with solve_cloudflare=true for Turnstile) |
| Multiple protected pages | bulk_stealthy_fetch |
| Multiple pages from the same site | open_session + session_fetch per page |
| Multiple plain HTTP requests to one site | open_request_session + session_make_request per request |
| Need a screenshot of a page | open_session + screenshot with session_id |
Start with make_request (fastest, lowest resource cost). Escalate to fetch if content requires JS rendering. Escalate to stealthy_fetch only if blocked. For multiple pages from the same site, use a persistent session to avoid browser launch overhead.
css_selector to narrow results before they reach the model -- this saves significant tokens.main_content_only=true (default) strips nav/footer by restricting to <body>.extraction_type="markdown" (default) is best for readability. Use "text" for minimal output, "html" when structure matters.css_selector matches multiple elements, all are returned in the content list.When main_content_only=true (the default), the server automatically sanitizes scraped content to prevent prompt injection from malicious websites. It strips:
display:none, visibility:hidden, opacity:0, font-size:0, height:0, width:0)aria-hidden="true" elements<template> tagsKeep main_content_only=true for maximum protection.
All browser-based tools (fetch, bulk_fetch, stealthy_fetch, bulk_stealthy_fetch) and persistent sessions (open_session) automatically block requests to ~3,500 known ad and tracker domains. This is always enabled in the MCP server to save tokens and speed up page loads. No configuration needed.
Start the server (stdio transport, used by most MCP clients):
scrapling-mcp
Note: The scrapling-mcp command was added in v0.4.13 as a shortcut that maps directly to scrapling mcp, making it easier to add Scrapling to MCP registries and clients that expect a single command. On older versions, use the scrapling command with mcp as the first argument instead.
Or with Streamable HTTP transport:
scrapling-mcp --http
scrapling-mcp --http --host 0.0.0.0 --port 8000
The host defaults to 127.0.0.1, so the server only accepts connections from the same machine. Pass --host 0.0.0.0 to make it reachable from the network.
Docker alternative:
docker pull pyd4vinci/scrapling
docker run -i --rm pyd4vinci/scrapling mcp
That runs the stdio transport. To use Streamable HTTP inside Docker, bind to 0.0.0.0 yourself and set a token, since the container's 127.0.0.1 is not reachable through the published port:
docker run -p 8000:8000 -e SCRAPLING_MCP_AUTH_TOKEN="<your-token>" pyd4vinci/scrapling mcp --http --host 0.0.0.0
Browser-based tools (fetch, bulk_fetch, stealthy_fetch, bulk_stealthy_fetch, and open_session) can use a custom Chromium-compatible browser executable instead of the bundled Chromium. This is useful for custom browser builds or lightweight browser engines.
To configure it once for the whole MCP server, pass the executable path when starting the server:
scrapling-mcp --executable-path "/path/to/chromium"
In a Claude Desktop configuration, add the option to the server arguments:
{
"mcpServers": {
"ScraplingServer": {
"command": "/Users/<MyUsername>/.venv/bin/scrapling-mcp",
"args": [
"--executable-path",
"/path/to/chromium"
]
}
}
}
You can also set the SCRAPLING_EXECUTABLE_PATH environment variable before starting the server. Tool calls can still pass executable_path directly when a single request or session needs a different browser executable. The scrapling extract fetch and scrapling extract stealthy-fetch CLI commands support the same --executable-path option and environment variable fallback.
The MCP server name when registering with a client is ScraplingServer. The command is the path to the scrapling-mcp binary with no arguments (or the scrapling binary with mcp as the argument on versions before 0.4.13).
open_session doesn't have to launch a browser locally. Pass a cdp_url and it connects to an already-running browser through the Chrome DevTools Protocol, whether that browser is on the same machine, another host, or a managed browser provider. Both session types (dynamic and stealthy) accept it, and the session_id you get back is used with session_fetch and screenshot as usual.
The URL can be a WebSocket endpoint (ws:///wss://), which is what managed browser providers hand out, or the HTTP endpoint of a browser started with --remote-debugging-port=9222, reached as cdp_url="http://localhost:9222".
Notes:
headless, real_chrome, and executable_path (including the server-wide default).locale, useragent, proxy, cookies, timezone_id, and so on), as each session creates its own browser context on the remote browser.The stdio transport is only reachable by the program that started it, but with Streamable HTTP anyone who can reach the port can call every tool, including fetching any URL from the machine running the server. That's why Streamable HTTP requires authentication, so --http on its own refuses to start and asks you for a token:
scrapling-mcp --http --auth-token "$(openssl rand -hex 32)"
Clients then have to send that token in an Authorization header, and any request without it is rejected with a 401:
{
"mcpServers": {
"ScraplingServer": {
"url": "https://your-server.example.com/mcp",
"headers": {
"Authorization": "Bearer <your-token>"
}
}
}
}
Passing the token on the command line leaves it in the shell history and the process list, so prefer the SCRAPLING_MCP_AUTH_TOKEN environment variable:
export SCRAPLING_MCP_AUTH_TOKEN="<your-token>"
scrapling-mcp --http
If you really want an unauthenticated server, for example while testing locally on the default 127.0.0.1, you have to ask for it with --no-auth:
scrapling-mcp --http --no-auth
Combining --no-auth with --host 0.0.0.0 leaves every tool open to anyone who can reach the port, so avoid that pair outside a trusted network.
When the server listens on a public address, also tell it which host names to accept, which turns on protection against DNS-rebinding attacks. The option can be repeated:
scrapling-mcp --http --allowed-host 'your-server.example.com:8000'
Notes:
--http --no-auth still logs a warning that it's unauthenticated.--auth-token and --no-auth keeps the token, so the server stays authenticated instead of quietly dropping it.