Back to Scrapling

Scrapling MCP Server

agent-skill/Scrapling-Skill/references/mcp-server.md

0.4.1527.8 KB
Original Source

Scrapling MCP Server

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).

One-shot tools

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:

ParameterTypeDefaultDescription
urlstrrequiredURL to fetch
method"GET" / "POST" / "PUT" / "DELETE""GET"HTTP method
datadict or str or nullnullRequest body (form data). POST/PUT/DELETE only
jsondict or list or nullnullRequest body (JSON). POST/PUT/DELETE only
extraction_type"markdown" / "html" / "text""markdown"Output format
css_selectorstr or nullnullCSS selector to narrow content (applied after main_content_only)
main_content_onlybooltrueRestrict to <body> content
impersonatestr"chrome"Browser fingerprint to impersonate
proxystr or nullnullProxy URL, e.g. "http://user:pass@host:port"
proxy_authdict or nullnull{"username": "...", "password": "..."}
authdict or nullnullHTTP basic auth, same format as proxy_auth
timeoutnumber30Seconds before timeout
retriesint3Retry attempts on failure
retry_delayint1Seconds between retries
stealthy_headersbooltrueGenerate realistic browser headers and Google referer
http3boolfalseUse HTTP/3 (may conflict with impersonate)
follow_redirectsbool or "safe""safe"Follow redirects. "safe" rejects redirects to internal/private IPs
max_redirectsint30Max redirects (-1 for unlimited)
headersdict or nullnullCustom request headers
cookiesdict or nullnullRequest cookies
paramsdict or nullnullQuery string parameters
verifybooltrueVerify 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):

ParameterTypeDefaultDescription
urlstrrequiredURL to fetch
extraction_typestr"markdown""markdown" / "html" / "text"
css_selectorstr or nullnullNarrow content before extraction
main_content_onlybooltrueRestrict to <body>
headlessbooltrueRun browser hidden (true) or visible (false)
proxystr or dict or nullnullString URL or {"server": "...", "username": "...", "password": "..."}
timeoutnumber30000Timeout in milliseconds
waitnumber0Extra wait (ms) after page load before extraction
wait_selectorstr or nullnullCSS selector to wait for before extraction
wait_selector_statestr"attached"State for wait_selector: "attached" / "visible" / "hidden" / "detached"
network_idleboolfalseWait until no network activity for 500ms
disable_resourcesboolfalseBlock fonts, images, media, stylesheets, etc. for speed
google_searchbooltrueSet a Google referer header
real_chromeboolfalseUse locally installed Chrome instead of bundled Chromium
cdp_urlstr or nullnullConnect to existing browser via CDP URL
extra_headersdict or nullnullAdditional request headers
useragentstr or nullnullCustom user-agent (auto-generated if null)
cookieslist or nullnullPlaywright-format cookies
timezone_idstr or nullnullBrowser timezone, e.g. "America/New_York"
localestr or nullnullBrowser 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):

ParameterTypeDefaultDescription
solve_cloudflareboolfalseAutomatically solve Cloudflare Turnstile/Interstitial challenges
hide_canvasboolfalseAdd noise to canvas operations to prevent fingerprinting
block_webrtcboolfalseForce WebRTC to respect proxy settings (prevents IP leak)
allow_webglbooltrueKeep WebGL enabled (disabling is detectable by WAFs)
additional_argsdict or nullnullExtra 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.

Session tools

open_session -- Create a persistent browser session

Opens 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:

ParameterTypeDefaultDescription
session_type"dynamic" / "stealthy"requiredType of browser session to create
session_idstr or nullnullCustom ID for the session. If omitted, a random 12-char hex ID is generated. Raises if already in use
headlessbooltrueRun browser hidden or visible
hide_canvasboolfalse(Stealthy only) Canvas fingerprint noise
block_webrtcboolfalse(Stealthy only) Block WebRTC IP leak
allow_webglbooltrue(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 session

Opens 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.

ParameterTypeDefaultDescription
session_idstr or nullnullCustom ID for the session. If omitted, a random 12-char hex ID is generated. Raises if already in use
impersonatestr"chrome"Browser fingerprint to impersonate on every request
proxystr or nullnullProxy 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.

ParameterTypeDefaultDescription
urlstrrequiredURL to fetch
session_idstrrequiredID of an open session created with open_session
extraction_typestr"markdown""markdown" / "html" / "text"
css_selectorstr or nullnullNarrow content before extraction
main_content_onlybooltrueRestrict to <body>
waitnumber0Extra wait (ms) after page load before extraction
timeoutnumber30000Timeout in milliseconds
google_searchbooltrueSet a Google referer header
network_idleboolfalseWait until no network activity for 500ms
load_dombooltrueWait for the page's JavaScript to fully load and execute
disable_resourcesboolfalseBlock fonts, images, media, stylesheets, etc. for speed
wait_selectorstr or nullnullCSS selector to wait for before extraction
wait_selector_statestr"attached"State for wait_selector: "attached" / "visible" / "hidden" / "detached"
extra_headersdict or nullnullAdditional request headers
blocked_domainslist or nullnullDomain names to block for this request (subdomains matched too)
solve_cloudflareboolfalse(Stealthy sessions only) Auto-solve Cloudflare challenges; errors on a dynamic session

session_make_request -- HTTP request through an open requests session

Makes 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 session

Closes a session (browser or requests) and frees its resources. Always close sessions when done.

ParameterTypeDefaultDescription
session_idstrrequiredSession ID from open_session

Returns a SessionClosedModel with session_id and message.

list_sessions -- List active sessions

Returns 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 screenshot

Navigates 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.

ParameterTypeDefaultDescription
urlstrrequiredURL to navigate to and capture
session_idstrrequiredID of an open browser session created with open_session
image_type"png" / "jpeg""png"Image format. Use "jpeg" for smaller payloads
full_pageboolfalseCapture the full scrollable page instead of just the viewport
qualityint or nullnullJPEG quality 0-100. Raises if passed with image_type="png"
waitnumber0Extra wait (ms) after page load before capture
wait_selectorstr or nullnullCSS selector to wait for before capture
wait_selector_statestr"attached"State for wait_selector: "attached" / "visible" / "hidden" / "detached"
network_idleboolfalseWait until no network activity for 500ms
timeoutnumber30000Timeout in milliseconds

Tool selection guide

ScenarioTool
Static page, no bot protectionmake_request
Multiple static pagesbulk_get
JavaScript-rendered / SPA pagefetch
Multiple JS-rendered pagesbulk_fetch
Cloudflare or strong anti-bot protectionstealthy_fetch (with solve_cloudflare=true for Turnstile)
Multiple protected pagesbulk_stealthy_fetch
Multiple pages from the same siteopen_session + session_fetch per page
Multiple plain HTTP requests to one siteopen_request_session + session_make_request per request
Need a screenshot of a pageopen_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.

Content extraction tips

  • Use 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.
  • If a css_selector matches multiple elements, all are returned in the content list.

Prompt injection protection

When main_content_only=true (the default), the server automatically sanitizes scraped content to prevent prompt injection from malicious websites. It strips:

  • CSS-hidden elements (display:none, visibility:hidden, opacity:0, font-size:0, height:0, width:0)
  • aria-hidden="true" elements
  • <template> tags
  • HTML comments
  • Zero-width unicode characters

Keep main_content_only=true for maximum protection.

Ad blocking

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.

Setup

Start the server (stdio transport, used by most MCP clients):

bash
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:

bash
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:

bash
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:

bash
docker run -p 8000:8000 -e SCRAPLING_MCP_AUTH_TOKEN="<your-token>" pyd4vinci/scrapling mcp --http --host 0.0.0.0

Custom browser executable

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:

bash
scrapling-mcp --executable-path "/path/to/chromium"

In a Claude Desktop configuration, add the option to the server arguments:

json
{
  "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).

Connecting to remote browsers

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:

  • The browser is already running, so options that only apply while launching one are ignored for CDP sessions: headless, real_chrome, and executable_path (including the server-wide default).
  • Everything else still applies (locale, useragent, proxy, cookies, timezone_id, and so on), as each session creates its own browser context on the remote browser.

Authentication

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:

bash
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:

json
{
  "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:

bash
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:

bash
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:

bash
scrapling-mcp --http --allowed-host 'your-server.example.com:8000'

Notes:

  • Authentication applies to the Streamable HTTP transport only. It's ignored with stdio, and the server logs a warning to say so.
  • Plain HTTP sends the token in cleartext, so put the server behind a reverse proxy that terminates TLS before exposing it to the internet.
  • This is a single shared key, not per-client credentials, so every client uses the same token and rotating it means restarting the server.
  • Starting with --http --no-auth still logs a warning that it's unauthenticated.
  • Passing both --auth-token and --no-auth keeps the token, so the server stays authenticated instead of quietly dropping it.