web_access_fetch
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 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:
```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.
web_access_search
Search the public web for a caller-specified query and get ranked organic results back, plus whatever Google rendered around them: knowledge panel, AI overview, People also ask, local pack, videos, discussions. Google's images, videos, shopping, books, places and forums tabs are searched with `searchType`.
**Primary use:** pass a `query` string. There is no engine or domain-filter parameter; any other key is rejected before the call.
```json
{ "query": "site:arxiv.org retrieval augmented generation" }
```
**Optional targeting fields:** `country` — ISO 3166-1 alpha-2 code the search runs from, e.g. `GB` (default `US`); `language` — results language tag such as `en` or `pt-br`.
```json
{ "query": "plumbers", "country": "GB", "language": "en" }
```
To search from a place, send `location`, a place name such as `London` or `Austin,Texas,United States` (1 to 200 characters), or `coordinates`, `{ latitude, longitude, radius }` with radius in meters (default 5000). The search is sent from that place's country; if both are sent, `coordinates` win. A name that cannot be placed fails, so send `coordinates` instead. On the results page the place biases results toward it. The effect is strongest for queries like `plumbers near me`, and it is not exact city targeting: a bare query such as `coffee shops` may still return results from a wider area.
```json
{ "query": "plumbers near me", "location": "Austin,Texas,United States" }
```
**Optional request field:** `searchCount` — how many organic results you want, an integer from 1 to 300 (above 300 is rejected). Google is paged, up to 36 pages, until that many are in hand; each page is billed as one search. Many queries run out before 300: Google often has 100-200 results for a query, and you get what it has, with `paging.complete: true` and `paging.stoppedBy: "end_of_results"`. Omit it for one page, about 10 results, and the response then carries no `paging`. Not with `format: "raw"`, which returns one page per call.
```json
{ "query": "construction consulting firms Ohio", "searchCount": 30 }
```
**Optional Google field:** `searchType` — the Google tab to search: `"web"` (the default, the ordinary results page), `"images"`, `"videos"`, `"shopping"`, `"books"`, `"places"` or `"forums"`. There is no news tab. Each page fetched is billed as one search, as on the web.
- `videos`, `books`, `forums` answer `results`, paged like the web; each video carries `video` (`channel`, `platform`, `duration`) and each book `book` (`authors`, `published`).
- `images` answers `images`, about 100 a page, each with `title`, `url` (the page it is on), `source`, `imageUrl` (the file), `imageWidth`, `imageHeight` and `thumbnail`. It has 3 pages; `searchCount` up to 300 collects across them, usually about 270 images.
- `shopping` answers `products`, the one page of about 55 product cards: `title`, `productId`, `price` and `originalPrice` as shown, `merchant` and `moreMerchants`, `delivery`, `returns`, `rating`, `reviews`. A card has no `url`. Google does not page this tab, so `page` must be 1.
- `places` answers `places`, 20 businesses a page, paged like the web up to page 15.
`results` is empty for images, shopping and places. `dateRange`, `sortBy` and `verbatim` apply to web, videos and forums only; `format: "raw"` and `aiOverview` to web only.
```json
{ "query": "eames lounge chair", "searchType": "images", "searchCount": 150 }
```
**Optional Google filters:** `safeSearch` — `true` removes explicit results; `includeOmittedResults` — `true` includes the results Google hides as very similar to ones shown; `autocorrect` — `false` searches the query exactly as typed instead of Google's correction; `restrictCountry` — a two-letter code — keeps only pages from that country (unlike `country`, which sets where the search runs from); `verbatim` — `true` matches the words exactly, without synonyms. None combines with `aiMode`.
```json
{ "query": "climate policy", "restrictCountry": "FR", "safeSearch": true }
```
**Optional Google fields:** `page`, `dateRange` and `sortBy` apply to Google results only; none of them combines with `aiMode`.
- `page` — the results page to start from, an integer from 1 to 30 (default 1), where page N is the page Google shows as N. Without `searchCount` the response is that one page; with it, `searchCount` results are collected starting from that page. `page` and `searchCount` together stay within the first 300 results: (page - 1) × 10 + (`searchCount`, or 10 without it) must be at most 300. A page past Google's last result returns no results with `zeroResults: true`. Pages hold 8-10 results, so separate `page` calls can repeat or skip a result; for one list without repeats, send one call with `searchCount`.
- `dateRange` — limit results to a publication window: one of `"hour"`, `"day"`, `"week"`, `"month"` or `"year"` for the past hour through the past year, or `{ "from": "2024-01-01", "to": "2024-06-30" }` for a custom range of ISO dates (YYYY-MM-DD), inclusive. Either end is optional but at least one is required, and `from` must not be after `to`.
- `sortBy` — `"relevance"` (the default) or `"date"` for the newest results first.
```json
{ "query": "heat pump grants", "page": 2, "dateRange": "month", "sortBy": "date" }
```
**Optional Google field:** `format` — `"structured"` (the default, recommended) for the parsed results above as JSON, or `"raw"` for the Google results page as HTML, one page per call. The response is then `html`, `htmlBytes` and `htmlTruncated` in place of `results` and the surfaces. This tool sends at most 60,000 bytes of markup per call and sets `htmlTruncated: true` when it cuts the page; for the whole page, call the HTTP API's POST /v1/search with `format: "raw"`. Raw supports `page` only, not `searchCount`: a raw call with `searchCount` is rejected (the API answers 400), so ask for page N with `page` and send one call per page, each billed as one search. `dateRange` and `sortBy` work with raw. Not combinable with `aiMode`.
```json
{ "query": "heat pump grants", "format": "raw" }
```
**Optional request field:** `aiMode: true` — ask Google AI Mode instead of the results page. The response is `aiMode`, one generated answer with the pages it cites and any products, places and videos it shows, and `results` is empty. Billed as one search. It cannot be combined with `searchCount`. If an AI Mode answer isn't available for the query, the call fails instead of returning a results page; retry, or search without it.
```json
{ "query": "how does a heat pump work", "aiMode": true }
```
With `aiMode`, `location` or `coordinates` sets the place the answer is given for; the answer stays in `language`. Without either, a question that depends on where you are, such as today's weather, may be answered without a location.
```json
{ "query": "best bakeries nearby", "aiMode": true, "coordinates": { "latitude": 48.8566, "longitude": 2.3522 } }
```
**Optional request field:** `aiOverview: true` — fill the AI Overview Google streams in after the results page loads. It makes a second, sequential fetch and adds latency: about 64% of results pages carry a streamed overview, and filling it adds about 2.8 s at p50 and 5.6 s at p90. A request with `aiOverview: true` costs 2x a normal search. Off by default: without it, an overview already present in the page is still returned, and a streamed one comes back as `declined: true`. Not combinable with `aiMode`.
```json
{ "query": "best cushioned marathon shoes", "aiOverview": true }
```
**Best for:** a request that names no URL, or one that needs sources found before anything is read.
**Not for:** a URL you already have — use web_access_fetch instead.
**Query operators:** quoted phrases and `site:` pass through to the search engine, so `site:example.com pricing` keeps results on that host. Other operators are untested — do not rely on them.
**Returns:** `results`, the ranked web documents, each with `position` (its place in this response, from 1), `rank` (its absolute Google rank, so page 3 starts at 21; Google only), `title`, `url` (the link to fetch; absent when Google hid the destination, and the result is still returned), `snippet`, `displayUrl` (Google's displayed URL line, empty when Google shows none, as on Reddit and YouTube results), `displayText` (the source line Google shows under the title, verbatim: a URL, engagement counts such as `20+ comments · 3 months ago`, or other text), `source` when Google names the site (such as `Reddit · r/buildapc`), and `timestamp` when the engine dates it; and `zeroResults`, true when the engine itself reported no match (broaden the query; retrying will not help). Every other field is a surface Google rendered around the documents, present only when the page carried it, never merged into `results`, and only Google returns them:
- `entity` — the knowledge panel for the one business or person the query named: `title`, `subtitle`, `description` with its `descriptionSource`, `rating`, `reviews`, `website`, labelled `attributes` (address, phone, hours…), social `profiles`, and `unread` module ids the read skipped. Often the whole answer for a query naming a single business, with `results` empty.
- `places` — local-pack business listings: `name`, `category`, `rating`, `reviews`, `address`, `phone`, `hours`, `url`, `mapsUrl`. Also often answers a business query with `results` empty, so read `entity` and `places` before treating an empty `results` as no answer. With `searchType: "places"` it is the whole answer.
- `products` — only with `searchType: "shopping"`, the product cards described above.
- `overviews` — Google's AI overviews. The first entry with no `topic` is the query's own summary; entries with a `topic` and `question` are the "Things to know" tabs; an entry with `declined: true` is a frame Google rendered and did not fill, which includes an overview Google streams in when `aiOverview` was not set. Each carries `text` (paragraphs and `- ` list items on their own lines) and `sources`, the cited pages as `{ title, url }` — fetch those to verify a claim.
- `peopleAlsoAsk` — `{ question }` entries; answers are not on the page. `relatedSearches` — query strings Google suggests.
- `answers` — one single-purpose widget under `localTime`, `currency`, `unitConversion`, `weather`, `translation`, `sports` or `flights`.
- `spelling` — `{ kind, query, asked }`: `substituted` means the results are for the corrected `query`, `suggested` means they are for the query as typed.
- `ads` (sponsored, with `advertiser`), `videos` and `shortVideos` (`platform`, `channel`, `date`, `duration`), `discussions` (`site`, `forum`, `comments`, `age`, `excerpt`), `images` (`source`; with `searchType: "images"` the whole answer, with the image file too), `sitelinks` (`resultPosition` of the result they sit under). Every entry has `position` and `title`, and `url` when its destination is known.
- `aiMode` — only with `aiMode: true`: Google's AI Mode answer. `text` is plain text (one block per line, list items as `- `, table rows with cells joined by ` | `); `markdown` is the same answer as Markdown, with headings, lists, tables and code; `blocks` is its structure in reading order, each `{ type }` of `paragraph`, `heading` (`text`, `level`), `list` (`ordered`, `items`), `table` (`header`, `rows`, one cell per column) or `code` (`text`, `language`). `sources` are the cited pages as `{ title, url, snippet, source }`: `snippet` is the passage quoted, `source` the site's name, and `url` is absent when a citation could not be resolved. When the answer shows them, `products` (`title`, `price` and `oldPrice` as displayed, `merchant` and `moreSellers`, `rating`, `reviews`, `thumbnail`, `productId`, `url`), `places` (`name`, `category`, `rating`, `reviews`, `priceLevel`, `status`, `address`, `description`, `url`) and `videos` (`title`, `url`, `channel`, `duration`, `thumbnail`). Every field but `text` and `sources` is absent when empty. Fetch the sources to verify a claim.
- `paging` — `{ pages, complete, stoppedBy }`, only when `searchCount` was sent. `pages` is how many results pages answered, each billed as one search. `stoppedBy` is why paging stopped: `search_count` (the count was reached), `end_of_results` (Google had no more), `page_cap` (the 36-page depth limit; Google may have more), `page_failed` (a later page could not be fetched) or `deadline` (the time budget ran out). `complete` is false only for `page_failed` and `deadline`, and `results` then holds what was collected. Surfaces describe the first page only; positions run on across pages.
**A snippet is not the page, and an overview is not a source.** To read a result, call `web_access_fetch` on its `url` before answering from it.
Requests must comply with destination policy, rate limits, and access controls.