dsh-google-chrome-search
Allows AI agents to perform real Google web searches by driving a local Chrome browser, including human-verification handling for CAPTCHAs, and also provides URL fetching and content extraction.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@dsh-google-chrome-searchSearch for 'MCP server examples' and summarize the top 5 results"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
dsh-google-chrome-search
A DeepSeek Harness (DSH) plugin that lets an AI agent run a real Google web search by driving the local Chrome browser over CDP (Chrome DevTools Protocol), and render any page to extract its content. No search API key needed — it works with the Chrome already installed on the machine.
Google frequently serves a human-verification page (CAPTCHA / "unusual traffic") for automated and datacenter traffic. When that happens, this plugin opens a visible Chrome window pointed at the verification page, waits for the human to solve it, and then extracts the results from the now-trusted session. That is the "ask the human" step — by design, the agent never tries to solve a CAPTCHA itself.

What you get
Piece | Path | Purpose |
Core engine |
| Chrome/CDP Google search + CAPTCHA verification + result extraction + Google AI Overview capture (AI-generated answer + cited references) |
Page engine |
| Render any URL + extract readable content (Mozilla Readability) + |
Login engine |
| Sign in with a Google account (visible window) + session check, kept in the persistent profile |
MCP server |
| Exposes |
CLI |
|
|
Skill |
| Teaches the agent how to use it + the human-verification workflow |
Related MCP server: browser-search-mcp
Quick start (no install — npx)
npx dsh-google-chrome-search "nodejs streams" --max 8That's it — no clone, no API key. The first run downloads the package (a few
seconds, then cached). The browser is auto-detected from your system, or
installed once with npx dsh-google-chrome-search install-browser (see below).
Requirements
Node.js ≥ 18 (tested on Node 22)
A Chrome/Chromium-family browser (Chrome, Chromium, Brave, Edge — any CDP-compatible browser). Auto-detected from common paths and
PATH; override withCHROME_PATHor--chrome. Or install the bundled Chrome for Testing once:npx dsh-google-chrome-search install-browser.For the visible-verification step, a desktop session with a display (so the Chrome window can be shown to the human). Headless/SSH can still detect the CAPTCHA and report it (with a screenshot).
Install
git clone https://github.com/davidcastilloalvarado/dsh-google-chrome-search.git
cd dsh-google-chrome-search
npm installDependencies: puppeteer-core (drives your browser over CDP), @puppeteer/browsers
(used only by install-browser to fetch Chrome for Testing), @modelcontextprotocol/sdk
(for the MCP server), @mozilla/readability (content extraction), and zod (schema
validation).
Optionally link the CLI globally so it is on PATH:
npm link # gives you: dsh-google-search "<query>"Install a bundled browser (optional — self-contained setup)
If the machine has no browser at all, download a dedicated Chrome for Testing build (latest stable, ~170 MB, one time) into the plugin's profile dir:
npx dsh-google-chrome-search install-browser
# or with the repo checked out:
node bin/google-search.mjs install-browserIt lands in ~/.dsh-chrome-google/browser/ (or under your GSEARCH_PROFILE) with a
small marker file (browser-info.json). From then on the plugin uses it
automatically when no other browser is configured — the resolution chain is:
--chrome flag → CHROME_PATH env → bundled Chrome for Testing → system paths (/usr/bin/…) → PATHNotes:
--forcere-downloads; it is a no-op while an install is present.On a bare headless Linux server the system shared libraries may still be missing (
libnss3,libgbm,libasound2, …) — a normal desktop has them.Removing it: delete the
browser/folder andbrowser-info.jsonfrom the profile dir.The visible-verification window needs a display either way (desktop, or Xvfb/VNC).
Use the CLI
# Search:
node bin/google-search.mjs "nodejs streams" --max 8
# or, after npm install / npm link:
npm run search -- "nodejs streams" --json
# Search, then render + extract the top 3 result pages:
node bin/google-search.mjs "nodejs streams" --max 8 --fetch-top 3 --fetch-max-chars 8000
# Fetch one URL directly (render + extract readable content):
node bin/google-search.mjs fetch "https://nodejs.org/api/stream.html" --max-chars 8000
# Sign in with a Google account (visible window) + check the session:
node bin/google-search.mjs login
node bin/google-search.mjs account --jsonExit codes: 0 = success (results / fetched content), 2 = verification required
(CAPTCHA), 3 = no results / fetch blocked or failed, 1 = error, 64 = usage.
Fetch a page (render + extract)
The plugin can also render any URL and extract its readable main content:
Runs the page in the same dedicated Chrome profile (so sites that see a consistent, trusted fingerprint behave better).
Waits for the page to fully load (including late SPA content).
Extracts the article with Mozilla Readability, run inside the live page. If the page has no distinct article, it falls back to the full page text.
Capped output (default 8,000 chars per page) so it stays agent-context friendly.
Detects anti-bot walls and reports
blockedinstead of returning garbage. When a site serves a human-verification challenge (e.g. DataDome's "slide to continue" wall), it opens a visible Chrome window with the page, waits up toverifyTimeoutMsfor the human to pass it, then extracts the real content — the same hand-to-human philosophy as the Google CAPTCHA flow. The trusted session cookie persists in the profile, so later pages of that site usually pass headless. Use--no-verify/autoVerify: falseto just reportblockedinstead.Detects PDF documents. Chrome renders PDFs in its built-in viewer, which is an empty page — the exact shape a bot-wall check would mistake for a challenge. A PDF is therefore detected explicitly (the main-document content-type, or the
.pdfpath plus the empty viewer page) and never treated as a wall. The result offers two ways to read the document:the first pages as images in
<profile>/screenshots/(...-pdf-<ts>-p1.png,-p2.png, …) — read them as images; this is the primary read path (no text extraction, so weird encodings and even scanned pages just work). By default the first 2 pages are captured; change it with--pdf-pages <n>(CLI:fetchand search with--fetch-top) or thepdfPagesMCP parameter (max 16; fewer images are produced when the document is shorter). Page images are rendered from the downloaded file, never from the browser's PDF viewer: via the systempdftoppm(poppler-utils,sudo apt install poppler-utils) when installed, otherwise via the optionalpdf-to-imgnpm package (installed automatically with this plugin; pure pdfjs, no system packages needed), with screenshots of the viewer as a last resort.the full file downloaded to
<profile>/downloads/(using the browser session's cookies, so a verification the human just passed is honored) — the lossless fallback for documents longer than the captured pages or exact text (use a PDF tool on it). When a human passes a challenge and the page turns out to be a PDF, both are captured and the visible window closes immediately instead of waiting out the verification timeout.
dsh-google-search fetch "https://example.com/article" --max-chars 10000
dsh-google-search fetch "https://example.com/article" --html --screenshotTwo ways to combine search and reading:
What | How |
Search, then read the top N pages in one call |
|
Search, then read a specific result |
|
Pages are rendered sequentially (one browser, one page at a time) — expect ~1–3 s per page.
AI Overview (Google's AI-generated answer)
Every search also captures Google's AI Overview — the AI-generated answer
that Google shows at the top of the results — together with the references it
cites. This is available on the search and search_and_fetch tools (MCP) and
on dsh-google-search "<query>" (CLI).
What you get, in addition to the organic results:
The AI answer text — Google's generated response, cleaned of the UI chrome (header, "N sites" label, source-card block) so it reads as the answer alone.
The cited references — the list of sites Google used to build the answer, each with a title and a full URL, deduplicated.
── AI Overview (Google's AI-generated answer) ──────────────────
Quantum entanglement is a physical phenomenon where two or more particles
become deeply interconnected …
References cited by Google:
1. scienceexchange.caltech.edu
https://scienceexchange.caltech.edu/topics/quantum-science-explained/entanglement
2. science.nasa.gov
https://science.nasa.gov/what-is-the-spooky-science-of-quantum-entanglement/
…Notes:
It is intermittent. Google only shows an AI Overview for some queries, and it is A/B tested per request. When there is none, the field is
nulland nothing is printed — the search still returns its organic results normally.Best-effort, never fails the search. The AI Overview markup is unstable (Google changes classes and layout frequently). Extraction is defensive: if it cannot be parsed, the search outcome is unchanged.
Structured access. In
--json/ MCP the outcome carries anaiOverviewobject:{ present: true, text, references: [{ title, url }] }ornull.Disabling: pass
aiOverview: false(MCP) or--no-ai-overview(CLI) to skip the capture entirely.
Sign in with a Google account (optional — more trusted, longer-lasting session)
The plugin works anonymously out of the box. But Google treats signed-in accounts very differently from anonymous automated traffic: a real, logged-in account is trusted far more, so CAPTCHAs become much rarer and the session lasts a long time (until Google expires it or you reset the profile).
# Open a visible Chrome window pointed at Google's account page. The human signs in with
# their own Google account; the session cookies are then stored in the persistent profile.
node bin/google-search.mjs login # or: npx dsh-google-chrome-search login
node bin/google-search.mjs login --wait 600000 # wait up to 10 min for the human
node bin/google-search.mjs account # check (headless) whether the profile is signed inAs MCP tools: mcp__chinchilla-websearch__login and mcp__chinchilla-websearch__account.
Security model:
The agent never sees or handles your credentials — you type them directly into a real Chrome window on your own machine.
Only session cookies end up on disk, and only in the plugin's own isolated profile (
~/.dsh-chrome-google), never in your personal browser.Treat the profile like a cached password: anyone with access to that folder on that machine can use the session while it is valid. Deleting the profile (or signing out from Google) revokes it.
Exit codes for login: 0 = signed in (or already signed in), 3 = timed out / window
closed before sign-in, 1 = error.
Use it as a native DSH tool (MCP)
Register the MCP server with DSH's @deepseek-ai/dsh-mcp-client in your profile config.
Zero-clone variant (recommended) — npx fetches the package on demand, so this snippet
works on any machine with Node:
- insert:
- id: mcp-chinchilla-websearch
name: '@deepseek-ai/dsh-mcp-client'
config:
serverName: chinchilla-websearch
transport: stdio
command: npx
args: [ "-y", "dsh-google-chrome-search", "mcp" ]
toolCallTimeoutMs: 300000No env block needed — the browser is auto-detected (standard Chrome/Chromium
locations on Linux and macOS, plus PATH), and the profile defaults to
~/.dsh-chrome-google (created on first run). Only if auto-detection misses your
browser, add an env: block with the full path — e.g.
CHROME_PATH: /path/to/your/browser (and optionally GSEARCH_PROFILE: /path/to/dir
to move the trusted session).
(Or, with the repo checked out, point at the files directly:
command: /path/to/node, args: [ /path/to/dsh-google-chrome-search/src/server.mjs ].)
After a DSH restart, the agent gets three native tools:
Tool | What it does |
| Google web search → links + snippets |
| Render one URL → extracted readable content (title, byline, text, optional HTML/screenshot); PDF URLs are detected and read as page images (first 2 by default, |
| Search → render the top N pages → per-page extracted content in one call |
| Open a visible window so the human signs in with a Google account → session kept in the profile |
| Check (headless) whether the profile holds a signed-in Google account |
Notes:
Calls are serialized (Chrome allows one process per profile), so concurrent tool calls queue rather than run in parallel.
search_and_fetchis slower than plain search: keeptoolCallTimeoutMsat300000(5 min) as shown above.The human-verification flow applies to both the Google search (CAPTCHA) and to result pages that wall off the browser (anti-bot slider): a visible Chrome window opens for the human, and the session persists in the profile afterwards.
Use it as a DSH skill
skill/SKILL.md teaches the agent how to run the search and how to handle the CAPTCHA
hand-off to the human. To install it, copy it into your DSH skills directory, e.g.:
mkdir -p ~/.dsh/skills/google-chrome-search
cp skill/SKILL.md ~/.dsh/skills/google-chrome-search/Before sharing/using it on another machine, edit the <INSTALL_DIR> placeholder inside
SKILL.md to point at where you cloned this repo (or drop the npm link CLI on PATH
and it just works).
Configuration (env / options)
Option / Env | Default | Meaning |
| auto-detect (bundled Chrome for Testing, then system paths, then | Chrome/Chromium-family executable |
|
| persistent, dedicated Chrome profile (keeps "verified" cookies) |
| 8 | organic results to return (max 20) |
| 150000 | how long to wait for the human to solve a CAPTCHA |
|
| if |
|
| region / language |
| 8000 | max extracted characters per fetched page (fetch / search_and_fetch) |
| 2 | how many pages of a fetched PDF to capture as images (max 16; stops at the end of the document) |
| 3 | how many result pages to render in |
|
| fetch options: also return extracted HTML / a page screenshot |
| 20000 | navigation timeout per fetched page |
| 300000 | how long |
The human-verification flow, step by step
Chrome runs the search headless (a dedicated, isolated profile — never your real browser).
If results are present → return them (
status: ok).If Google serves a CAPTCHA:
Screenshot it.
Open a visible Chrome window (same profile) on the verification page.
Wait up to
verifyTimeoutMsfor the human to solve it, polling the page.If solved → extract + return results (flagged
verifiedViaHuman: true). If timed out → returnstatus: verification_requiredwith the latest screenshot.
The verified session persists in the profile, so the next search usually succeeds headless.
Releasing (npm + GitHub release)
Releases are manual and tokenless — the same methodology as
chinchilla-llm-router. From the GitHub Actions tab, run the release
workflow with an input like v1.0.1:
Before dispatching: bump
versioninpackage.jsonto the release version (CI never rewrites versions) and commit.The workflow validates the version format, checks it isn't already on npm, refuses if the tag exists, runs the test suite, creates the GitHub release (with the
npm packtarball attached), and publishes to npm.npm auth is Trusted Publishing (OIDC): no token is stored. Set it up once on npmjs.com:
Create the
productionenvironment in this repo (Settings → Environments).On npmjs.com, add a trusted publisher for the package pointing at this GitHub repo, scoped to the
productionenvironment.The
publish-npmjob runs in that environment; Node 24's npm 11 exchanges the GitHub OIDC token for a short-lived registry token automatically (npm publish --provenance).
Testing
npm testSpawns the MCP server, checks the search, fetch, and search_and_fetch tools are
listed, and — if a Chrome binary is available on the machine — performs a live search with
autoVerify: false. In environments without a browser (e.g. CI) the live call is skipped
gracefully.
FAQ
How is the browser chosen? First hit wins:
--chromeflagCHROME_PATHenvbundled Chrome for Testing (if you ran
install-browser)well-known system paths (table below)
bare
google-chrome/chromiumonPATH
Several browsers installed? That order decides — pin one with CHROME_PATH or --chrome.
OS | Paths checked |
Linux |
|
macOS |
|
No browser installed? Install the bundled Chrome for Testing once (~170 MB); it is used automatically from then on:
npx dsh-google-chrome-search install-browserOr install a system browser (sudo apt install google-chrome-stable / brew install --cask google-chrome). On a bare headless Linux server, shared libraries may still be missing (libnss3, libgbm, libasound2, …).
Where are the cookies, screenshots, and bundled browser?
Everything lives in the profile dir — ~/.dsh-chrome-google/ by default (override: GSEARCH_PROFILE or --profile):
What | Where |
Google session cookies (trusted session) |
|
CAPTCHA screenshots |
|
Bundled Chrome for Testing |
|
Deleting the folder resets the trusted session — the next search likely hits a CAPTCHA again. Your personal Chrome profile is never touched.
CHROME_PATH is set but doesn't work?
It is used as-is, no existence check — a typo or moved binary fails at launch. Test it yourself:
/path/to/chrome --versionNote it overrides everything below it in the chain, including the bundled browser.
Headless server / SSH?
Search and fetch: fully headless, works fine.
CAPTCHA: detected and reported with a screenshot.
The "open a window for the human" step needs a display (desktop, or Xvfb/VNC); without one you get
verification_required+ the screenshot.
Troubleshooting
Symptom | Fix |
| Run |
Runs as root in a container, sandbox error | The default is |
CAPTCHA on every search | Keep the dedicated profile ( |
No visible window appears (SSH / headless) | A window needs a display: use a desktop machine or Xvfb/VNC — or set |
| Close all Chrome instances using that profile, then retry (the profile is separate from your personal one). Don't run two CLI calls at once — one process per profile. |
| That's the human-verification step working as intended: pass the challenge in the window, then it retries and keeps the session. |
| The site walls off headless browsers and |
| The page is JS-heavy and hadn't finished rendering; retry (it settles up to ~7 s), or bump |
| That's the PDF detection working: read the page images ( |
Revert / clean up
Config: remove the
mcp-chinchilla-websearchentry from your DSH profile config.Skill:
rm -rf ~/.dsh/skills/google-chrome-searchProfile/screenshots (and any bundled browser):
rm -rf ~/.dsh-chrome-google
License
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to perform real-time Google searches with anti-bot protection. Bypasses search engine restrictions using advanced browser automation to extract search results locally without requiring paid API services.7MIT
- AlicenseAqualityAmaintenanceEnables web search via a real browser for any LLM, bypassing anti-bot measures without API keys.5MIT
- AlicenseBqualityBmaintenanceBridges AI agents (Codex, Claude Code) with a real Chrome session via CDP, enabling Google Search and Google AI interactions through the browser.2277MIT
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to search the web and extract content using multiple search providers, with caching, retry logic, and options for JavaScript-heavy page rendering.
Related MCP Connectors
Search Google straight from your AI agent. Web results, images, videos, news, products, scholarly ar
The best web search for your AI Agent
Live web search for AI agents. $0.001/call, x402 on Base, no API key.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/DavidCastilloAlvarado/dsh-google-chrome-search'
If you have feedback or need assistance with the MCP directory API, please join our Discord server