{"$schema":"https://static.modelcontextprotocol.io/schemas/mcp-server-card/v1.json","name":"alterlab","description":"AlterLab web scraping tools for AI agents: scrape any URL to clean markdown, extract structured data, take screenshots, crawl, search, map sites and batch jobs, with adaptive anti-bot handling and pay-per-success pricing.","version":"1.0.0","protocolVersion":"2025-06-18","serverInfo":{"name":"alterlab","title":"AlterLab","version":"1.0.0"},"websiteUrl":"https://alterlab.io","documentationUrl":"https://alterlab.io/docs","transport":{"type":"streamable-http","endpoint":"https://mcp.alterlab.io/mcp"},"capabilities":{"tools":{"listChanged":false}},"authentication":{"required":true,"schemes":[{"type":"oauth2","authorization_server_metadata":"https://alterlab.io/.well-known/oauth-authorization-server","protected_resource_metadata":"https://mcp.alterlab.io/.well-known/oauth-protected-resource","pkce":"S256","dynamic_client_registration":true},{"type":"apiKey","in":"header","name":"X-API-Key"}],"instructions":"https://alterlab.io/auth.md"},"tools":[{"name":"alterlab_scrape","description":"Use when a normal fetch returns 403/429, a bot-protection challenge page, a CAPTCHA, or an empty JavaScript shell. Fetch any URL and return clean markdown, text, HTML, or JSON. Website challenges and JavaScript-heavy pages are handled automatically by a 5-tier system that starts at the cheapest tier that works and escalates only when needed. Returns markdown by default, ready for LLM context. Supports GET and POST via method, structured extraction via extraction_schema or extraction_prompt, and cost caps via cost_controls. Supports browser actions via actions, plus screenshot and generate_pdf; the response includes action_results, one entry per action with index, type, success, error, result (evaluate) and screenshot_url (screenshot actions).","inputSchema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"URL to scrape"},"method":{"type":"string","enum":["GET","POST"],"default":"GET","description":"HTTP method. POST is for GraphQL, forms and REST APIs. Default: GET."},"body":{"type":"string","description":"Request body for POST requests."},"content_type":{"type":"string","enum":["application/json","application/x-www-form-urlencoded","text/plain","application/graphql"],"description":"Content-Type of body. Requires body."},"mode":{"type":"string","enum":["auto","html","js","pdf","ocr"],"default":"auto","description":"Scraping mode: auto (recommended), html, js (headless browser), pdf, or ocr Default: auto."},"formats":{"type":"array","items":{"type":"string","enum":["text","json","json_v2","html","markdown","rag","raw","content"]},"default":["markdown"],"description":"Output formats. 'markdown' is best for LLM consumption. Default: [\"markdown\"]."},"extraction_schema":{"type":"object","description":"JSON schema for structured extraction. Fields matching this schema are extracted from the page. Example: { \"title\": \"string\", \"price\": \"number\" }"},"extraction_prompt":{"type":"string","maxLength":2000,"description":"Natural language extraction instruction."},"extraction_profile":{"type":"string","description":"Built-in extraction profile (product, article, job_posting, ...)."},"extraction_model":{"type":"string","description":"LLM model override."},"extraction_provider":{"type":"string","enum":["openai","anthropic","openrouter","groq"]},"template":{"type":"string","description":"Extraction template name."},"evidence":{"type":"boolean","description":"Return extraction evidence."},"filter_content":{"type":"boolean"},"cache":{"type":"boolean","description":"Allow a cached result."},"cache_ttl":{"type":"number","minimum":60,"maximum":86400},"render_js":{"description":"Render JavaScript with a headless browser. 'auto' renders only when needed. Default: false.","anyOf":[{"type":"boolean"},{"type":"string","enum":["auto"]}],"default":false},"use_proxy":{"type":"boolean","default":false,"description":"Route through a premium proxy. Default: false."},"proxy_country":{"type":"string","description":"Proxy country code."},"wait_for":{"type":"string","description":"CSS selector to wait for."},"timeout":{"type":"number","minimum":1,"maximum":300,"description":"Timeout. Default: 90.","default":90},"max_response_bytes":{"type":"integer","minimum":0,"maximum":52428800},"include_raw_html":{"type":"boolean","description":"Include raw html. Default: false.","default":false},"session_id":{"type":"string","format":"uuid","description":"Stored session (cookies) to scrape with."},"cookies":{"type":"object","additionalProperties":{"type":"string"}},"scroll_to_load":{"type":"boolean","description":"Scroll to load. Default: false.","default":false},"scroll_count":{"type":"integer","minimum":1,"maximum":10},"remove_cookie_banners":{"type":"boolean","description":"Remove cookie banners. Default: true.","default":true},"block_images":{"type":"boolean","description":"Block images. Default: false.","default":false},"location":{"type":"object","properties":{"country":{"type":"string","minLength":2,"maxLength":2},"language":{"type":"string","minLength":2,"maxLength":5}}},"prefer_cost":{"type":"boolean"},"prefer_speed":{"type":"boolean"},"fail_fast":{"type":"boolean"},"force_refresh":{"type":"boolean"},"promote_schema_org":{"type":"boolean"},"cost_controls":{"type":"object","description":"Cap spending, pin a tier, or trade off cost vs speed.","properties":{"force_tier":{"type":"string","enum":["1","2","3","3.5","4"]},"max_tier":{"type":"string","enum":["1","2","3","3.5","4"]},"max_credits":{"type":"number","exclusiveMinimum":0},"prefer_cost":{"type":"boolean"},"prefer_speed":{"type":"boolean"},"fail_fast":{"type":"boolean"},"time_budget":{"type":"number","minimum":5,"maximum":300}}},"estimate_first":{"type":"boolean","default":false,"description":"Run a free cost estimate before scraping. Default: false."},"actions":{"type":"array","maxItems":20,"items":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","enum":["wait"]},"milliseconds":{"type":"integer","minimum":100,"maximum":30000,"description":"Fixed delay in ms; with selector, the wait timeout"},"selector":{"type":"string","maxLength":500,"description":"CSS selector to wait for visibility"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type"],"additionalProperties":false,"description":"Fixed delay or wait for a selector; give milliseconds, selector or both."},{"type":"object","properties":{"type":{"type":"string","enum":["wait_for"]},"selector":{"type":"string","maxLength":500,"description":"CSS selector to wait for"},"state":{"type":"string","enum":["visible","hidden","attached","detached"],"default":"visible","description":"Element state to wait for; hidden/detached wait for disappearance (e.g. a spinner)"},"timeout":{"type":"integer","minimum":1000,"maximum":30000,"description":"Timeout in ms (default 10000)"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","selector"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["click"]},"selector":{"type":"string","maxLength":500,"description":"CSS selector of the element to click"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","selector"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fill"]},"selector":{"type":"string","maxLength":500,"description":"CSS selector of the input"},"value":{"type":"string","maxLength":5000,"description":"Value to fill in"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","selector","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["press"]},"key":{"type":"string","maxLength":50,"description":"Key to press, e.g. Enter, Tab, Escape"},"selector":{"type":"string","maxLength":500,"description":"CSS selector, or XPath when prefixed with '//' or 'xpath=' of the element to focus and press the key on; omit to press on the page"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","key"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["scroll"]},"direction":{"type":"string","enum":["down","up"],"default":"down"},"amount":{"type":"integer","minimum":1,"maximum":20,"description":"Viewport heights to scroll","default":1}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["infinite_scroll"]},"max_scrolls":{"type":"integer","minimum":1,"maximum":50,"description":"Maximum scroll iterations","default":10},"delay":{"type":"integer","minimum":200,"maximum":5000,"description":"Delay between scrolls in ms","default":1000},"end_selector":{"type":"string","maxLength":500,"description":"CSS selector that marks the end of content"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["screenshot"]},"full_page":{"type":"boolean","default":true,"description":"Capture the full page or just the viewport"}},"required":["type"],"additionalProperties":false,"description":"Capture a screenshot at this point in the sequence."},{"type":"object","properties":{"type":{"type":"string","enum":["evaluate"]},"script":{"type":"string","maxLength":5120,"description":"JavaScript to run in the page. Network APIs (fetch, XMLHttpRequest, WebSocket) and eval/Function are blocked."}},"required":["type","script"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["dismiss_consent"]},"mode":{"type":"string","enum":["hide","accept","reject"],"default":"hide","description":"hide: hide the consent overlay without changing consent state; accept/reject: click the matching button, then hide what remains."}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["select"]},"selector":{"type":"string","maxLength":500,"description":"CSS selector, or XPath when prefixed with '//' or 'xpath=' of the <select> element"},"value":{"type":"string","maxLength":500,"description":"Option value attribute to select"},"label":{"type":"string","maxLength":500,"description":"Option visible label to select"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","selector"],"additionalProperties":false,"description":"Choose a dropdown option; give exactly one of value or label. action_results[i].result holds the selected values."},{"type":"object","properties":{"type":{"type":"string","enum":["hover"]},"selector":{"type":"string","maxLength":500,"description":"CSS selector, or XPath when prefixed with '//' or 'xpath=' of the element to hover"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","selector"],"additionalProperties":false,"description":"Move the pointer over an element, e.g. to open a hover menu."},{"type":"object","properties":{"type":{"type":"string","enum":["click_text"]},"text":{"type":"string","maxLength":500,"description":"Visible text of the element to click"},"exact":{"type":"boolean","default":false,"description":"Match the whole text case-sensitively (default: case-insensitive substring)"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","text"],"additionalProperties":false,"description":"Click the first element whose visible text matches."},{"type":"object","properties":{"type":{"type":"string","enum":["extract"]},"selector":{"type":"string","maxLength":500,"description":"CSS selector, or XPath when prefixed with '//' or 'xpath=' of the element to read"},"attribute":{"type":"string","maxLength":100,"description":"Attribute to return, e.g. href; omit for the visible text"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","selector"],"additionalProperties":false,"description":"Read the first matching element's text or attribute into action_results[i].result (max 5000 chars; null when the attribute is absent)."},{"type":"object","properties":{"type":{"type":"string","enum":["check"]},"selector":{"type":"string","maxLength":500,"description":"CSS selector, or XPath when prefixed with '//' or 'xpath=' of the checkbox or radio"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","selector"],"additionalProperties":false,"description":"Check a checkbox or radio button."},{"type":"object","properties":{"type":{"type":"string","enum":["uncheck"]},"selector":{"type":"string","maxLength":500,"description":"CSS selector, or XPath when prefixed with '//' or 'xpath=' of the checkbox"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","selector"],"additionalProperties":false,"description":"Uncheck a checkbox."},{"type":"object","properties":{"type":{"type":"string","enum":["wait_event"]},"event":{"type":"string","enum":["load","domcontentloaded","networkidle"],"default":"load","description":"Load state to wait for"},"timeout":{"type":"integer","minimum":1000,"maximum":30000,"description":"Timeout in ms (default 10000)"}},"required":["type"],"additionalProperties":false,"description":"Wait until the page reaches a load state; fails on timeout."},{"type":"object","properties":{"type":{"type":"string","enum":["snapshot"]},"format":{"type":"string","enum":["html","markdown"],"default":"html","description":"Capture the rendered HTML or its markdown conversion"}},"required":["type"],"additionalProperties":false,"description":"Capture the page HTML or markdown at this step; delivered as action_results[i].snapshot_url"}]},"description":"Browser actions run in order after the page loads, before content extraction and any screenshot or PDF capture. Requires a rendered page; render_js defaults to true when actions are given. Selectors are CSS, or XPath when prefixed with '//' or 'xpath='. Failed actions are skipped and the sequence continues. The response includes action_results, one entry per action with index, type, success, error, result (evaluate, extract, select) and screenshot_url (screenshot actions)."},"screenshot":{"type":"boolean","description":"Capture a full-page screenshot after any actions (adds a small fee, uses a rendered page). The response includes screenshot_url."},"generate_pdf":{"type":"boolean","description":"Generate a PDF of the rendered page after any actions (adds a small fee, uses a rendered page). The response includes pdf_url."}},"required":["url"]}},{"name":"alterlab_extract","description":"Extract structured data (prices, product info, contact details, custom fields) as JSON from HTML, text or markdown you already hold. Use when you have content and need specific fields. Does not fetch a URL: to fetch and extract in one step, use alterlab_scrape with extraction_schema.","inputSchema":{"type":"object","properties":{"content":{"type":"string","minLength":1},"content_type":{"type":"string","enum":["html","text","markdown"],"description":"Format of the content you pass. Default: html.","default":"html"},"extraction_profile":{"type":"string"},"extraction_template":{"type":"string"},"extraction_schema":{"type":"object","description":"JSON schema for structured extraction. Fields matching this schema are extracted from the page. Example: { \"title\": \"string\", \"price\": \"number\" }"},"extraction_prompt":{"type":"string","maxLength":2000},"extraction_model":{"type":"string"},"extraction_provider":{"type":"string","enum":["openai","anthropic","openrouter","groq"]},"formats":{"type":"array","items":{"type":"string"},"description":"Output formats to return. Default: [\"json\"].","default":["json"]},"source_url":{"type":"string","maxLength":2048},"evidence":{"type":"boolean","description":"Return supporting evidence for each field. Default: false.","default":false},"cache":{"type":"string","enum":["auto","skip","only"],"description":"Cache behaviour. Default: auto.","default":"auto"},"cache_ttl":{"type":"integer","minimum":1,"maximum":86400}},"required":["content"]}},{"name":"alterlab_screenshot","description":"Use when a normal fetch returns 403/429, a bot-protection challenge page, a CAPTCHA, or an empty JavaScript shell. Capture a full-page PNG screenshot of any URL, including anti-bot-protected sites, rendered in a real headless browser. Use wait_for to wait for an element and wait_until to control load timing. Pass actions (for example dismiss_consent or evaluate) to prepare the page; the screenshot is captured after they run and action_results is returned.","inputSchema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"wait_for":{"type":"string","description":"CSS selector to wait for."},"wait_until":{"type":"string","enum":["networkidle","domcontentloaded","load"],"description":"Wait until. Default: networkidle.","default":"networkidle"},"actions":{"type":"array","maxItems":20,"items":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","enum":["wait"]},"milliseconds":{"type":"integer","minimum":100,"maximum":30000,"description":"Fixed delay in ms; with selector, the wait timeout"},"selector":{"type":"string","maxLength":500,"description":"CSS selector to wait for visibility"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type"],"additionalProperties":false,"description":"Fixed delay or wait for a selector; give milliseconds, selector or both."},{"type":"object","properties":{"type":{"type":"string","enum":["wait_for"]},"selector":{"type":"string","maxLength":500,"description":"CSS selector to wait for"},"state":{"type":"string","enum":["visible","hidden","attached","detached"],"default":"visible","description":"Element state to wait for; hidden/detached wait for disappearance (e.g. a spinner)"},"timeout":{"type":"integer","minimum":1000,"maximum":30000,"description":"Timeout in ms (default 10000)"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","selector"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["click"]},"selector":{"type":"string","maxLength":500,"description":"CSS selector of the element to click"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","selector"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["fill"]},"selector":{"type":"string","maxLength":500,"description":"CSS selector of the input"},"value":{"type":"string","maxLength":5000,"description":"Value to fill in"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","selector","value"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["press"]},"key":{"type":"string","maxLength":50,"description":"Key to press, e.g. Enter, Tab, Escape"},"selector":{"type":"string","maxLength":500,"description":"CSS selector, or XPath when prefixed with '//' or 'xpath=' of the element to focus and press the key on; omit to press on the page"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","key"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["scroll"]},"direction":{"type":"string","enum":["down","up"],"default":"down"},"amount":{"type":"integer","minimum":1,"maximum":20,"description":"Viewport heights to scroll","default":1}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["infinite_scroll"]},"max_scrolls":{"type":"integer","minimum":1,"maximum":50,"description":"Maximum scroll iterations","default":10},"delay":{"type":"integer","minimum":200,"maximum":5000,"description":"Delay between scrolls in ms","default":1000},"end_selector":{"type":"string","maxLength":500,"description":"CSS selector that marks the end of content"}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["screenshot"]},"full_page":{"type":"boolean","default":true,"description":"Capture the full page or just the viewport"}},"required":["type"],"additionalProperties":false,"description":"Capture a screenshot at this point in the sequence."},{"type":"object","properties":{"type":{"type":"string","enum":["evaluate"]},"script":{"type":"string","maxLength":5120,"description":"JavaScript to run in the page. Network APIs (fetch, XMLHttpRequest, WebSocket) and eval/Function are blocked."}},"required":["type","script"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["dismiss_consent"]},"mode":{"type":"string","enum":["hide","accept","reject"],"default":"hide","description":"hide: hide the consent overlay without changing consent state; accept/reject: click the matching button, then hide what remains."}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["select"]},"selector":{"type":"string","maxLength":500,"description":"CSS selector, or XPath when prefixed with '//' or 'xpath=' of the <select> element"},"value":{"type":"string","maxLength":500,"description":"Option value attribute to select"},"label":{"type":"string","maxLength":500,"description":"Option visible label to select"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","selector"],"additionalProperties":false,"description":"Choose a dropdown option; give exactly one of value or label. action_results[i].result holds the selected values."},{"type":"object","properties":{"type":{"type":"string","enum":["hover"]},"selector":{"type":"string","maxLength":500,"description":"CSS selector, or XPath when prefixed with '//' or 'xpath=' of the element to hover"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","selector"],"additionalProperties":false,"description":"Move the pointer over an element, e.g. to open a hover menu."},{"type":"object","properties":{"type":{"type":"string","enum":["click_text"]},"text":{"type":"string","maxLength":500,"description":"Visible text of the element to click"},"exact":{"type":"boolean","default":false,"description":"Match the whole text case-sensitively (default: case-insensitive substring)"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","text"],"additionalProperties":false,"description":"Click the first element whose visible text matches."},{"type":"object","properties":{"type":{"type":"string","enum":["extract"]},"selector":{"type":"string","maxLength":500,"description":"CSS selector, or XPath when prefixed with '//' or 'xpath=' of the element to read"},"attribute":{"type":"string","maxLength":100,"description":"Attribute to return, e.g. href; omit for the visible text"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","selector"],"additionalProperties":false,"description":"Read the first matching element's text or attribute into action_results[i].result (max 5000 chars; null when the attribute is absent)."},{"type":"object","properties":{"type":{"type":"string","enum":["check"]},"selector":{"type":"string","maxLength":500,"description":"CSS selector, or XPath when prefixed with '//' or 'xpath=' of the checkbox or radio"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","selector"],"additionalProperties":false,"description":"Check a checkbox or radio button."},{"type":"object","properties":{"type":{"type":"string","enum":["uncheck"]},"selector":{"type":"string","maxLength":500,"description":"CSS selector, or XPath when prefixed with '//' or 'xpath=' of the checkbox"},"frame":{"anyOf":[{"type":"string","maxLength":500},{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":3}],"description":"Selector of the <iframe> that contains the target; a list targets nested frames, outermost first"}},"required":["type","selector"],"additionalProperties":false,"description":"Uncheck a checkbox."},{"type":"object","properties":{"type":{"type":"string","enum":["wait_event"]},"event":{"type":"string","enum":["load","domcontentloaded","networkidle"],"default":"load","description":"Load state to wait for"},"timeout":{"type":"integer","minimum":1000,"maximum":30000,"description":"Timeout in ms (default 10000)"}},"required":["type"],"additionalProperties":false,"description":"Wait until the page reaches a load state; fails on timeout."},{"type":"object","properties":{"type":{"type":"string","enum":["snapshot"]},"format":{"type":"string","enum":["html","markdown"],"default":"html","description":"Capture the rendered HTML or its markdown conversion"}},"required":["type"],"additionalProperties":false,"description":"Capture the page HTML or markdown at this step; delivered as action_results[i].snapshot_url"}]},"description":"Browser actions run in order after the page loads, before content extraction and any screenshot or PDF capture. Requires a rendered page; render_js defaults to true when actions are given. Selectors are CSS, or XPath when prefixed with '//' or 'xpath='. Failed actions are skipped and the sequence continues. The screenshot is captured after the actions run, and action_results is returned alongside it."}},"required":["url"]}},{"name":"alterlab_crawl","description":"Crawl a whole website and return the content of every page, for RAG, indexing or site-wide export. Use when you need many pages from one domain; for one URL use alterlab_scrape, for a URL list only use alterlab_map. Works on JavaScript-heavy and protected sites, with anti-bot handling on every page. Returns a crawl_id immediately; results are available from GET /api/v1/crawl/{crawl_id}.","inputSchema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"max_pages":{"type":"integer","minimum":1,"maximum":100000,"description":"Maximum number of pages. Default: 50.","default":50},"max_depth":{"type":"integer","minimum":0,"maximum":20,"description":"Maximum link depth from the start URL. Default: 3.","default":3},"include_patterns":{"type":"array","items":{"type":"string"}},"exclude_patterns":{"type":"array","items":{"type":"string"}},"sitemap":{"type":"string","enum":["include","skip","only"],"description":"Sitemap handling. Default: include.","default":"include"},"sitemap_path":{"type":"string"},"formats":{"type":"array","items":{"type":"string","enum":["text","json","json_v2","html","markdown"]}},"extraction_schema":{"type":"object","description":"JSON schema for structured extraction. Fields matching this schema are extracted from the page. Example: { \"title\": \"string\", \"price\": \"number\" }"},"extraction_profile":{"type":"string","enum":["auto","product","article","job_posting","faq","recipe","event"]},"headers":{"type":"object","additionalProperties":{"type":"string"}},"extraction_model":{"type":"string"},"render_js":{"description":"Render JavaScript with a headless browser. 'auto' renders only when needed. Default: false.","anyOf":[{"type":"boolean"},{"type":"string","enum":["auto"]}],"default":false},"use_proxy":{"type":"boolean","default":false,"description":"Route through a premium proxy. Default: false."},"max_concurrency":{"type":"integer","minimum":1,"maximum":50,"description":"Maximum parallel page fetches. Default: 10.","default":10},"respect_robots":{"type":"boolean","description":"Obey robots.txt. Default: true.","default":true},"include_subdomains":{"type":"boolean","description":"Include subdomains of the site. Default: false.","default":false},"wait_for":{"type":"string"},"timeout":{"type":"number","minimum":1,"maximum":300},"webhook_url":{"type":"string","format":"uri"},"cost_controls":{"type":"object","properties":{"max_credits":{"type":"integer","exclusiveMinimum":0},"max_tier":{"type":"string","enum":["1","2","3","3.5","4"]},"force_tier":{"type":"string","enum":["1","2","3","3.5","4"]}}}},"required":["url"]}},{"name":"alterlab_search","description":"Search the web and get structured results (URLs, titles, snippets). Use when you have a question or topic but no URL yet; follow up with alterlab_scrape to read a page, or set scrape_results=true to read every result in one call. Use domain to restrict to one site and time_range to filter by recency.","inputSchema":{"type":"object","properties":{"query":{"type":"string","minLength":1,"maxLength":500},"num_results":{"type":"integer","minimum":1,"maximum":30,"description":"Number of results to return. Default: 10.","default":10},"page":{"type":"integer","minimum":1,"maximum":10,"description":"Results page number. Default: 1.","default":1},"domain":{"type":"string"},"country":{"type":"string","minLength":2,"maxLength":2},"language":{"type":"string","minLength":2,"maxLength":5},"time_range":{"type":"string","enum":["hour","day","week","month","year"]},"scrape_results":{"type":"boolean","description":"Also scrape each result page. Default: false.","default":false},"formats":{"type":"array","items":{"type":"string","enum":["text","json","json_v2","html","markdown"]}},"extraction_schema":{"type":"object","description":"JSON schema for structured extraction. Fields matching this schema are extracted from the page. Example: { \"title\": \"string\", \"price\": \"number\" }"},"safe_search":{"type":"boolean"}},"required":["query"]}},{"name":"alterlab_map","description":"List every URL on a site via sitemap parsing and link extraction, without fetching page content. Use before alterlab_crawl or alterlab_batch to choose pages; to read the content itself use alterlab_crawl. Works on JavaScript-heavy and protected sites.","inputSchema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"max_pages":{"type":"integer","minimum":1,"maximum":50000,"description":"Maximum number of pages. Default: 500.","default":500},"max_depth":{"type":"integer","minimum":0,"maximum":10,"description":"Maximum link depth from the start URL. Default: 3.","default":3},"include_patterns":{"type":"array","items":{"type":"string"}},"exclude_patterns":{"type":"array","items":{"type":"string"}},"search":{"type":"string","maxLength":500},"sitemap":{"type":"string","enum":["include","skip","only"],"description":"Sitemap handling. Default: include.","default":"include"},"sitemap_path":{"type":"string"},"include_metadata":{"type":"boolean","description":"Include per-URL metadata. Default: false.","default":false},"include_subdomains":{"type":"boolean","description":"Include subdomains of the site. Default: false.","default":false},"respect_robots":{"type":"boolean","description":"Obey robots.txt. Default: true.","default":true}},"required":["url"]}},{"name":"alterlab_batch_scrape","description":"Use when a normal fetch returns 403/429, a bot-protection challenge page, a CAPTCHA, or an empty JavaScript shell. Scrape 2-20 URLs in parallel and get all results back in one call, no polling required. Failed URLs report their error; successful ones return content. For 20+ URLs use alterlab_batch.","inputSchema":{"type":"object","properties":{"urls":{"type":"array","items":{"type":"string","format":"uri"},"minItems":1,"maxItems":20},"formats":{"type":"array","items":{"type":"string","enum":["text","json","json_v2","html","markdown","rag","content"]},"description":"Output formats to return. Default: [\"markdown\"].","default":["markdown"]},"render_js":{"type":"boolean","description":"Render JavaScript with a headless browser. Default: false.","default":false},"use_proxy":{"type":"boolean","default":false,"description":"Route through a premium proxy. Default: false."},"timeout":{"type":"integer","minimum":1,"maximum":300,"description":"Timeout. Default: 90.","default":90},"max_concurrent":{"type":"integer","minimum":1,"maximum":10,"description":"Max concurrent. Default: 3.","default":3}},"required":["urls"]}},{"name":"alterlab_batch","description":"Use when a normal fetch returns 403/429, a bot-protection challenge page, a CAPTCHA, or an empty JavaScript shell. Scrape large URL sets (up to 100 per call) asynchronously. Each URL can have its own mode, formats and extraction_schema. Returns a batch_id immediately; results are available from GET /api/v1/batch/{batch_id}.","inputSchema":{"type":"object","properties":{"urls":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"mode":{"type":"string","enum":["auto","html","js","pdf","ocr"],"default":"auto","description":"Scraping mode: auto (recommended), html, js (headless browser), pdf, or ocr"},"formats":{"type":"array","items":{"type":"string"}},"extraction_schema":{"type":"object","description":"JSON schema for structured extraction. Fields matching this schema are extracted from the page. Example: { \"title\": \"string\", \"price\": \"number\" }"},"render_js":{"type":"boolean"},"use_proxy":{"type":"boolean"},"timeout":{"type":"integer","minimum":1,"maximum":300},"wait_for":{"type":"string"},"cache":{"type":"boolean","default":false}},"required":["url"]}},"webhook_url":{"type":"string","format":"uri"}},"required":["urls"]}},{"name":"alterlab_estimate_cost","description":"Estimate the credit cost of scraping a URL before you run it. Use when cost matters or before a large job; no credits are charged. Returns the predicted tier, estimated cost and confidence. Full machine-readable price list: GET https://alterlab.io/api/v1/pricing (public, no auth).","inputSchema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"mode":{"type":"string","enum":["auto","html","js","pdf","ocr"],"default":"auto","description":"Scraping mode: auto (recommended), html, js (headless browser), pdf, or ocr Default: auto."},"formats":{"type":"array","items":{"type":"string"}},"render_js":{"type":"boolean","description":"Render JavaScript with a headless browser. Default: false.","default":false},"use_proxy":{"type":"boolean","description":"Route through a premium proxy. Default: false.","default":false}},"required":["url"]}},{"name":"alterlab_create_account","description":"Create an AlterLab account and API key for your user. Use only when no ALTERLAB_API_KEY exists yet; skip it if a key is already configured. Signup is on behalf of your user (agent signup with human approval). Nothing is created until the human approves: they get an email (and you get a verification_url and user_code to show them) describing what the agent can do. After approval you receive a scoped API key labeled with agent_name, with a default daily spend cap, revocable from the dashboard. No extra free credit is granted; the usual welcome rules apply to the human's account. If the human has not approved yet, the result contains the signup_id, verification_url and user_code; poll GET /api/v1/agent/signup/{signup_id} or call this tool again.","inputSchema":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"Email address of the human who will own the account and approve the request."},"agent_name":{"type":"string","default":"MCP client","description":"Name of this agent, shown to the human and used to label the API key. Default: MCP client."}},"required":["email"]}}]}