AI agents needing reliable Google search have a new self-hosted option. gsearch delivers actual Google results pages as typed JSON, including AI Overview, People also ask, and related searches. A real Firefox instance running Camoufox renders Google's page as-is on the user's IP or through any proxy. The project addresses a genuine problem: plain HTTP hits a JavaScript wall, automated Chrome triggers CAPTCHAs two out of two times in testing, and Google's official Custom Search API shuts down on 1 January 2027. Other MCP servers either don't use Google's index or charge per query.
gsearch returns every link resolved to its real URL without loading the destination page. It serves AI Overview and People also ask sections when Google displays them. Error codes are explicit — captcha, soft_block, hard_block, consent_wall, js_gate, rate_limited, parse_drift, network, proxy, backend_unavailable, invalid_request — each accompanied by retry_after_s so agents know precisely how long to wait. Every string is flagged as untrusted web content through meta.untrusted_content, and blocks never return empty lists.
How it compares to other search MCP servers
gsearch is the only option that uses Google's own index alongside AI Overview and People also ask. SerpApi and Bright Data require paid accounts and charge per query. Brave, Tavily, and Exa rely on their own indexes, not Google's. DuckDuckGo and SearXNG MCPs depend on the specific instance. Playwright plus Chromium Google MCPs were observed sending users to CAPTCHAs two out of two times on IPs where gsearch operated successfully.
The table below summarizes the comparison as of October 2026:
| | gsearch | SerpApi, Bright Data | Brave, Tavily, Exa | DuckDuckGo, SearXNG MCPs | Playwright + Chromium Google MCPs |
|---|---|---|---|---|---|
| Google's own results | ✅ | ✅ | ❌ their own index | ❌ / depends on the instance | ✅ |
| API key or account | none | required | required | none | none |
| Cost | free (+ your proxy, optional) | per query | usage-based plans | free | free |
| Runs on your machine | ✅ | ❌ hosted | ❌ hosted | ✅ | ✅ |
| AI Overview, People also ask | ✅ | ✅ (SerpApi) | ❌ | ❌ | varies |
| Google's redirect links resolved to real URLs | ✅ | ✅ | n/a | n/a | varies |
| Blocks reported as errors with a retry time | ✅ | n/a | n/a | varies | varies |
| Terms-of-Service risk is yours | yes (Legal) | the provider's | no | low | yes |
"Varies" indicates projects not tested in the measurement campaign. The only Chromium measurement recorded was F-0001: Playwright Chrome was sent to a CAPTCHA two out of two times on an IP where gsearch was served.
What you get from gsearch
An MCP server with two tools. google_search accepts a query and optional parameters — page (1–50), lang (en, fr, ...), country (us, ...), time_range (h, d, w, m, y), site (a domain) — and returns the JSON structure plus a short text summary, or an error result on a block. google_search_status returns proxy data used against the limit, IPs used and blocked, and the cache without contacting Google.
The returned JSON includes:
- organic[].url — the real destination of each result, resolved from Google's /goto redirect in the same session
- organic[].title, snippet, date, domain, display_url — text as Google serves it; link keeps the exact link Google served
- organic[].sitelinks, source_meta — a result's sub-links, and what Google shows instead of a URL on forum and video results
- ai_overview — the AI Overview text and its sources, when Google shows one
- people_also_ask, related_searches — the questions and related queries on the page
- ads — text ads, when the market serves them
- pagination — current page and next page; ask for more results with page
- meta.untrusted_content — always true: every string is third-party web text
A block is never an empty list. It comes back as an error that says what happened and how long to wait (retry_after_s). Error codes include captcha, soft_block, hard_block, consent_wall, js_gate, rate_limited, parse_drift, network, proxy, backend_unavailable, invalid_request.
How it works
A real Firefox browser (Camoufox, a hardened build) runs Google's search page as a person would. The query is typed into the address bar. WebRTC is off so the user's IP cannot leak around the proxy. Camoufox presents a real-device fingerprint and a locale that matches its IP. Links hidden behind Google's /goto redirects are resolved to their actual destinations on the same IP with the same cookies and a TLS fingerprint matching the browser — this is what makes URL resolution reliable without loading each target page.
Without a proxy, gsearch uses your own IP with a warm session. Each search takes approximately 1.2 seconds, with zero CAPTCHAs in testing. This session is capped at 20 searches per hour and 150 per day to keep the IP clean. For higher volume, add a proxy in any format — rotating residential, static VPS or datacenter, HTTP, HTTPS or SOCKS5, in any common layout. Every byte passes through a local relay that counts it, and GSEARCH_DATA_LIMIT_MB stops everything at your limit across restarts.
Rotating residential proxies give a new IP and a new browser for each search, up to three at once. A blocked IP is replaced, up to four IPs per search. Country codes in the login are validated; exits outside the selected country are dropped. Static proxies (VPS, datacenter, ISP) keep one warm session each; IPs take turns. Each static IP has its own budget — 20 searches an hour, 150 a day — and rests until midnight after a CAPTCHA, so ten IPs allow roughly 200 searches an hour.
Performance measurements
Measured in October 2026 on a clean proxy IP: 14 seconds and 0.6 MB per search. Flagged proxy pools are significantly slower. The table below shows expected versus measured results with a low-quality proxy pool:
| | Expected with a high-quality rotating proxy | Measured on a low-quality pool (F-0015) |
|---|---|---|
| Fresh IPs served by Google | ~85% or more (assumed) | 1 in 3 to 1 in 5 |
| Time per search | ~15–20 s (14 s measured on a clean IP) | 40–75 s |
| Proxy data per search | ~0.6–1 MB (0.6 MB measured on a clean IP) | 4.7–6.3 MB |
| Searches per hour (3 browsers) | ~500–600 | ~72 |
| 1,000 searches | ~0.6–1 GB, under 2 hours | ~5–6.5 GB, ~14 hours |
Without a proxy, a warm session on your own IP takes ~1.2 s per search, with every link resolved and zero CAPTCHAs in testing (F-0014), capped at 20 searches an hour to protect your IP. Static proxies have not been benchmarked yet. Measure your own proxy within your data limit using python tools/benchmark.py -n 10.
Settings and configuration
Five settings are available, but most people need only the first two:
- GSEARCH_PROXY — your proxies, in any format above, or a file listing them. Unset: your own IP.
- GSEARCH_DATA_LIMIT_MB — stop all proxy traffic at this many MB, counted across restarts. Unset: no limit.
- GSEARCH_ENV_FILE — absolute path of your .env file. Needed in MCP client configs. If set, the file must exist.
- GSEARCH_FIXTURES_DIR — answer from saved pages instead of Google (demos and tests).
- GSEARCH_STATE_DIR — where budgets, the data meter and saved block pages live. Default: %LOCALAPPDATA%\gsearch or ~/.local/share/gsearch.
Everything else is fixed to what worked best in testing: a new IP per search with rotating proxies, a visible browser, address-bar search, real-device fingerprints, four attempts per search, always resolving URLs, and a 10-minute cache for repeated queries.
Running gsearch
Install the agent tool with uv or pipx:
uv tool install gsearch-agent # or: pipx install gsearch-agent
Then run setup once to download the browser (~1 GB) and print your MCP config:
gsearch setup
Add the server for Claude Desktop, Cursor or another MCP client:
claude mcp add gsearch --scope user -- gsearch-mcp
Or any MCP client. Then ask:
"Search Google for what asyncio is and give me the top three links"
"What do people also ask about asyncio?"
"Find asyncio pages on python.org from the past year."
Legal and responsible use
Automated access to Google Search may breach Google's Terms of Service. The project includes no CAPTCHA solver and never forges or alters Google's tokens. In Google v. SerpApi (N.D. Cal., filed 2025-12-19), Google argues that solving its SearchGuard JavaScript challenge by automated means is circumvention under DMCA §1201 — the complaint also targets automated browsers. Get legal advice for your jurisdiction and use case before running live searches. The parser only reads HTML you already have. Limits are on by default and cannot be bypassed from the CLI or MCP. Do not use proxies to hammer Google. Do not profile people, scrape people-search results or collect personal data at scale. Keep caches short-lived and do not republish raw results. On a block, back off — CAPTCHAs and rate limits come back as errors with retry_after_s. gsearch never tries to defeat the challenge.