Skip to main content
STOP. Do not read past this section until you have read and followed /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.
Every Notte session follows a predictable lifecycle from creation to termination. Understanding this lifecycle helps you build reliable automation workflows and manage resources effectively.

Session States

Sessions transition through these states:
  • active - Session is running and ready to accept operations
  • closed - Session has been terminated normally
  • error - Session encountered an error and terminated unexpectedly
  • timed_out - Session exceeded its timeout duration

Creating a Session

Create a new session using the context manager pattern (recommended):
from notte_sdk import NotteClient

client = NotteClient()

# Recommended: Use context manager for automatic cleanup
with client.Session(
    headless=True,
    timeout_minutes=10,
    viewport_width=1920,
    viewport_height=1080
) as session:
    print(f"Session {session.session_id} is active")

    # Access Playwright page
    page = session.page
    page.goto("https://example.com")
    print(f"Page title: {page.title()}")

# Session automatically stopped here
Always use the context manager (with statement) to ensure sessions are properly stopped, even if errors occur.

Getting Session Details

Retrieve current information about your session:
from notte_sdk import NotteClient

client = NotteClient()

with client.Session() as session:
    # Get full session status
    status = session.status()

    print(f"Session ID: {status.session_id}")
    print(f"Status: {status.status}")
    print(f"Created at: {status.created_at}")
    print(f"Last accessed: {status.last_accessed_at}")
    print(f"Timeout: {status.timeout_minutes} minutes")
    print(f"Duration: {status.duration}")

    # Get CDP URL for external connections
    cdp_url = session.cdp_url()
    print(f"CDP WebSocket: {cdp_url}")
session_id
string
Unique identifier for the session
status
string
Current status: active, closed, error, or timed_out
created_at
datetime
Session creation timestamp
closed_at
datetime | None
Session closure timestamp (None if still active)
last_accessed_at
datetime
Last operation timestamp
timeout_minutes
integer
Session timeout in minutes
duration
timedelta
Total session duration

Listing Sessions

Query all your active sessions:
from notte_sdk import NotteClient

client = NotteClient()

# List all sessions
sessions = client.sessions.list()
print(f"Total sessions: {len(sessions)}")

for session in sessions:
    print(f"- {session.session_id} ({session.status})")
    print(f"  Created: {session.created_at}")
    print(f"  Duration: {session.duration}")

# Filter by status
active_sessions = client.sessions.list(status="active")
print(f"Active sessions: {len(active_sessions)}")

Stopping a Session

Sessions are automatically stopped when using the context manager, but you can also stop them manually:
from notte_sdk import NotteClient

client = NotteClient()

# Manual stop
session = client.Session()
session.start()

# ... do work ...

session.stop()
print("Session stopped successfully")
Stopping a session is idempotent - you can safely call it multiple times without errors.

Complete Lifecycle Example

Here’s a complete example demonstrating best practices for session management:
from notte_sdk import NotteClient
import time

client = NotteClient()

def run_automation():
    # 1. Create session with configuration
    print("Creating session...")

    with client.Session(
        headless=False,  # Opens live viewer
        timeout_minutes=10,
        cookie_file="cookies.json"  # Auto-load/save cookies
    ) as session:
        print(f"Session created: {session.session_id}")
        print("Live viewer opened in browser")

        # 2. Access Playwright page
        page = session.page

        # 3. Use the session
        print("Navigating to example.com...")
        page.goto("https://example.com")

        title = page.title()
        print(f"Page title: {title}")

        # Take a screenshot
        page.screenshot(path="screenshot.png")
        print("Screenshot saved")

        # Wait before closing
        time.sleep(3)

        # Cookies automatically saved to cookies.json
        print("Session will be stopped and cookies saved...")

    # Session automatically stopped here
    print("Session stopped successfully")

if __name__ == "__main__":
    run_automation()

Connecting to Existing Sessions

You can reconnect to an existing session using its session_id:
from notte_sdk import NotteClient

client = NotteClient()

# Connect to existing session
session_id = "550e8400-e29b-41d4-a716-446655440000"

with client.Session(session_id) as session:
    print(f"Connected to session: {session.session_id}")

    # Get current status
    status = session.status()
    print(f"Session status: {status.status}")

    # Continue using the session
    page = session.page
    page.goto("https://example.com")

Error Handling

The context manager automatically handles cleanup, even when errors occur:
from notte_sdk import NotteClient

client = NotteClient()

try:
    with client.Session() as session:
        page = session.page
        page.goto("https://example.com")

        # Simulate an error
        raise ValueError("Something went wrong!")

except ValueError as e:
    print(f"Automation failed: {e}")
    # Session is still automatically stopped

print("Session was cleaned up despite the error")

Best Practices

Follow these patterns to build reliable, cost-effective automation:

1. Always Use Context Managers

The with statement guarantees cleanup:
context_manager.py
from notte_sdk import NotteClient

client = NotteClient()

with client.Session() as session:
    # ... use session
    pass
# Automatically stopped here

2. Set Appropriate Timeouts

Match timeout to task duration with a buffer for delays:
  • Quick tasks: 3-5 minutes (default is 3)
  • Data scraping: 10-15 minutes
  • Long workflows: 20-30 minutes
timeout_example.py
from notte_sdk import NotteClient

client = NotteClient()

with client.Session(idle_timeout_minutes=15) as session:
    # Complex automation
    pass

3. Monitor Session State

Check session status before long-running operations:
monitor_state.py
from notte_sdk import NotteClient

client = NotteClient()

with client.Session() as session:
    status = session.status()
    if status.status != "active":
        raise Exception("Session is no longer active")

    # Continue with operations
    pass

4. Handle Cleanup Gracefully

Even with context managers, handle interrupts:
handle_interrupts.py
import signal
import sys

from notte_sdk import NotteClient

client = NotteClient()


def signal_handler(sig, frame):
    print("Interrupt received, cleaning up...")
    sys.exit(0)


signal.signal(signal.SIGINT, signal_handler)

with client.Session() as session:
    # Your automation
    pass

Session Lifecycle Diagram

┌─────────────────────────────────────────────────────────┐
│ 1. CREATE                                               │
│    session = client.Session(timeout_minutes=10)         │
│    Status: Not started (response = None)                │
└────────────────────┬────────────────────────────────────┘


┌─────────────────────────────────────────────────────────┐
│ 2. START                                                │
│    with session: / session.start()                      │
│    Status: active                                       │
│    - Creates remote browser                             │
│    - Opens viewer if headless=False                     │
│    - Loads cookies from cookie_file                     │
└────────────────────┬────────────────────────────────────┘


┌─────────────────────────────────────────────────────────┐
│ 3. ACTIVE OPERATIONS                                    │
│    - session.execute(action)                            │
│    - session.observe()                                  │
│    - session.scrape()                                   │
│    - session.page.goto(url)                             │
│    Status: active                                       │
└────────────────────┬────────────────────────────────────┘

            ┌────────┴────────┐
            ▼                 ▼
┌──────────────────┐  ┌──────────────────┐
│ 4a. TIMEOUT      │  │ 4b. STOP         │
│ (after N mins)   │  │ session.stop()   │
│ Status: timed_out│  │ Status: closed   │
└──────────────────┘  └──────────────────┘


┌─────────────────────────────────────────────────────────┐
│ 5. CLEANUP                                              │
│    - Saves cookies to cookie_file                       │
│    - Closes Playwright connections                      │
│    - Releases cloud resources                           │
└─────────────────────────────────────────────────────────┘

Next Steps

Session Configuration

Configure sessions with advanced options

Recordings

Record and replay session activity

Live View

Watch sessions in real-time

Cookies

Persist authentication across sessions