Building Browser-Using AI Agents in Python with Playwright and LangGraph

Learn how to build AI agents that browse real websites using Playwright, browser-use, and LangGraph — no API required.

Building Browser-Using AI Agents in Python with Playwright and LangGraph

In this article, you will learn how to build AI agents that can browse and interact with real websites using Playwright, browser-use, and LangGraph.

Topics we will cover include:

  • Why Playwright is the right foundation for browser automation in 2026, and how it differs from Selenium.
  • How to scrape dynamic, JavaScript-rendered pages and complete multi-step forms reliably.
  • How to wire browser actions into LangGraph and browser-use agents, handle anti-bot detection, manage waiting and session persistence, and deploy the result in Docker.

Building Browser-Using AI Agents in Python

Introduction

Most AI agent tutorials start with an API. They show you how to call OpenWeather, hit the Stripe endpoint, pull data from GitHub. That is a fine starting point until you try to build something real and realize that the task you actually need done does not have an API.

Think about what humans do with browsers every day: filing government forms, reading competitor pricing, extracting research from sites that guard their data behind JavaScript rendering, logging into portals that have never heard of OAuth. There are roughly 1.1 billion websites on the internet. A vanishingly small fraction of them have public APIs. The rest only speak browser.

An agent that is limited to API calls handles maybe 5% of the tasks a human worker does daily. Give that agent a browser, and the coverage approaches everything. That is the gap this article closes.

The global AI agents market stands at $10.91 billion in 2026 and is projected to reach $50.31 billion by 2030, with browser-capable agents at the center of that growth. 27.7% of enterprises are already running agentic browsers in production, up from virtually none two years prior. The tooling has matured fast, and the patterns are settled enough to teach properly.

By the end of this article, you will have a working browser agent that navigates real websites, fills forms, extracts structured data, and connects to an LLM that decides what to do next — all in Python.

Why Playwright, Not Selenium

If you built browser automation five years ago, you built it with Selenium. Selenium is still widely deployed, still works, and is not going anywhere. But for any new project in 2026, Playwright is the default. The reasons are practical, not theoretical.

Selenium communicates with the browser by sending individual HTTP requests to a WebDriver. Every action — click, type, scroll — is a separate request. Playwright uses a persistent WebSocket connection for the entire session. Commands flow through that channel with no per-action round-trip cost. Independent benchmarks consistently show Playwright running 30–50% faster than Selenium at the test-suite level and averaging ~290ms per action versus Selenium’s ~536ms. For a browser agent that might execute hundreds of actions, that gap compounds.

Playwright also bundles its own browser binaries. When you install it, you get pre-configured versions of Chromium, Firefox, and WebKit that are guaranteed to work with your Playwright version. No driver version mismatches, no broken CI pipelines because someone updated Chrome. It has built-in auto-waiting before it clicks an element; it verifies the element is visible, enabled, and not animating. You do not have to write time.sleep(2) and hope for the best.

For AI agents specifically, Playwright fires real mouse and keyboard events that mirror how humans interact with browsers. Sites designed to detect automation look for synthetic DOM clicks. Playwright’s interaction model is harder to distinguish from genuine human input.

There is also the browser-use library, which sits one level higher. Browser-use is a Python library that gives an LLM a working browser. Under the hood, it uses Playwright to drive the browser, but the LLM reads the page state and decides what to click, type, and extract — no CSS selectors required. You give it a task in plain English, and it figures out the rest. We will cover both raw Playwright and browser-use in this article, because they serve different needs: Playwright when you want precise, predictable control; browser-use when you want the agent to handle navigation decisions autonomously.

Setting Up the Environment

You need Python 3.10 or higher, an OpenAI API key, and about five minutes.

Step 1: Create a virtual environment

python -m venv browser_agent_env

# macOS / Linux
source browser_agent_env/bin/activate

# Windows
browser_agent_env\Scripts\activate

Step 2: Install dependencies

pip install playwright \
            browser-use \
            langchain \
            langchain-openai \
            langgraph \
            langchain-community \
            python-dotenv

Step 3: Install the browser binaries

This is the step most people miss. Playwright needs to download Chromium, Firefox, and WebKit separately from the Python package. Run this once after installing:

playwright install chromium

If you want all three browser engines, run playwright install. Chromium alone is sufficient for most agent work and is smaller to download.

Step 4: Store your API key

Create a .env file in your project directory:

OPENAI_API_KEY=your_openai_api_key_here

Add .env to your .gitignore immediately. Do not commit API keys.

Step 5: Verify everything works

Here is a first script that navigates to a URL, reads the heading, and saves a screenshot. Use example.com, a publicly available test domain maintained by IANA that will not block you.

Save as first_run.py and run python first_run.py:

# first_run.py
# Navigate to a URL, take a screenshot, and extract the page title.
# Prerequisites: pip install playwright && playwright install chromium
# How to run: python first_run.py

import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        # Launch Chromium in headless mode (no visible browser window).
        # Set headless=False if you want to watch it run during development.
        browser = await p.chromium.launch(headless=True)

        # A browser context is like a fresh browser profile.
        # It isolates cookies, storage, and cache from other contexts.
        context = await browser.new_context(
            viewport={"width": 1280, "height": 720}
        )

        page = await context.new_page()
        await page.goto("http://example.com/")

        title = await page.title()
        heading = await page.locator("h1").inner_text()

        print(f"Title: {title}")
        print(f"Heading: {heading}")

        await page.screenshot(path="example_screenshot.png")
        print("Screenshot saved to example_screenshot.png")

        await browser.close()

asyncio.run(main())

If the script runs without errors and produces a screenshot, your environment is ready to build on.