Fetch bot-protected and JavaScript-heavy pages for AI agents, or parse them to JSON with templates.
Call this server's tools from your browser. Nothing to install.
Optional. Bearer followed by your UnblockingAPI key from https://unblockingapi.com (500 free credits, no card), e.g. 'Bearer <key>'. Without it, clients that support OAuth sign in with your UnblockingAPI account instead.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Find published templates that parse a site into structured JSON instead of HTML. Pass the url you are about to fetch to see whether one already covers it — do this before writing your own extraction for a well-known site. Also searches by keyword or category. Each result shows the fields it returns and an example call; pass its reference as unblock_fetch's template argument. Free — no credit is charged.
A URL you intend to fetch. Returns the templates built for that site, if any.
Which page of `limit` results to return, from 1, when more templates match than fit.
Maximum templates to return (default 25).
Keyword matched against a template's name, reference, host and description (e.g. 'property', 'company').
Category slug, e.g. 'search-results', 'real-estate', 'business-directories'. Omit all filters to see the categories.
Find published templates that parse a site into structured JSON instead of HTML. Pass the url you are about to fetch to see whether one already covers it — do this before writing your own extraction for a well-known site. Also searches by keyword or category. Each result shows the fields it returns and an example call; pass its reference as unblock_fetch's template argument. Free — no credit is charged.
| Argument | Type | Description |
|---|---|---|
| url | string | A URL you intend to fetch. Returns the templates built for that site, if any. |
| page | integer | Which page of `limit` results to return, from 1, when more templates match than fit. |
| limit | integer | Maximum templates to return (default 25). |
| search | string | Keyword matched against a template's name, reference, host and description (e.g. 'property', 'company'). |
| category | string | Category slug, e.g. 'search-results', 'real-estate', 'business-directories'. Omit all filters to see the categories. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"url": {
"type": "string",
"description": "A URL you intend to fetch. Returns the templates built for that site, if any."
},
"page": {
"type": "integer",
"minimum": 1,
"description": "Which page of `limit` results to return, from 1, when more templates match than fit."
},
"limit": {
"type": "integer",
"maximum": 100,
"minimum": 1,
"description": "Maximum templates to return (default 25)."
},
"search": {
"type": "string",
"description": "Keyword matched against a template's name, reference, host and description (e.g. 'property', 'company')."
},
"category": {
"type": "string",
"description": "Category slug, e.g. 'search-results', 'real-estate', 'business-directories'. Omit all filters to see the categories."
}
},
"additionalProperties": false
}Read this before writing code that uses UnblockingAPI - an app, script, scheduled job or backend that fetches web pages (a rank tracker, a listings aggregator, a price monitor, …). Returns the REST API reference for calling it with plain HTTP (no SDK), how to keep the key server-side on platforms like Lovable, Replit and Next.js, how to use templates, and complete recipes. Free. Start with topic 'api', then the recipe that fits.
| Argument | Type | Description |
|---|---|---|
| topic* | string | 'api': the REST API for apps: request, response, errors, timeouts, keeping the key server-side. 'fetch-tuning': getting complete pages: scrolling, waiting for content, consent walls, locations. 'templates': finding and calling templates for JSON, their output shapes, building your own. 'rank-tracker': recipe: a Google rank tracker for keywords and domains. 'listings-aggregator': recipe: one page that aggregates listings (e.g. properties) from several sites. 'price-monitor': recipe: watch product prices and alert on changes. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"topic"
],
"properties": {
"topic": {
"enum": [
"api",
"fetch-tuning",
"templates",
"rank-tracker",
"listings-aggregator",
"price-monitor"
],
"type": "string",
"description": "'api': the REST API for apps: request, response, errors, timeouts, keeping the key server-side. 'fetch-tuning': getting complete pages: scrolling, waiting for content, consent walls, locations. 'templates': finding and calling templates for JSON, their output shapes, building your own. 'rank-tracker': recipe: a Google rank tracker for keywords and domains. 'listings-aggregator': recipe: one page that aggregates listings (e.g. properties) from several sites. 'price-monitor': recipe: watch product prices and alert on changes."
}
},
"additionalProperties": false
}Fetch a web page through UnblockingAPI's rotating residential proxies and a real browser. Useful for pages a plain HTTP fetch can't read: pages that need JavaScript, refuse automated requests, or show different content by country. Returns the page as Markdown (or cleaned HTML with format: 'html'); select narrows it to the part you need. If content is missing, fetch again with scroll_steps or wait_for. Picks the mode itself by default: a plain HTTP fetch first, and a real browser when the site blocks it or needs JavaScript. Pass a template reference to get structured JSON instead of HTML — call find_templates with the url first to see whether one exists. Costs 1 credit per successful fetch; failures are free.
| Argument | Type | Description |
|---|---|---|
| url* | string | The HTTP/HTTPS URL to fetch. Media and binary files are rejected. |
| fresh | boolean | Fetch again even if this exact fetch was made in the last 10 minutes (by default that copy is reused for free). |
| format | string | How the page comes back (template results are always JSON). "markdown" (default): text, headings, links and lists, a fraction of the size. "html": the cleaned markup, for attributes, custom elements and choosing a select. |
| render | boolean | Omit to let the API decide (plain fetch first, a browser when blocked or when the page is an empty JavaScript shell; learned per site). true always renders with a real browser (slower, up to ~2 min worst case); false never does. Any wait option implies true. |
| select |
| string |
| CSS selector: return only the matching elements (e.g. 'article', 'table tr', 'shreddit-post'), in the chosen format. Re-reading a fetch with another select or format reuses the page already fetched - no credit. |
| max_age | integer | Accept a cached copy of the same request up to this many seconds old (0–300). Cache hits return in milliseconds and still cost 1 credit. Default 0 = always fetch fresh. |
| location | string | 2-letter country code to proxy through (e.g. 'us', 'gb', 'de'). Most countries are supported; an unsupported one is refused with the list. |
| template | string | Parse the page with a published template and return JSON instead of HTML. Takes a template reference like 'handle/name' — call find_templates with this url first to see whether one covers the site. Append '@<version>' to pin a version (the response's template_version is the one that answered). The template forces its own render and wait settings. |
| wait_for | string | Implies a browser. When to capture: 'stable' (default — once the DOM stops changing), 'domcontentloaded' (immediately), 'networkidle', or any CSS selector (wait until it is visible, then settle). Prefer a selector or 'stable' on pages that never go quiet. |
| detect_ms | integer | Implies a browser. How long to probe wait_rules guards before falling back to wait_for. Default 800. |
| max_chars | integer | Cap on returned body characters (default 80000, max 140000). Longer bodies are cut with a note; select narrows a page to the part you need instead. |
| settle_ms | integer | Implies a browser. Ceiling (not a delay) on the settle wait, default 5000. Capture happens as soon as the DOM has been quiet for 500ms. Use wait_min_ms for a minimum delay; lower this to cap the worst case. |
| wait_rules | array | Implies a browser. Conditional waits for pages with several possible layouts (consent gate, interstitial, A/B variant). Each 'if' selector is probed in order for detect_ms; the first visible one wins and its 'then' replaces wait_for. Example: [{if: '#consent', then: '#results'}]. |
| wait_state | string | Condition for a CSS selector in wait_for (requires one): 'visible' (default), 'nonempty' (visible text, ignoring loading placeholders), 'hidden' (all matches hidden or gone — e.g. a spinner), 'stable' (text and match count unchanged for 750ms). |
| wait_min_ms | integer | Implies a browser. Minimum delay after navigation before scrolling or checking readiness, for content that is absent from the first capture. |
| scroll_steps | integer | Implies a browser. Scroll down this many times before the readiness check, to trigger lazy-loaded sections. Bounded discovery, not a way to collect an infinite list. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"url"
],
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "The HTTP/HTTPS URL to fetch. Media and binary files are rejected."
},
"fresh": {
"type": "boolean",
"description": "Fetch again even if this exact fetch was made in the last 10 minutes (by default that copy is reused for free)."
},
"format": {
"enum": [
"markdown",
"html"
],
"type": "string",
"description": "How the page comes back (template results are always JSON). \"markdown\" (default): text, headings, links and lists, a fraction of the size. \"html\": the cleaned markup, for attributes, custom elements and choosing a select."
},
"render": {
"type": "boolean",
"description": "Omit to let the API decide (plain fetch first, a browser when blocked or when the page is an empty JavaScript shell; learned per site). true always renders with a real browser (slower, up to ~2 min worst case); false never does. Any wait option implies true."
},
"select": {
"type": "string",
"maxLength": 500,
"description": "CSS selector: return only the matching elements (e.g. 'article', 'table tr', 'shreddit-post'), in the chosen format. Re-reading a fetch with another select or format reuses the page already fetched - no credit."
},
"max_age": {
"type": "integer",
"maximum": 300,
"minimum": 0,
"description": "Accept a cached copy of the same request up to this many seconds old (0–300). Cache hits return in milliseconds and still cost 1 credit. Default 0 = always fetch fresh."
},
"location": {
"type": "string",
"pattern": "^[a-zA-Z]{2}$",
"description": "2-letter country code to proxy through (e.g. 'us', 'gb', 'de'). Most countries are supported; an unsupported one is refused with the list."
},
"template": {
"type": "string",
"pattern": "^(?:[a-z0-9][a-z0-9-]{1,48}[a-z0-9]\\/)?[a-z0-9][a-z0-9-]{1,48}[a-z0-9](?:@[1-9]\\d{0,8})?$",
"description": "Parse the page with a published template and return JSON instead of HTML. Takes a template reference like 'handle/name' — call find_templates with this url first to see whether one covers the site. Append '@<version>' to pin a version (the response's template_version is the one that answered). The template forces its own render and wait settings."
},
"wait_for": {
"type": "string",
"maxLength": 500,
"description": "Implies a browser. When to capture: 'stable' (default — once the DOM stops changing), 'domcontentloaded' (immediately), 'networkidle', or any CSS selector (wait until it is visible, then settle). Prefer a selector or 'stable' on pages that never go quiet."
},
"detect_ms": {
"type": "integer",
"maximum": 25000,
"minimum": 0,
"description": "Implies a browser. How long to probe wait_rules guards before falling back to wait_for. Default 800."
},
"max_chars": {
"type": "integer",
"maximum": 140000,
"minimum": 1000,
"description": "Cap on returned body characters (default 80000, max 140000). Longer bodies are cut with a note; select narrows a page to the part you need instead."
},
"settle_ms": {
"type": "integer",
"maximum": 25000,
"minimum": 0,
"description": "Implies a browser. Ceiling (not a delay) on the settle wait, default 5000. Capture happens as soon as the DOM has been quiet for 500ms. Use wait_min_ms for a minimum delay; lower this to cap the worst case."
},
"wait_rules": {
"type": "array",
"items": {
"type": "object",
"required": [
"if"
],
"properties": {
"if": {
"type": "string",
"description": "CSS selector to probe for visibility."
},
"then": {
"type": "string",
"description": "Replacement wait_for when the guard is visible: a mode or a CSS selector. Empty = capture as-is."
}
},
"additionalProperties": false
},
"maxItems": 10,
"description": "Implies a browser. Conditional waits for pages with several possible layouts (consent gate, interstitial, A/B variant). Each 'if' selector is probed in order for detect_ms; the first visible one wins and its 'then' replaces wait_for. Example: [{if: '#consent', then: '#results'}]."
},
"wait_state": {
"enum": [
"visible",
"nonempty",
"hidden",
"stable"
],
"type": "string",
"description": "Condition for a CSS selector in wait_for (requires one): 'visible' (default), 'nonempty' (visible text, ignoring loading placeholders), 'hidden' (all matches hidden or gone — e.g. a spinner), 'stable' (text and match count unchanged for 750ms)."
},
"wait_min_ms": {
"type": "integer",
"maximum": 10000,
"minimum": 0,
"description": "Implies a browser. Minimum delay after navigation before scrolling or checking readiness, for content that is absent from the first capture."
},
"scroll_steps": {
"type": "integer",
"maximum": 10,
"minimum": 0,
"description": "Implies a browser. Scroll down this many times before the readiness check, to trigger lazy-loaded sections. Bounded discovery, not a way to collect an infinite list."
}
},
"additionalProperties": false
}