> ## Documentation Index
> Fetch the complete documentation index at: https://notte-experiment-visibility-md-links.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Session Lifecycle

> Manage the lifecycle of your Notte browser sessions

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):

<CodeGroup>
  ```python Python - Context Manager theme={null}
  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
  ```

  ```python Python - Manual Management theme={null}
  from notte_sdk import NotteClient

  client = NotteClient()

  # Manual management (not recommended)
  session = client.Session(timeout_minutes=10)
  session.start()

  try:
      print(f"Session {session.session_id} is active")
      page = session.page
      page.goto("https://example.com")
  finally:
      # Always stop the session
      session.stop()
  ```
</CodeGroup>

<Tip>
  Always use the context manager (`with` statement) to ensure sessions are properly stopped, even if errors occur.
</Tip>

## Getting Session Details

Retrieve current information about your session:

<CodeGroup>
  ```python Python theme={null}
  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}")
  ```
</CodeGroup>

<ResponseField name="session_id" type="string">
  Unique identifier for the session
</ResponseField>

<ResponseField name="status" type="string">
  Current status: `active`, `closed`, `error`, or `timed_out`
</ResponseField>

<ResponseField name="created_at" type="datetime">
  Session creation timestamp
</ResponseField>

<ResponseField name="closed_at" type="datetime | None">
  Session closure timestamp (None if still active)
</ResponseField>

<ResponseField name="last_accessed_at" type="datetime">
  Last operation timestamp
</ResponseField>

<ResponseField name="timeout_minutes" type="integer">
  Session timeout in minutes
</ResponseField>

<ResponseField name="duration" type="timedelta">
  Total session duration
</ResponseField>

## Listing Sessions

Query all your active sessions:

<CodeGroup>
  ```python Python theme={null}
  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)}")
  ```
</CodeGroup>

## Stopping a Session

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

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

  client = NotteClient()

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

  # ... do work ...

  session.stop()
  print("Session stopped successfully")
  ```
</CodeGroup>

<Tip>
  Stopping a session is idempotent - you can safely call it multiple times without errors.
</Tip>

## Complete Lifecycle Example

Here's a complete example demonstrating best practices for session management:

<CodeGroup>
  ```python Python theme={null}
  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()
  ```
</CodeGroup>

## Connecting to Existing Sessions

You can reconnect to an existing session using its session\_id:

<CodeGroup>
  ```python Python theme={null}
  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")
  ```
</CodeGroup>

## Error Handling

The context manager automatically handles cleanup, even when errors occur:

<CodeGroup>
  ```python Python - Automatic Cleanup theme={null}
  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")
  ```

  ```python Python - Manual Error Handling theme={null}
  from notte_sdk import NotteClient

  client = NotteClient()

  session = None

  try:
      session = client.Session()
      session.start()

      page = session.page
      page.goto("https://example.com")

      # Your automation code here

  except Exception as error:
      print(f"Automation failed: {error}")
  finally:
      # This always runs, whether success or failure
      if session is not None:
          session.stop()
          print("Session stopped")
  ```
</CodeGroup>

## Best Practices

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

### 1. Always Use Context Managers

The `with` statement guarantees cleanup:

{/* @sniptest testers/sessions/lifecycle/context_manager.py */}

```python context_manager.py theme={null}
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

{/* @sniptest testers/sessions/lifecycle/timeout_example.py */}

```python timeout_example.py theme={null}
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:

{/* @sniptest testers/sessions/lifecycle/monitor_state.py */}

```python monitor_state.py theme={null}
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:

{/* @sniptest testers/sessions/lifecycle/handle_interrupts.py */}

```python handle_interrupts.py theme={null}
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

<CardGroup cols={2}>
  <Card title="Session Configuration" icon="gear" href="/features/sessions/configuration.md">
    Configure sessions with advanced options
  </Card>

  <Card title="Recordings" icon="video" href="/features/sessions/recordings.md">
    Record and replay session activity
  </Card>

  <Card title="Live View" icon="eye" href="/features/sessions/live-view.md">
    Watch sessions in real-time
  </Card>

  <Card title="Cookies" icon="cookie-bite" href="/features/sessions/cookies.md">
    Persist authentication across sessions
  </Card>
</CardGroup>
