Skip to main content
Glama

Fetch a web page

web_access_fetch
Destructive

Fetch a caller-specified HTTP(S) URL and get clean, LLM-ready Markdown back.

Primary use (the common case): pass only a url. The page is fetched with a normal GET and returned as Markdown — no other parameters are needed.

{ "url": "https://example.com/article" }

Best for: any URL, especially sites that block automated traffic or render their content client-side (news, docs, blogs, web apps). Not for: searching the web when you don't have a URL — use web_access_search instead.

Optional parameters (omit unless you need them):

  • format — markdown (default), raw (the destination's verbatim body), or json (a { statusCode, headers, data } envelope with the destination's status and headers).

  • executeJS — set true to render JavaScript for SPAs when the content comes back empty.

  • actions — drive a real browser (click, scroll, type, wait) before capturing the page. See below.

To send a direct POST, PUT or PATCH (with a body), use web_access_request — this tool's direct HTTP path only issues GETs. Plenty of those calls are reads: a GraphQL query, a search backend that takes a body, a JSON API that refuses GET.

  • headers — forward custom request headers; not combinable with executeJS or actions, which run in a browser.

  • countryCode — ISO 3166-1 alpha-2 (e.g. "US") to route through a proxy in that country.

  • solveCaptcha — defaults true; set false to fail fast instead of spending effort solving a challenge.

Returns: Markdown by default; the verbatim body or a JSON envelope when format is set accordingly.


actions — driving the page instead of just loading it

An actions sequence runs in a real browser session and returns the page as it stands after the last step. Use it when the content you need does not exist in the document until something happens to the page: a click past a consent gate, a search form submitted, a "load more" button, a tab or accordion opened, or rows that only render once scrolled into view. Actions can modify destination data or submit a form, so clients should treat any call to this tool as potentially destructive.

Escalate in this order — each step takes longer than the last, and steps 2 and 3 bill at the browser rate:

  1. Plain url — always try this first.

  2. executeJS: true — the page renders client-side but needs no interaction.

  3. actions — the content requires interaction. Takes tens of seconds and holds a browser session.

If the data is still absent after all three, it is likely never in the HTML at all — look for the JSON API the page itself calls and fetch that endpoint directly, which is faster and returns exact values.

Steps (max 50 per request; at most one screenshot):

  • {"type": "wait", "selector": ".price", "timeout": 20000} — wait until the selector appears, then continue immediately. Prefer this over a fixed pause.

  • {"type": "wait", "milliseconds": 3000} — fixed pause. Max 30000ms, as is timeout above.

  • {"type": "click", "selector": "#accept", "all": false} — all: true clicks every match.

  • {"type": "write", "text": "..."} — types into the focused element; click it first.

  • {"type": "press", "key": "Enter"}

  • {"type": "scroll", "direction": "down", "amount": 1000, "selector": "..."} — selector scrolls that element instead of the page.

  • {"type": "hover", "selector": "..."}

  • {"type": "selectOption", "selector": "select#size", "value": "L"} — value may be an array.

  • {"type": "navigate", "url": "https://..."} — go to another page mid-session, keeping cookies and state.

  • {"type": "screenshot", "full_page": true, "quality": 80}

The session opens on url before your first step, so never begin with a navigate to that same URL.

Examples

Dismiss a cookie banner, then read the page:

{ "url": "https://example.com/pricing", "actions": [
  { "type": "click", "selector": "#accept-cookies" },
  { "type": "wait", "selector": "main .plan", "timeout": 15000 }
] }

Run a search the site offers no URL for:

{ "url": "https://example.com", "actions": [
  { "type": "click", "selector": "input[name=q]" },
  { "type": "write", "text": "standing desk" },
  { "type": "press", "key": "Enter" },
  { "type": "wait", "selector": ".results .item", "timeout": 20000 }
] }

Fill in rows that render only as they scroll into view:

{ "url": "https://example.com/listings", "actions": [
  { "type": "wait", "selector": ".card", "timeout": 20000 },
  { "type": "scroll", "direction": "down" },
  { "type": "wait", "milliseconds": 1500 },
  { "type": "scroll", "direction": "down" },
  { "type": "wait", "milliseconds": 1500 }
] }

Returns with actions: a JSON object — data (the final page, Markdown by default), finalUrl, statusCode, and screenshot when the sequence took one. If a step fails, the call still succeeds and returns error plus failedActionIndex, a 0-based index into your actions array, with data holding the page as it stood at that point — read it to see what the page actually showed, then fix that step's selector.

Not combinable with headers or format: "raw"; a browser session is always a GET.

Requests must comply with destination policy, robots directives, rate limits, and access controls. Challenge handling is subject to the caller's String account and organization policy.

Input Schema

NameRequiredDescriptionDefault
urlYesThe full URL of the webpage to fetch. Must be a valid HTTP/HTTPS URL.
formatNoOutput format: 'markdown' for clean LLM-optimized text (recommended), 'raw' for the destination's verbatim body, 'json' for a { statusCode, headers, data } envelope.
actionsNoBrowser actions to run in order before the page is captured, for content that only appears after interaction. Max 50, at most one screenshot. Not combinable with headers, format 'raw' or solveCaptcha false.
headersNoCustom request headers to forward (max 50). Not combinable with executeJS or actions.
executeJSNoEnable JavaScript rendering for SPAs and dynamic content. Set to true if content appears empty or incomplete.
countryCodeNoISO 3166-1 alpha-2 country code for geolocated proxy routing, e.g. 'US'.
solveCaptchaNoWhether to attempt captcha solving. Defaults to true server-side; set false to fail fast on challenges.

Output Schema

NameRequiredDescriptionDefault
bodyYes
errorNoSet when a browser action step failed. The call still succeeds, and body holds the page as it stood when the step failed.
headersYes
finalUrlNo
screenshotNo
statusCodeYes
failedActionIndexNo0-based index into the request's actions array identifying the step that failed.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed10 schema fields changed
    • changedInput schema / properties / actions / description
      Previous value: -"Browser actions to run in order before the page is captured, for content that only appears after interaction. Max 50, at most one screenshot. Not combinable with method, body, headers, or format 'raw'."New value: +"Browser actions to run in order before the page is captured, for content that only appears after interaction. Max 50, at most one screenshot. Not combinable with headers, format 'raw' or solveCaptcha false."
    • removedInput schema / properties / body
      Removed value: -{
      -  "description": "Request body for POST/PUT/PATCH. A string is sent as-is; an object is JSON-stringified. Not allowed for GET."
      -}
    • changedInput schema / properties / executeJS / description
      Previous value: -"Enable JavaScript rendering for SPAs and dynamic content. Set to true if content appears empty or incomplete. Cannot be combined with custom headers."New value: +"Enable JavaScript rendering for SPAs and dynamic content. Set to true if content appears empty or incomplete."
    • changedInput schema / properties / format / description
      Previous value: -"Output format: 'markdown' for clean LLM-optimized text (recommended), 'raw' for the verbatim upstream body, 'json' for a { statusCode, headers, data } envelope."New value: +"Output format: 'markdown' for clean LLM-optimized text (recommended), 'raw' for the destination's verbatim body, 'json' for a { statusCode, headers, data } envelope."
    • changedInput schema / properties / headers / description
      Previous value: -"Custom request headers to forward (max 50). Not supported when executeJS is enabled."New value: +"Custom request headers to forward (max 50). Not combinable with executeJS or actions."
    • removedInput schema / properties / method
      Removed value: -{
      -  "description": "HTTP method for the request (GET/POST/PUT/PATCH), defaults to GET. Use POST/PUT/PATCH to send a body.",
      -  "type": "string"
      -}
    • removedOutput schema / additionalProperties
      Removed value: -false
    • addedOutput schema / properties / error / description
      Added value: +"Set when a browser action step failed. The call still succeeds, and body holds the page as it stood when the step failed."
    • addedOutput schema / properties / failedActionIndex / description
      Added value: +"0-based index into the request's actions array identifying the step that failed."
    • removedOutput schema / properties / screenshot / additionalProperties
      Removed value: -false
  2. Changed5 schema fields changed
    • addedInput schema / properties / actions
      Added value: +{
      +  "description": "Browser actions to run in order before the page is captured, for content that only appears after interaction. Max 50, at most one screenshot. Not combinable with method, body, headers, or format 'raw'.",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "all": {
      +        "description": "click: click every element matching the selector instead of the first.",
      +        "type": [
      +          "null",
      +          "boolean"
      +        ]
      +      },
      +      "amount": {
      +        "description": "scroll: distance in pixels.",
      +        "type": [
      +          "null",
      +          "integer"
      +        ]
      +      },
      +      "direction": {
      +        "description": "scroll: up, down, left, or right.",
      +        "type": "string"
      +      },
      +      "full_page": {
      +        "description": "screenshot: capture the whole scrollable page rather than the viewport.",
      +        "type": [
      +          "null",
      +          "boolean"
      +        ]
      +      },
      +      "key": {
      +        "description": "press: the key to press, e.g. 'Enter'.",
      +        "type": "string"
      +      },
      +      "milliseconds": {
      +        "description": "wait: pause this many milliseconds (max 30000). Prefer waiting on a selector.",
      +        "type": [
      +          "null",
      +          "integer"
      +        ]
      +      },
      +      "quality": {
      +        "description": "screenshot: JPEG quality, 1-100.",
      +        "type": [
      +          "null",
      +          "integer"
      +        ]
      +      },
      +      "selector": {
      +        "description": "CSS selector. Required for click, hover and selectOption; on wait it waits for the element to appear; on scroll it scrolls that element instead of the page.",
      +        "type": "string"
      +      },
      +      "text": {
      +        "description": "write: the text to type into the focused element.",
      +        "type": "string"
      +      },
      +      "timeout": {
      +        "description": "wait with a selector: give up after this many milliseconds (max 30000).",
      +        "type": [
      +          "null",
      +          "integer"
      +        ]
      +      },
      +      "type": {
      +        "description": "The action to run: wait, click, write, press, scroll, screenshot, navigate, hover, or selectOption.",
      +        "type": "string"
      +      },
      +      "url": {
      +        "description": "navigate: the URL to go to, carrying the session's cookies and state.",
      +        "type": "string"
      +      },
      +      "value": {
      +        "description": "selectOption: the option value to select, or an array of them for a multi-select."
      +      }
      +    },
      +    "required": [
      +      "type"
      +    ],
      +    "type": "object"
      +  },
      +  "type": [
      +    "null",
      +    "array"
      +  ]
      +}
    • addedOutput schema / properties / error
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / failedActionIndex
      Added value: +{
      +  "type": [
      +    "null",
      +    "integer"
      +  ]
      +}
    • addedOutput schema / properties / finalUrl
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / screenshot
      Added value: +{
      +  "additionalProperties": false,
      +  "properties": {
      +    "base64": {
      +      "type": "string"
      +    },
      +    "format": {
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "format",
      +    "base64"
      +  ],
      +  "type": [
      +    "null",
      +    "object"
      +  ]
      +}
  3. First observed

TDQS

A4.9/5.0
Behavior5/5

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

Goes well beyond annotations: browser-rate billing, session duration (tens of seconds), max 50 actions / one screenshot, 30000ms caps, failure semantics (call still succeeds, returns error + failedActionIndex with partial data), incompatibility matrix (headers, format raw, solveCaptcha false), and that action sequences can mutate destination state — consistent with destructiveHint=true.

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

Conciseness4/5

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

Front-loaded with the primary use and well-structured with bold headers, inline JSON examples and bullet lists proportional to a 7-parameter nested tool. It loses a point for some redundancy — `format` and the action-return shape are described twice (optional parameters block and Returns block).

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 complex, open-world, nested-schema tool, nothing essential is missing: invocation shape, escalation strategy, per-action contract, failure handling, and the policy/robots caveat are all covered. An output schema exists, yet the action-mode return shape is still explained where it matters.

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

Parameters5/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, but the description adds substantial meaning on top: when to pick each format, when executeJS is warranted vs. actions, per-action semantics with examples, and the non-combinability rules between headers, executeJS and actions.

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 a caller-specified HTTP(S) URL") and names the output ("clean, LLM-ready Markdown"). It also explicitly disambiguates against siblings: web_access_search for searching without a URL, web_access_request for POST/PUT/PATCH bodies.

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?

Gives the common case (pass only url), a "Best for" and a "Not for" section, and a three-step escalation ladder (plain url → executeJS → actions) with cost/latency guidance. It even tells the agent what to do if all three fail (find the underlying JSON API).

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.