can1357/oh-my-pi · error · SearchProviderError

Google blocked the browser search with an automated-traffic

Error message

Google blocked the browser search with an automated-traffic challenge. Try another web search provider or retry later.

What it means

Thrown by callGoogleHtml after the page loads when blockReason() classifies the response as an automated-traffic challenge — status 403/429, a /sorry/ redirect URL, or HTML containing 'unusual traffic' / g-recaptcha markers. Status 429 signals rate limiting/abuse detection by Google against the scraping approach.

Source

Thrown at packages/coding-agent/src/web/search/providers/google.ts:146

			referer: GOOGLE_HOME_URL,
			browser: {
				homeUrl: GOOGLE_HOME_URL,
				ready: { selector: "a h3", timeoutMs: RESULT_RENDER_TIMEOUT_MS },
				shouldFallback: candidate => blockReason(candidate) !== undefined,
			},
		});
	} catch (error) {
		if (error instanceof SearchProviderError || params.signal?.aborted) throw error;
		if (signal.aborted) {
			throw new SearchProviderError("google", "Google browser search timed out.", 504);
		}
		const message = error instanceof Error ? error.message : String(error);
		throw new SearchProviderError("google", `Google browser search failed: ${message}`, 503);
	}

	const blocked = blockReason(page);
	if (blocked === "traffic") {
		throw new SearchProviderError(
			"google",
			"Google blocked the browser search with an automated-traffic challenge. Try another web search provider or retry later.",
			429,
		);
	}
	if (page.status < 200 || page.status >= 300) {
		throw new SearchProviderError("google", `Google HTML error (${page.status})`, page.status);
	}
	if (blocked === "javascript") {
		throw new SearchProviderError(
			"google",
			"Google returned its JavaScript challenge instead of rendered search results.",
			429,
		);
	}
	return page.html;
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Retry later, ideally with backoff; the block is usually time-limited.
  2. Configure a different web search provider (Jina, Gemini, Exa, etc.) which uses APIs rather than scraping.
  3. Change network egress (residential IP, different VPN/exit node) if the IP is flagged.
  4. Reduce search frequency/concurrency to stay under Google's abuse thresholds.

Example fix

// before: tight loop against google scraping
for (const q of queries) await search({ provider: "google", query: q });
// after: fall back to an API-backed provider
const provider = pickProvider(); // e.g. "jina" when google is blocked
for (const q of queries) await search({ provider, query: q });
Defensive patterns

Strategy: fallback

Type guard

function isTrafficBlocked(e: unknown): boolean {
  return e instanceof SearchProviderError && e.provider === 'google' && e.statusCode === 429;
}

Try / catch

try {
  return await search({ provider: 'google', query });
} catch (err) {
  if (isTrafficBlocked(err)) return await search({ provider: 'jina', query }); // API-backed fallback
  throw err;
}

Prevention

When it happens

Trigger: GET of the Google Search results URL returns status 403 or 429, redirects to a google.com/sorry/ page, or its HTML matches /unusual traffic|detected unusual traffic|g-recaptcha/i (including via the browser fallback's shouldFallback probe).

Common situations: High search volume from one IP (shared CI runners, corporate NAT, VPN endpoints); datacenter IPs Google distrusts; no cookies/captcha tokens available for the headless browser.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/caaa3c7bf217d3b7. Report an issue: GitHub.