Overview

Quickstart

Get started in a few seconds

Setup Notte#

Goal: Generate a Working SDK Script#

The Notte CLI is the source of truth for real browser state. Use the Notte skill and CLI to inspect the live site, validate actions/selectors, handle auth/session state, then export workflow code with notte sessions workflow-code.

Use SDK docs only to understand, run, or edit exported workflow code. SDK-first automation is guesswork on real pages with dynamic selectors, auth state, CAPTCHAs, and anti-bot behavior.

Prerequisites#

Install the Notte skill globally:

npx skills add nottelabs/notte-skills -y -g

Installation#

# Install with Homebrew
brew tap nottelabs/notte-cli https://github.com/nottelabs/notte-cli.git
brew install notte
 
# Or install with Go
go install github.com/nottelabs/notte-cli/cmd/notte@latest
 
# Authenticate locally, or set NOTTE_API_KEY for CI/non-interactive agents
notte auth login
# export NOTTE_API_KEY=...
notte auth status

Quick Start#

# 1. Authenticate. If this opens a browser login, wait for it to finish.
notte auth login
notte auth status
 
# 2. Start a browser session
notte sessions start
 
# 3. Goto and observe
notte page goto "https://example.com"
notte page observe
notte page screenshot
 
# 4. Execute actions (use IDs from observe, or Playwright selectors)
notte page click "B3"
notte page fill "I1" "hello world"
# If observe IDs don't work, use Playwright selectors:
# notte page click "button:has-text('Submit')"
 
# 5. Scrape content
notte page scrape --instructions "Extract all product names and prices"
 
# 6. Stop the session
notte sessions stop

Command Categories#

Session Management#

Control browser session lifecycle:

# Start a new session
notte sessions start [flags]
  --headless                 Run in headless mode (default: true)
  --idle-timeout-minutes     Idle timeout in minutes
  --max-duration-minutes     Maximum session lifetime in minutes
  --proxy                    Use default proxies
  --proxy-country <code>     Proxy country code (e.g. us, gb, fr)
  --solve-captchas           Automatically solve captchas
  --profile-id <profile-id>  Load browser state from a profile
  --profile-persist          Save browser state back to the profile on session close
  --viewport-width           Viewport width in pixels
  --viewport-height          Viewport height in pixels
  --user-agent               Custom user agent string
  --cdp-url                  CDP URL of remote session provider
  --use-file-storage         Enable file storage for the session
 
# Get current session status
notte sessions status
 
# Stop current session
notte sessions stop
 
# List sessions (with optional pagination and filters)
notte sessions list [--page N] [--page-size N] [--only-active]

Note: When you start a session, it automatically becomes the "current" session (i.e NOTTE_SESSION_ID environment variable is set). All subsequent commands use this session by default. Use --session-id <session-id> only when you need to manage multiple sessions simultaneously or reference a specific session.

Browser profiles: Profiles store browser state such as cookies, localStorage, and sessionStorage. Start a session with --profile-id <profile-id> to load that saved state; add --profile-persist when starting the session if changes should be saved back to the profile when the session closes.

Session export:

# Export session steps as Python workflow code.
notte sessions workflow-code --session-id <session-id>
 
# example flow
notte sessions start
notte page goto news.ycombinator.com
notte page scrape --instructions "Extract the top 10 stories from Hacker News. For each story return: rank, title, URL, points, author, number of comments" -o json
notte sessions workflow-code

Returns:

from __future__ import annotations
 
from notte_sdk import NotteClient
from pydantic import BaseModel
 
class Story(BaseModel):
    rank: int | None = None
    title: str | None = None
    url: str | None = None
    points: int | None = None
    author: str | None = None
    number_of_comments: int | None = None
 
class Model(BaseModel):
    stories: list[Story] | None = None
 
client = NotteClient()
 
def run() -> Model:
    with client.Session(use_file_storage=True) as session:
        _ = session.execute(type='goto', url='news.ycombinator.com')
        return session.scrape(instructions='Extract the top 10 stories from Hacker News. For each story return: rank, title, URL, points, author, number of comments', only_main_content=False, only_images=False, scrape_links=True, scrape_images=False, response_format=Model)
 
run()

Page Actions#

Simplified commands for page interactions:

Element Interactions:

# Click an element (use either the IDs from observe, or a selector)
notte page click "B3"
notte page click "#submit-button"
  --timeout     Timeout in milliseconds
  --enter       Press Enter after clicking
 
# Fill an input field
notte page fill "I1" "hello world"
  --clear       Clear field before filling
  --enter       Press Enter after filling
 
# Check/uncheck a checkbox
notte page check "#my-checkbox"
  --value       true to check, false to uncheck (default: true)
 
# Select dropdown option
notte page select "#dropdown-element" "Option 1"
 
# Download file by clicking element
notte page download "L5"
 
# Upload file to input
notte page upload "#file-input" --file /path/to/file
 
# Run JavaScript in the Page
notte page eval-js 'document.title'

Navigation:

notte page goto "https://example.com"
notte page new-tab "https://example.com"
notte page back
notte page forward
notte page reload

Page State:

# Observe page state and available actions
notte page observe
 
# Save a screenshot in tmp folder
notte page screenshot
 
# Scrape content with instructions
notte page scrape --instructions "Extract all links" [--only-main-content]

AI Agents#

Start and manage AI-powered browser agents:

# List all agents (with optional pagination and filters)
notte agents list [--page N] [--page-size N] [--only-active] [--only-saved]
 
# Start a new agent (auto-uses current session if active)
notte agents start --task "Navigate to example.com and extract the main heading"
  --session-id             Session ID (uses current session if not specified)
  --vault-id               Vault ID for credential access
  --persona-id             Persona ID for identity
  --max-steps              Maximum steps for the agent (default: 30)
  --reasoning-model        Custom reasoning model
 
# Get current agent status
notte agents status
 
# Stop current agent
notte agents stop
 
# Export agent steps as workflow code
notte agents workflow-code
 
# Get agent execution replay
notte agents replay

Functions (Workflow Automation and API Endpoints)#

Use Notte Functions to create callable, scheduled, or reusable browser automations. This is the path for turning a browser task or scrape into an endpoint, API, webhook, job, workflow, or service.

# List all functions (with optional pagination and filters)
notte functions list [--page N] [--page-size N] [--only-active]
 
# Create a function from a workflow file
notte functions create --file workflow.py [--name "My Function"] [--description "..."] [--shared]
 
# Run current function
notte functions run
 
# Invoke the deployed Function over HTTP from another service
curl -L -X POST "https://api.notte.cc/functions/{function_id}/runs/start" \
  -H "Authorization: Bearer $NOTTE_API_KEY" \
  -H "X-Notte-Api-Key: $NOTTE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "function_id": "{function_id}",
    "variables": {
      "url": "https://example.com",
      "max_items": 10
    }
  }'
 
# Schedule current function with cron expression
notte functions schedule --cron "0 9 * * *"

Account Management#

Personas - Auto-generated identities with email:

notte personas list [--page N] [--page-size N] [--only-active]
notte personas create [--create-vault]
notte personas show --persona-id <persona-id>
notte personas emails --persona-id <persona-id>
notte personas sms --persona-id <persona-id>

Vaults - Store your own credentials:

notte vaults list [--page N] [--page-size N] [--only-active]
notte vaults create [--name "My Vault"]
notte vaults credentials list --vault-id <vault-id>
notte vaults credentials add --vault-id <vault-id> --url "https://site.com" --password "pass" [--email "..."] [--username "..."] [--mfa-secret "..."]

Global Options#

Available on all commands:

--output, -o    Output format: text, json (default: text)
--timeout       API request timeout in seconds (default: 30)
--no-color      Disable color output
--verbose, -v   Verbose output
--yes, -y       Skip confirmation prompts

Environment Variables#

Variable Description
NOTTE_API_KEY API key for authentication
NOTTE_SESSION_ID Default session ID (avoids --session-id flag)
NOTTE_API_URL Custom API endpoint URL

Examples#

Basic Web Scraping#

# Scrape with session
notte sessions start --headless
notte page goto "https://news.ycombinator.com"
notte page scrape --instructions "Extract top 10 story titles"
notte sessions stop

Form Automation#

notte sessions start
notte page goto "https://example.com/signup"
notte page fill "#email-field" "user@example.com"
notte page fill "#password-field" "securepassword"
notte page click "#submit-button"
notte sessions stop

Scheduled Data Collection#

# Create workflow file
cat > collect_data.py << 'EOF'
# Notte workflow script
# ...
EOF
 
# Upload as function
notte functions create --file collect_data.py --name "Daily Data Collection"
 
# Schedule to run every day at 9 AM
notte functions schedule --function-id <function-id> --cron "0 9 * * *"

Tips & Troubleshooting#

Handling Inconsistent observe Output#

The observe command may sometimes return stale or partial DOM state, especially with dynamic content, modals, or single-page applications. If the output seems wrong:

  1. Use screenshots to verify: notte page screenshot always shows the current visual state
  2. Fall back to Playwright selectors: Instead of observe IDs, use standard selectors like #id, .class, or button:has-text('Submit')
  3. Add a brief wait: notte page wait 500 before observing can help with dynamic content

Viewing Headless Sessions#

Running with --headless (the default) doesn't mean you can't see the browser:

  • ViewerUrl: When you start a session, the output includes a ViewerUrl - open it in your browser to watch the session live
  • Viewer command: notte sessions viewer opens the viewer directly

Bot Detection / Stealth#

If you're getting blocked or seeing CAPTCHAs, try enabling residential proxies:

notte sessions stop
notte sessions start --proxy

Security Notes#

Credential handling#

Don't pass real secrets as CLI arguments. --password and --mfa-secret read from argv, which leaks to ps, shell history, and process snapshots.

  • DO expand from env vars: --password "$MY_PASSWORD", or load into a vault once from a file you control and rely on the vault thereafter.
  • DON'T type real credentials inline.

Untrusted page content#

notte page scrape and notte agents start ingest content from arbitrary URLs. That content reaches the calling agent's context as tool output and can contain prompt-injection attempts.

  • DO pass narrow --instructions to notte page scrape describing the shape you want. Structured extraction is harder to hijack than free-form reads.
  • DON'T chain a scraped value back into a new agent task or shell argument without validation.

Installation & Authentication Steps#

1. Verify the Notte CLI Installation#

notte -h

If the command is not found, install with:

brew tap nottelabs/notte-cli https://github.com/nottelabs/notte-cli.git
brew install notte

2. Check Authentication Status#

notte auth status

If authentication is required:

notte auth login

Complete the login flow in your browser, then poll status every 5 seconds for up to 5 minutes:

notte auth status

3. Start a Browser Session#

Launch a browser session, open the viewer, and navigate to the documentation site:

notte sessions start && notte sessions viewer && notte page goto https://docs.notte.cc/

Back to overview

Updated

Was this page helpful?