Connecting Google ADK agents to Browserless
Agent Development Kit (ADK) is Google's open-source framework for building and deploying AI agents. This guide gives an ADK agent web access through Browserless, first with the hosted Browserless MCP server and then with a custom Playwright tool for full page control.
- A Browserless API token from your account dashboard
- Python 3.11 or higher
- A Gemini API key from Google AI Studio, or a Vertex AI project
- Familiarity with ADK agents
Which approach to use
| Approach | Use it when | What the agent gets |
|---|---|---|
| Browserless MCP server | The agent needs page content, search, crawls, screenshots, or PDFs | Browserless MCP tools through McpToolset, with no browser code to write |
| Playwright function tool | You need specific page interactions, or control over exactly what comes back | A Python function you write, running on a Browserless session via connect_over_cdp |
Start with MCP. Switch to a function tool when the MCP tools don't expose an interaction you need. If you want Gemini to drive the browser from screenshots instead, see Gemini Computer Use.
Connect ADK to the Browserless MCP server
Install ADK
- venv
- uv
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
pip install "google-adk[mcp]"uv init browserless-adk && cd browserless-adk
uv add "google-adk[mcp]"The
mcpextra installs the MCP SDK thatMcpToolsetimports. With uv, prefix theadkcommands below withuv run(for exampleuv run adk web), or activate.venvfirst.Create the agent folder
ADK discovers agents by folder. Create this layout:
browserless_agent/
├── __init__.py
├── agent.py
└── .envinit.pyimports the agent module:from . import agent.envholds your keys:- Gemini API key
- Vertex AI
GOOGLE_GENAI_USE_VERTEXAI=FALSE
GOOGLE_API_KEY=your-gemini-api-key
BROWSERLESS_TOKEN=YOUR_API_TOKEN_HEREGOOGLE_GENAI_USE_VERTEXAI=TRUE
GOOGLE_CLOUD_PROJECT=your-project-id
GOOGLE_CLOUD_LOCATION=us-central1
BROWSERLESS_TOKEN=YOUR_API_TOKEN_HEREVertex AI authenticates with Application Default Credentials. Run
gcloud auth application-default loginonce before starting the agent.The
gemini-flash-latestalias used below may not resolve on regional endpoints likeus-central1. Replace it with a versioned model ID from the Vertex AI Gemini models list.Add
browserless_agent/.envto.gitignorebefore you fill it in, so your tokens never get committed.Define the agent
In
agent.py, point anMcpToolsetat the hosted Browserless MCP server and pass your token as a bearer header:import os
from google.adk.agents import LlmAgent
from google.adk.tools.mcp_tool import McpToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams
TOKEN = os.getenv("BROWSERLESS_TOKEN")
root_agent = LlmAgent(
model="gemini-flash-latest",
name="browserless_agent",
instruction=(
"You answer questions about the web. Use the Browserless tools to search, "
"scrape, and crawl pages, and cite the URLs you used."
),
tools=[
McpToolset(
connection_params=StreamableHTTPConnectionParams(
url="https://mcp.browserless.io/mcp",
headers={"Authorization": f"Bearer {TOKEN}"},
# Scrapes and crawls can outlast the default read timeout.
sse_read_timeout=300,
),
# Optional: limit the agent to the tools it needs.
tool_filter=[
"browserless_smartscraper",
"browserless_search",
"browserless_crawl",
],
)
],
)Run the agent
From the folder that contains
browserless_agent/, start the dev UI:adk webOpen the URL it prints, select
browserless_agent, and ask: "Scrape https://news.ycombinator.com and list the top 3 stories." Or run it in the terminal:adk run browserless_agentResponse:
[browserless_agent]: Here are the top 3 stories on Hacker News:
1. <story title> (https://...)
2. <story title> (https://...)
3. <story title> (https://...)The dev UI's event panel shows each
browserless_smartscrapercall and the content it returned.
Write a Playwright function tool
ADK turns any Python function into a tool, using its signature and docstring as the schema. This tool opens a Browserless session with Playwright, reads the page, and closes the session before returning.
pip install google-adk playwright
You don't need playwright install, since the browser runs on Browserless.
import os
from google.adk.agents import LlmAgent
from playwright.async_api import async_playwright
TOKEN = os.getenv("BROWSERLESS_TOKEN")
BROWSERLESS_URL = f"wss://production-sfo.browserless.io?token={TOKEN}"
async def read_page(url: str) -> dict:
"""Load a web page in a real browser and return its title and visible text.
Args:
url: The full URL to load, including https://.
Returns:
A dict with the page title, final URL, and up to 8,000 characters of text.
"""
async with async_playwright() as p:
browser = await p.chromium.connect_over_cdp(BROWSERLESS_URL)
try:
page = await browser.new_page()
await page.goto(url, wait_until="domcontentloaded")
text = await page.inner_text("body")
# Truncate so one large page doesn't flood the model's context.
return {"title": await page.title(), "url": page.url, "text": text[:8000]}
finally:
# Close in finally so a failed page load doesn't leave the session running.
await browser.close()
root_agent = LlmAgent(
model="gemini-flash-latest",
name="browserless_agent",
instruction="Use read_page to load any URL the user mentions before answering.",
tools=[read_page],
)
Response, from adk run browserless_agent with "What's on https://example.com?":
[browserless_agent]: The page is titled "Example Domain". It says the domain is for use in
documentation examples and links to more information from IANA.
You can give one agent both: put read_page and the McpToolset in the same tools list.
Configure the browser session
For the function tool, set every Browserless session option on the connect_over_cdp URL. Routes such as /stealth go in the path, and options such as proxies and timeouts go in the query string.
Stealth
Use the stealth route for sites with bot detection:
BROWSERLESS_URL = f"wss://production-sfo.browserless.io/stealth?token={TOKEN}"
Residential proxies
Route traffic through residential IPs for geo-targeted pages or sites that rate-limit datacenter IPs:
BROWSERLESS_URL = f"wss://production-sfo.browserless.io?token={TOKEN}&proxy=residential&proxyCountry=us"
Regional and self-hosted endpoints
| Deployment | Endpoint |
|---|---|
| US West (San Francisco) | wss://production-sfo.browserless.io?token={TOKEN} |
| Europe (London) | wss://production-lon.browserless.io?token={TOKEN} |
| Europe (Amsterdam) | wss://production-ams.browserless.io?token={TOKEN} |
| Self-hosted Docker | ws://localhost:3000?token={TOKEN} |
FAQ & Troubleshooting
adk web doesn't list my agent
Run adk web from the parent of browserless_agent/, not from inside it. The folder also needs an __init__.py that imports agent, and agent.py must define a variable named root_agent.
The MCP tools fail with 401 Unauthorized
BROWSERLESS_TOKEN isn't reaching the header. Check that .env sits inside the agent folder (ADK loads it from there) and that the header value reads Bearer <token> with a space.
MCP tool calls time out on large crawls
Raise sse_read_timeout on StreamableHTTPConnectionParams, or ask the agent to crawl fewer pages with a lower limit. browserless_crawl is in beta and only available on Cloud plans.
Can I use this from ADK for TypeScript, Go, or Java?
Yes. The MCP route works in any ADK language that supports remote MCP servers: point its MCP toolset at https://mcp.browserless.io/mcp with the same Authorization: Bearer header. For a function tool, use that language's Playwright or Puppeteer client with connectOverCDP and the same Browserless URL.
The page loads but the content is empty or blocked
Switch to the stealth route and add a residential proxy. If the site still blocks you, use the browserless_smartscraper MCP tool, which cascades through HTTP fetch, proxies, a headless browser, and CAPTCHA solving on its own.