Skip to main content
Glama
ScrapeUnblocker

ScrapeUnblocker MCP Server

Official

ScrapeUnblocker MCP server

A Model Context Protocol server that lets Claude (and any other MCP client) fetch any web page's HTML through the ScrapeUnblocker scraping API, bypassing anti-bot protection (Cloudflare, DataDome, PerimeterX, Akamai, Shape).

You bring your own API key. Nothing is shared or proxied through us.

Tools

Tool

What it does

fetch_html

Fetch the fully rendered HTML of a URL (optionally after running interactive browser steps).

list_elements

List a page's notable elements with a ready-to-use selector for each (selector discovery).

fetch_parsed

Fetch a page and return AI-parsed structured JSON.

google_search

Run a Google search and return organic results as JSON.

Browser steps (interact, then capture)

Some pages only reveal what you need after you interact with them - accept a cookie banner, click a tab, type into a search box and submit, or scroll to trigger lazy loading. Pass an optional steps array to fetch_html and those actions run in a real browser, in order, after the page loads; the resulting HTML is then returned.

Available actions:

Action

Fields

wait_for

selector, selector_type? (css/xPath/className/tagName), timeout_ms?

wait_for_text

value, timeout_ms?

wait

value (ms)

click

selector, selector_type?, timeout_ms?

type

selector, selector_type?, value, clear?, timeout_ms? (typed human-like)

select

selector, selector_type?, value, timeout_ms?

press_key

value (Enter, Tab, Escape, Backspace, Delete, Space, Arrow*, Home, End, PageUp, PageDown)

scroll

value ("bottom" or a pixel offset)

Steps are not idempotent - they run once per call. If a step fails, fetch_html returns which step failed, why, and the page HTML at that moment so you can fix the selector and retry.

List elements (discover selectors first)

list_elements loads a page and returns a JSON list of its notable elements (links, inputs, buttons, selects, ...), each with a ready-to-use selector plus tag, text and useful attributes (name, id, type, placeholder, aria_label, href, ...):

{ "url": "https://example.com", "count": 42, "elements": [ { "tag": "input", "selector": "#search", "type": "text", "placeholder": "Search", "aria_label": "Search" } ] }

The natural workflow is discover, then act: call list_elements to find the selectors you need, then pass matching steps to fetch_html to click/type/ select and capture the resulting HTML.

Related MCP server: SteadyFetch

Get an API key

Sign up and grab your key at app.scrapeunblocker.com. The server reads it from the SCRAPEUNBLOCKER_KEY environment variable.

Install

Claude Code

The easiest route is the official plugin, which installs this server for you, prompts for your API key (stored in your OS keychain rather than an environment variable), and adds a /scrape-url command plus reference skills:

/plugin marketplace add ScrapeUnblocker/claude-code-plugin
/plugin install scrapeunblocker@scrapeunblocker

See ScrapeUnblocker/claude-code-plugin.

To add the bare server instead:

claude mcp add scrapeunblocker \
  --env SCRAPEUNBLOCKER_KEY=your_api_key_here \
  -- npx -y scrapeunblocker-mcp

Claude Desktop

Add this to your claude_desktop_config.json (Settings → Developer → Edit Config):

{
  "mcpServers": {
    "scrapeunblocker": {
      "command": "npx",
      "args": ["-y", "scrapeunblocker-mcp"],
      "env": {
        "SCRAPEUNBLOCKER_KEY": "your_api_key_here"
      }
    }
  }
}

Restart Claude Desktop and the ScrapeUnblocker tools appear.

Any other MCP client

Run the server over stdio:

SCRAPEUNBLOCKER_KEY=your_api_key_here npx -y scrapeunblocker-mcp

Example prompts

  • "Fetch the HTML of https://www.example-shop.com/product/123 and list the price."

  • "This page keeps blocking me: . Use fetch_html to get it."

  • "List the elements on , then use fetch_html steps to type 'laptop' into the search box, press Enter, wait for the results, and give me the HTML."

  • "Search Google for 'best running shoes 2026' and give me the top 5 links."

Development

npm install
npm run build      # bundles to dist/ with tsup
npm run typecheck
SCRAPEUNBLOCKER_KEY=... node dist/index.js   # run the server

License

MIT

Available Tools

4 tools
fetch_htmlFetch page HTMLA

Fetch the fully rendered HTML of any web page through ScrapeUnblocker, bypassing anti-bot protection (Cloudflare, DataDome, PerimeterX, Akamai, Shape). Use this when a normal fetch is blocked (403/429, captcha, 'access denied') or when the page needs a real browser to render. Returns the raw HTML as text.

For pages that need interaction (accept a cookie banner, click a tab, type into a search box, scroll to trigger lazy loading) pass steps: an ordered list of browser actions run in a real browser AFTER the page loads, then the resulting HTML is returned. Workflow: first call the list_elements tool to discover the real selectors on the page, then build steps against them. Steps are NOT idempotent - they run once per call. If a step fails, this tool returns which step failed, why, and the page HTML at that moment so you can fix the selector and retry.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesThe absolute URL to fetch (http/https).
stepsNoOptional ordered browser actions to run in a real browser after the page loads, before the HTML is captured. Use `list_elements` first to find selectors. Runs once (not idempotent).
wait_valueNoThe CSS selector or JS expression paired with wait_method (e.g. '#price' or 'document.readyState==="complete"').
wait_methodNoOptional render-wait strategy: 'css' waits for a selector, 'js' waits for a JS expression to be truthy.
proxy_countryNoOptional ISO 3166-1 alpha-2 country code to route through, e.g. 'US', 'GB', 'DE'.
sleep_secondsNoExtra seconds to wait after load before capturing the HTML.
method_timeout_secondsNoCap in seconds for the render-wait method.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses important behaviors: bypasses anti-bot protection, steps are not idempotent and run once per call, and failed steps return the failing step, reason, and page HTML at that moment. This is strong behavioral disclosure, though it omits potential costs, rate limits, or output size caveats.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence serves a purpose: the main behavior, the bypass value, the step workflow, the selector discovery guidance, and the failure semantics. It front-loads the core purpose and keeps related operational details together. No filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no annotations and no output schema, the description is remarkably complete. It covers the main use case, the fallback trigger, step semantics, failure behavior, return format, and the recommended workflow with list_elements. The 100% schema coverage for parameters fills the remaining gaps, so nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds meaningful semantics beyond the schema by explaining that `steps` are an ordered list run after page load, that selectors should be discovered via list_elements, and that steps are non-idempotent. Other parameters like `wait_method` and `proxy_country` are adequately covered by the schema itself.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Fetch the fully rendered HTML of any web page') and immediately distinguishes itself by naming the anti-bot bypass use case. The scope is unambiguous and clearly separates it from the sibling tools like fetch_parsed and google_search.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly tells the agent when to use it: when a normal fetch is blocked (403/429, captcha, 'access denied') or when a real browser is needed for rendering. It also gives a workflow for interactive pages (use list_elements first, then build steps). It doesn't explicitly name the alternative tool for parsed content or state when not to use it, but the usage context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fetch_parsedFetch AI-parsed page dataA

Fetch a web page through ScrapeUnblocker and return AI-parsed structured JSON instead of raw HTML (e.g. product details, article content). Best for extracting fields from product, listing or article pages without writing your own HTML parsing. If the page holds no structured data, the result says so (that call is not billed) - use fetch_html for the page itself.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesThe absolute URL to fetch and parse.
rules_hintNoOptional natural-language hint about what to extract, to guide parsing.
proxy_countryNoOptional ISO country code to route through, e.g. 'US'.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden and does well: it discloses the ScrapeUnblocker routing layer, the output form, and a non-obvious billing rule for empty results. It does not address authentication, rate limits, or latency, so it falls short of full disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, zero padding, and the core differentiator (structured JSON vs raw HTML) is front-loaded before the usage guidance and the fallback instruction.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description usefully characterizes the return value (structured JSON with product/article fields) and the empty-result case. It is nearly complete, though it leaves the exact response envelope unspecified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so url, rules_hint and proxy_country are already documented in the schema. The description hints at the parsing intent behind rules_hint but adds no syntax or format detail beyond what the schema provides, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (fetch a web page) and the distinctive output (AI-parsed structured JSON instead of raw HTML), with concrete examples of the content types returned. It explicitly distinguishes itself from the sibling fetch_html.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the ideal scenarios (product, listing, article pages) and names the alternative tool (fetch_html) with the condition that selects it. It also covers the failure case - no structured data present - and notes that call is unbilled, which removes ambiguity about retry behavior.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_elementsList page elements (selector discovery)A

Load a page through ScrapeUnblocker and return a JSON list of its notable elements (links, inputs, buttons, selects, etc.) with a ready-to-use selector for each, plus tag, text and useful attributes (name, id, type, placeholder, aria_label, href, ...). Read-only and does not interact with the page. This is the discovery half of interactive scraping: call list_elements to find the selectors you need, then pass matching steps to fetch_html to click/type/select and capture the resulting HTML.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesThe absolute URL whose elements you want to list.
proxy_countryNoOptional ISO country code to route through, e.g. 'US'.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses the read-only nature, that it does not interact with the page, and that it loads the page through ScrapeUnblocker. It does not mention rate limits or how 'notable' elements are selected, but for a read-only discovery tool this is reasonable coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with no filler: the first states core purpose and output, the second emphasizes read-only behavior, and the third gives the workflow context. All information earns its place and the most important details are front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Since there is no output schema, the description explains the return value (JSON list with selector, tag, text, attributes) sufficiently. It also connects the tool to the broader fetch_html workflow. Minor gaps such as empty results or blocked pages are not covered, but they are not essential for correct selection and invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%: url is described as 'The absolute URL whose elements you want to list' and proxy_country as 'Optional ISO country code to route through'. The tool description adds no extra parameter context, but with full schema coverage the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: loads a page and returns a JSON list of notable elements with ready-to-use selectors and attributes. It also distinguishes itself from the sibling fetch_html by positioning itself as the 'discovery half of interactive scraping' and explicitly noting it is read-only.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a direct usage workflow: 'call list_elements to find the selectors you need, then pass matching steps to fetch_html'. It also clarifies that the tool does not interact with the page, implying that fetch_html is for interaction, which serves as an alternative and exclusion.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.2.0
    • Changedfetch_html1 field changed
      • addedInput schema / properties / steps
        Added value: +{
        +  "description": "Optional ordered browser actions to run in a real browser after the page loads, before the HTML is captured. Use `list_elements` first to find selectors. Runs once (not idempotent).",
        +  "items": {
        +    "anyOf": [
        +      {
        +        "additionalProperties": false,
        +        "description": "Wait until an element matching `selector` exists.",
        +        "properties": {
        +          "action": {
        +            "const": "wait_for",
        +            "type": "string"
        +          },
        +          "selector": {
        +            "description": "Selector to wait for (until present).",
        +            "type": "string"
        +          },
        +          "selector_type": {
        +            "description": "How `selector` is interpreted. Defaults to 'css'.",
        +            "enum": [
        +              "css",
        +              "xPath",
        +              "className",
        +              "tagName"
        +            ],
        +            "type": "string"
        +          },
        +          "timeout_ms": {
        +            "exclusiveMinimum": 0,
        +            "type": "integer"
        +          }
        +        },
        +        "required": [
        +          "action",
        +          "selector"
        +        ],
        +        "type": "object"
        +      },
        +      {
        +        "additionalProperties": false,
        +        "description": "Wait until the given text appears on the page.",
        +        "properties": {
        +          "action": {
        +            "const": "wait_for_text",
        +            "type": "string"
        +          },
        +          "timeout_ms": {
        +            "exclusiveMinimum": 0,
        +            "type": "integer"
        +          },
        +          "value": {
        +            "description": "Text to wait for anywhere on the page.",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "action",
        +          "value"
        +        ],
        +        "type": "object"
        +      },
        +      {
        +        "additionalProperties": false,
        +        "description": "Pause for a fixed number of milliseconds.",
        +        "properties": {
        +          "action": {
        +            "const": "wait",
        +            "type": "string"
        +          },
        +          "value": {
        +            "description": "Fixed pause in milliseconds.",
        +            "minimum": 0,
        +            "type": "integer"
        +          }
        +        },
        +        "required": [
        +          "action",
        +          "value"
        +        ],
        +        "type": "object"
        +      },
        +      {
        +        "additionalProperties": false,
        +        "description": "Click the element matching `selector`.",
        +        "properties": {
        +          "action": {
        +            "const": "click",
        +            "type": "string"
        +          },
        +          "selector": {
        +            "description": "Selector of the element to click.",
        +            "type": "string"
        +          },
        +          "selector_type": {
        +            "$ref": "#/properties/steps/items/anyOf/0/properties/selector_type",
        +            "description": "How `selector` is interpreted. Defaults to 'css'."
        +          },
        +          "timeout_ms": {
        +            "exclusiveMinimum": 0,
        +            "type": "integer"
        +          }
        +        },
        +        "required": [
        +          "action",
        +          "selector"
        +        ],
        +        "type": "object"
        +      },
        +      {
        +        "additionalProperties": false,
        +        "description": "Type text into an input, character by character.",
        +        "properties": {
        +          "action": {
        +            "const": "type",
        +            "type": "string"
        +          },
        +          "clear": {
        +            "description": "Clear the field before typing.",
        +            "type": "boolean"
        +          },
        +          "selector": {
        +            "description": "Selector of the field to type into.",
        +            "type": "string"
        +          },
        +          "selector_type": {
        +            "$ref": "#/properties/steps/items/anyOf/0/properties/selector_type",
        +            "description": "How `selector` is interpreted. Defaults to 'css'."
        +          },
        +          "timeout_ms": {
        +            "exclusiveMinimum": 0,
        +            "type": "integer"
        +          },
        +          "value": {
        +            "description": "Text to type (entered human-like).",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "action",
        +          "selector",
        +          "value"
        +        ],
        +        "type": "object"
        +      },
        +      {
        +        "additionalProperties": false,
        +        "description": "Choose an option in a <select> dropdown by value.",
        +        "properties": {
        +          "action": {
        +            "const": "select",
        +            "type": "string"
        +          },
        +          "selector": {
        +            "description": "Selector of the <select> element.",
        +            "type": "string"
        +          },
        +          "selector_type": {
        +            "$ref": "#/properties/steps/items/anyOf/0/properties/selector_type",
        +            "description": "How `selector` is interpreted. Defaults to 'css'."
        +          },
        +          "timeout_ms": {
        +            "exclusiveMinimum": 0,
        +            "type": "integer"
        +          },
        +          "value": {
        +            "description": "The option value to select.",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "action",
        +          "selector",
        +          "value"
        +        ],
        +        "type": "object"
        +      },
        +      {
        +        "additionalProperties": false,
        +        "description": "Press a single keyboard key.",
        +        "properties": {
        +          "action": {
        +            "const": "press_key",
        +            "type": "string"
        +          },
        +          "value": {
        +            "description": "The key to press.",
        +            "enum": [
        +              "Enter",
        +              "Tab",
        +              "Escape",
        +              "Backspace",
        +              "Delete",
        +              "Space",
        +              "ArrowUp",
        +              "ArrowDown",
        +              "ArrowLeft",
        +              "ArrowRight",
        +              "Home",
        +              "End",
        +              "PageUp",
        +              "PageDown"
        +            ],
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "action",
        +          "value"
        +        ],
        +        "type": "object"
        +      },
        +      {
        +        "additionalProperties": false,
        +        "description": "Scroll the page to the bottom or by a pixel amount.",
        +        "properties": {
        +          "action": {
        +            "const": "scroll",
        +            "type": "string"
        +          },
        +          "value": {
        +            "anyOf": [
        +              {
        +                "const": "bottom",
        +                "type": "string"
        +              },
        +              {
        +                "type": "integer"
        +              }
        +            ],
        +            "description": "'bottom' to scroll to the end, or a pixel offset."
        +          }
        +        },
        +        "required": [
        +          "action",
        +          "value"
        +        ],
        +        "type": "object"
        +      }
        +    ]
        +  },
        +  "type": "array"
        +}
    • Addedlist_elements
  2. 3 tool updatesv0.1.4
    • Addedfetch_html
    • Addedfetch_parsed
    • Addedgoogle_search
  3. 3 tool updatesv0.1.3
    • Removedfetch_html
    • Removedfetch_parsed
    • Removedgoogle_search
  4. 3 tool updatesv0.1.2
    • First observedfetch_html
    • First observedfetch_parsed
    • First observedgoogle_search

TDQS

A4.3/5.0

Scored across 4 tools

Disambiguation5/5

Each tool targets a distinct action: fetch_html (raw HTML), fetch_parsed (structured JSON), google_search (URL discovery), and list_elements (read-only selector discovery). The descriptions explicitly cross-reference each other (e.g. 'use fetch_html for the page itself'), making selection unambiguous.

Naming Consistency5/5

All four names are snake_case and follow a verb_noun pattern (fetch_html, fetch_parsed, list_elements, google_search). The convention is uniform and predictable.

Tool Count4/5

Four tools is lean and each earns its place for a scraping service, covering fetch, parse, search, and element discovery. It sits at the low end of the ideal range but is well-scoped rather than thin.

Completeness4/5

The surface covers the core scraping lifecycle: discovery (google_search), selector inspection (list_elements), raw fetch, and parsed extraction with interactive steps. Minor gaps like multi-page crawling or pagination/session handling exist but core workflows are covered.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Enables AI agents to fetch bot-protected web pages, run structured Google searches, and check domain authority through UnblockingAPI's anti-detection engine and residential proxies.
    3
    35 npm
    1
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides AI agents with reliable web fetching capabilities, handling retries, caching, and anti-bot bypass automatically.
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to fetch any web page (including those behind Cloudflare or CAPTCHAs), extract clean markdown, structured data, crawl sites, and map URLs via BypassAPI.
    MIT