> ## Documentation Index
> Fetch the complete documentation index at: https://docs.notte.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# Playwright vs Notte Controls

> Understanding the difference between direct Playwright control and Notte's AI-enabled SDK

<Tip>
  STOP. Do not read past this section until you have read and followed [/quickstart.md](/quickstart.md).

  Goal: produce a reliable SDK automation script. The intended authoring flow is generate then edit, not write browser automation from scratch.

  Do not hand-write SDK code with element IDs, selectors, or form fields from memory. Element IDs, selectors, and field mappings must come from a live `observe()` call, CLI `notte page observe` output, or generated workflow code. Guessed browser targets fail on real pages.

  Use the Notte skill and CLI to inspect the live site, validate actions/selectors, handle auth/session state, and export workflow code with `notte sessions workflow-code` before using SDK docs or SDK code.

  SDK reference pages are for understanding, running, or editing generated workflow code. They are not the starting point for manually authoring the initial browser automation. SDK-first code is guesswork on real-world pages with dynamic selectors, auth state, CAPTCHAs, and anti-bot behavior.
</Tip>

When working with Notte sessions, you have two ways to interact with the browser: using Playwright directly via CDP, or using Notte's AI-enabled SDK methods. Both approaches work with the same session, and you can even mix them in your automation.

## Direct Playwright Control

When you access `session.page`, you get a Playwright-compatible page object that connects directly to the browser via Chrome DevTools Protocol:

{/* @sniptest testers/sessions/playwright-vs-notte/playwright_direct.py */}

```python playwright_direct.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

with client.Session() as session:
    page = session.page
    page.goto("https://example.com")
    page.fill("input[name='email']", "user@example.com")
    page.click("button[type='submit']")
```

This gives you the full Playwright API - everything you can do with Playwright works here. You control the browser directly through WebSocket connections with low latency.

## Notte SDK Methods

Notte provides high-level methods designed for AI agents and structured automation:

{/* @sniptest testers/sessions/playwright-vs-notte/notte_sdk_methods.py */}

```python notte_sdk_methods.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

with client.Session() as session:
    session.execute(type="goto", url="https://example.com")
    actions = session.observe(instructions="Fill the email input")
    session.execute(actions[0])  # Execute the action the AI recommends
    data = session.scrape(instructions="Extract all product names")
```

These methods use Notte's backend to execute actions, with built-in AI capabilities, observability, and error handling.

## Key Differences

| Feature                | Playwright (`session.page`)   | Notte SDK (`execute/observe/scrape`)          |
| ---------------------- | ----------------------------- | --------------------------------------------- |
| **API Surface**        | Full Playwright API           | Streamlined action-based API                  |
| **Dependencies**       | Requires `playwright` package | Just `notte-sdk`                              |
| **Element Selection**  | Manual CSS/XPath selectors    | AI-powered natural language + selectors       |
| **Page Understanding** | Manual interpretation         | AI describes page with `observe()`            |
| **Data Extraction**    | Manual parsing                | Structured LLM-powered `scrape()`             |
| **Observability**      | Manual logging                | Session replay, action recording, live viewer |
| **Error Handling**     | Manual try/except             | Automatic retries and validation              |
| **Network Control**    | ✅ Intercept, modify requests  | ❌ Not available                               |
| **Latency**            | Lower (WebSocket)             | Higher (HTTP API)                             |
| **Action Coverage**    | Everything                    | Everything via extensive action library       |

## Why Use Playwright?

Choose `session.page` when you need:

* **Network control** - Intercept, block, or modify requests and responses
* **Event monitoring** - Listen to console logs, network events, page errors
* **Lowest latency** - Direct WebSocket communication for high-speed operations
* **Standard patterns** - Use familiar Playwright code and examples
* **Fine-grained control** - Access to every Playwright feature

<CodeGroup>
  ```python Python theme={null}
  from notte_sdk import NotteClient
  from playwright.sync_api import sync_playwright

  client = NotteClient()

  with client.Session() as session:
      page = session.page

      # Block images for faster loading
      page.route("**/*.{png,jpg,jpeg}", lambda route: route.abort())

      # Listen to network requests
      page.on("request", lambda req: print(f"→ {req.url}"))
      page.on("response", lambda res: print(f"← {res.url} ({res.status})"))

      page.goto("https://example.com")
  ```
</CodeGroup>

## Why Use Notte SDK?

Choose `session.execute()`, `observe()`, and `scrape()` when you need:

* **AI-powered automation** - Let AI find elements and understand pages
* **Structured data extraction** - Extract data into Pydantic models automatically
* **Built-in observability** - Session replays, trajectory tracking, live viewer
* **Simpler API** - Smaller learning curve, no Playwright knowledge required
* **Production reliability** - Automatic retries, error handling, validation
* **Agent workflows** - Designed for AI agents with semantic action spaces

<CodeGroup>
  ```python Python theme={null}
  from notte_sdk import NotteClient
  from pydantic import BaseModel

  client = NotteClient()

  class Product(BaseModel):
      name: str
      price: float

  with client.Session() as session:
      session.execute(type="goto", url="https://example.com/products")

      # AI understands the page
      obs = session.observe(instructions="Find the search box")
      action = obs.space.first()  # AI picks the right element
      session.execute(action.with_value("laptops"))

      # Structured extraction with LLM
      products = session.scrape(
          response_format=list[Product],
          instructions="Extract all products with names and prices"
      )

      # Every action is recorded
      replay = session.replay()
      replay.download("automation.mp4")
  ```
</CodeGroup>

## Mix Both Approaches

You can combine both methods in the same session:

<CodeGroup>
  ```python Python theme={null}
  from notte_sdk import NotteClient

  client = NotteClient()

  with client.Session() as session:
      # Use Notte for high-level navigation
      session.execute(type="goto", url="https://example.com")

      # Switch to Playwright for network control
      page = session.page
      page.route("**/api/*", lambda route: route.continue_(headers={
          **route.request.headers,
          "Authorization": f"Bearer {token}"
      }))

      # Back to Notte for AI-powered scraping
      data = session.scrape(instructions="Extract all article titles")
  ```
</CodeGroup>

## When to Choose What

### Use Playwright if:

* You need network interception or request modification
* You're integrating existing Playwright scripts
* Performance is critical (milliseconds matter)
* You need to listen to browser events

### Use Notte SDK if:

* Building AI agents that understand web pages
* You want structured data extraction
* You need session replay and debugging features
* You prefer simpler, action-based API
* Building production systems with error handling

### Use Both if:

* You need network control AND AI features
* Complex workflows with different requirements
* You want the flexibility of both approaches

## Next Steps

<CardGroup cols={2}>
  <Card title="Connect with Playwright" icon="p" href="/features/sessions/playwright">
    Learn how to use Playwright with Notte sessions
  </Card>

  <Card title="Session Configuration" icon="gear" href="/features/sessions/configuration">
    Configure sessions with advanced options
  </Card>

  <Card title="Actions Reference" icon="hand-pointer" href="/sdk-reference/misc/gotoaction">
    Explore all available Notte actions
  </Card>

  <Card title="Recordings" icon="video" href="/features/sessions/recordings">
    Debug with session replays
  </Card>
</CardGroup>
