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.
```json
{ "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 costs more time and money than the last:**
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:
```json
{ "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:
```json
{ "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:
```json
{ "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.