For AI agents: a documentation index is available at /llms.txt
Skip to main content

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.

Prerequisites

Which approach to use​

ApproachUse it whenWhat the agent gets
Browserless MCP serverThe agent needs page content, search, crawls, screenshots, or PDFsBrowserless MCP tools through McpToolset, with no browser code to write
Playwright function toolYou need specific page interactions, or control over exactly what comes backA 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​

  1. Install ADK

    python -m venv .venv
    source .venv/bin/activate # On Windows: .venv\Scripts\activate
    pip install "google-adk[mcp]"

    The mcp extra installs the MCP SDK that McpToolset imports. With uv, prefix the adk commands below with uv run (for example uv run adk web), or activate .venv first.

  2. Create the agent folder

    ADK discovers agents by folder. Create this layout:

    browserless_agent/
    ├── __init__.py
    ├── agent.py
    └── .env

    init.py imports the agent module:

    from . import agent

    .env holds your keys:

    GOOGLE_GENAI_USE_VERTEXAI=FALSE
    GOOGLE_API_KEY=your-gemini-api-key
    BROWSERLESS_TOKEN=YOUR_API_TOKEN_HERE

    Add browserless_agent/.env to .gitignore before you fill it in, so your tokens never get committed.

  3. Define the agent

    In agent.py, point an McpToolset at 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",
    ],
    )
    ],
    )
  4. Run the agent

    From the folder that contains browserless_agent/, start the dev UI:

    adk web

    Open 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_agent

    Response:

    [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_smartscraper call 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​

DeploymentEndpoint
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 Dockerws://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.

Next steps​

Was this page helpful?