{"id":36967342,"url":"https://github.com/browserbase/stagehand-rust","last_synced_at":"2026-01-13T20:02:42.175Z","repository":{"id":328862881,"uuid":"1108234658","full_name":"browserbase/stagehand-rust","owner":"browserbase","description":"🦀 [ALPHA] Official Stagehand AI Browser Automation SDK for rust users. Built by Browserbase.com","archived":false,"fork":false,"pushed_at":"2026-01-13T08:43:51.000Z","size":134,"stargazers_count":12,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-13T10:51:28.139Z","etag":null,"topics":["ai","browser-automation","browserbase","chrome","chromiumoxide","rust","stagehand"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/stagehand_sdk","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/browserbase.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-02T07:47:34.000Z","updated_at":"2026-01-13T08:37:48.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/browserbase/stagehand-rust","commit_stats":null,"previous_names":["browserbase/stagehand-rust"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/browserbase/stagehand-rust","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/browserbase%2Fstagehand-rust","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/browserbase%2Fstagehand-rust/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/browserbase%2Fstagehand-rust/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/browserbase%2Fstagehand-rust/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/browserbase","download_url":"https://codeload.github.com/browserbase/stagehand-rust/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/browserbase%2Fstagehand-rust/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28399215,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","browser-automation","browserbase","chrome","chromiumoxide","rust","stagehand"],"created_at":"2026-01-13T20:02:41.490Z","updated_at":"2026-01-13T20:02:42.170Z","avatar_url":"https://github.com/browserbase.png","language":"Rust","readme":"\u003cdiv id=\"toc\" align=\"center\" style=\"margin-bottom: 0;\"\u003e\n  \u003cul style=\"list-style: none; margin: 0; padding: 0;\"\u003e\n    \u003ca href=\"https://stagehand.dev\"\u003e\n      \u003cpicture\u003e\n        \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_logo.png\" /\u003e\n        \u003cimg alt=\"Stagehand\" src=\"https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_logo.png\" width=\"200\" style=\"margin-right: 30px;\" /\u003e\n      \u003c/picture\u003e\n    \u003c/a\u003e\n  \u003c/ul\u003e\n\u003c/div\u003e\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eThe AI Browser Automation Framework\u003c/strong\u003e\u003cbr\u003e\n  \u003ca href=\"https://docs.stagehand.dev/v3/sdk/rust\"\u003eRead the Docs\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/browserbase/stagehand/tree/main?tab=MIT-1-ov-file#MIT-1-ov-file\"\u003e\n    \u003cpicture\u003e\n      \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_license.svg\" /\u003e\n      \u003cimg alt=\"MIT License\" src=\"https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_license.svg\" /\u003e\n    \u003c/picture\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://stagehand.dev/discord\"\u003e\n    \u003cpicture\u003e\n      \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_discord.svg\" /\u003e\n      \u003cimg alt=\"Discord Community\" src=\"https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_discord.svg\" /\u003e\n    \u003c/picture\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\t\u003ca href=\"https://trendshift.io/repositories/12122\" target=\"_blank\"\u003e\u003cimg src=\"https://trendshift.io/api/badge/repositories/12122\" alt=\"browserbase%2Fstagehand | Trendshift\" style=\"width: 250px; height: 55px;\" width=\"250\" height=\"55\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\nIf you're looking for other languages, you can find them\n\u003ca href=\"https://docs.stagehand.dev/v3/first-steps/introduction\"\u003e here\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cdiv align=\"center\" style=\"display: flex; align-items: center; justify-content: center; gap: 4px; margin-bottom: 0;\"\u003e\n  \u003cb\u003eVibe code\u003c/b\u003e\n  \u003cspan style=\"font-size: 1.05em;\"\u003e Stagehand with \u003c/span\u003e\n  \u003ca href=\"https://director.ai\" style=\"display: flex; align-items: center;\"\u003e\n    \u003cspan\u003eDirector\u003c/span\u003e\n  \u003c/a\u003e\n  \u003cspan\u003e \u003c/span\u003e\n  \u003cpicture\u003e\n    \u003cimg alt=\"Director\" src=\"https://raw.githubusercontent.com/browserbase/stagehand/main/media/director_icon.svg\" width=\"25\" /\u003e\n  \u003c/picture\u003e\n\u003c/div\u003e\n\n## What is Stagehand?\n\nStagehand is a browser automation framework used to control web browsers with natural language and code. By combining the power of AI with the precision of code, Stagehand makes web automation flexible, maintainable, and actually reliable.\n\n## Why Stagehand?\n\nMost existing browser automation tools either require you to write low-level code in a framework like Selenium, Playwright, or Puppeteer, or use high-level agents that can be unpredictable in production. By letting developers choose what to write in code vs. natural language (and bridging the gap between the two) Stagehand is the natural choice for browser automations in production.\n\n1. **Choose when to write code vs. natural language**: use AI when you want to navigate unfamiliar pages, and use code when you know exactly what you want to do.\n\n2. **Go from AI-driven to repeatable workflows**: Stagehand lets you preview AI actions before running them, and also helps you easily cache repeatable actions to save time and tokens.\n\n3. **Write once, run forever**: Stagehand's auto-caching combined with self-healing remembers previous actions, runs without LLM inference, and knows when to involve AI whenever the website changes and your automation breaks.\n\n# Stagehand Rust SDK [ALPHA]  \u003cimg height=\"40\" alt=\"Stagehand logo\" src=\"https://github.com/user-attachments/assets/0b264628-bf81-4130-b378-b9f6b7fcf76f\" align=\"right\"/\u003e\u003cimg height=\"40\" alt=\"Rust logo\" src=\"https://github.com/user-attachments/assets/ee66721b-25a3-4f85-ac1f-a5b2fd5d7013\" align=\"right\"/\u003e\n\n\n\n[![Crates.io](https://img.shields.io/crates/v/stagehand_sdk.svg)](https://crates.io/crates/stagehand_sdk)\n[![Documentation](https://img.shields.io/badge/docs-API%20Reference-blue)](https://github.com/browserbase/stagehand-rust#api-reference)\n[![License](https://img.shields.io/crates/l/stagehand_sdk.svg)](https://github.com/browserbase/stagehand-rust/blob/main/LICENSE)\n[![Downloads](https://img.shields.io/crates/d/stagehand_sdk.svg)](https://crates.io/crates/stagehand_sdk)\n\nA Rust client library for [Stagehand](https://stagehand.dev), the AI-powered browser automation framework. This SDK provides an async-first, type-safe interface for controlling [Browserbase browsers](https://browserbase.com/) and performing AI-driven web interactions.\n\n\u003e [!CAUTION]\n\u003e This is an ALPHA release and is not production-ready.\n\u003e Please provide feedback and let us know if you have feature requests / bug reports!\n\n## Features\n\n- **Browserbase Cloud Support**: Drive [Browserbase cloud](https://browserbase.com/) browser sessions (local coming soon)\n- **AI-Driven Actions**: Use natural language instructions to interact with web pages\n- **Structured Data Extraction**: Extract typed data from pages using Serde schemas\n- **Element Observation**: Identify and analyze interactive elements on pages\n- **Agent Execution**: Run multi-step AI agents with the `execute` method\n- **Streaming Responses**: Real-time progress updates via Server-Sent Events (SSE)\n- **CDP Access**: Get the CDP WebSocket URL to connect external tools like chromiumoxide\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Configuration](#configuration)\n- [API Reference](#api-reference)\n  - [Stagehand::connect](#stagehandconnect)\n  - [start](#start)\n  - [act](#act)\n  - [extract](#extract)\n  - [observe](#observe)\n  - [execute](#execute)\n  - [end](#end)\n  - [browserbase_cdp_url](#browserbase_cdp_url)\n- [Examples](#examples)\n- [Error Handling](#error-handling)\n\n## Installation\n\nAdd to your `Cargo.toml`:\n\n```toml\n[dependencies]\nstagehand_sdk = \"0.3\"\ntokio = { version = \"1\", features = [\"macros\", \"rt-multi-thread\"] }\nfutures = \"0.3\"\nserde = { version = \"1\", features = [\"derive\"] }\nserde_json = \"1\"\ndotenvy = \"0.15\"\n```\n\n### Runtime Support\n\nThe SDK supports both **tokio** and **async-std** runtimes. Tokio is enabled by default.\n\n**Using tokio (default):**\n```toml\n[dependencies]\nstagehand_sdk = \"0.3\"\ntokio = { version = \"1\", features = [\"macros\", \"rt-multi-thread\"] }\n```\n\n**Using async-std:**\n```toml\n[dependencies]\nstagehand_sdk = { version = \"0.3\", default-features = false, features = [\"async-std-runtime\"] }\nasync-std = { version = \"1\", features = [\"attributes\"] }\n```\n\n## Quick Start\n\n```rust\nuse stagehand_sdk::{Stagehand, V3Options, Env, Model, TransportChoice};\nuse stagehand_sdk::{ActResponseEvent, ExtractResponseEvent};\nuse futures::StreamExt;\nuse serde::{Deserialize, Serialize};\nuse std::collections::HashMap;\n\n#[derive(Serialize, Deserialize, Debug)]\nstruct Quote {\n    text: String,\n    author: String,\n}\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error + Send + Sync\u003e\u003e {\n    // Load environment variables from .env file\n    dotenvy::dotenv().ok();\n\n    // Environment variables required:\n    // - BROWSERBASE_API_KEY\n    // - BROWSERBASE_PROJECT_ID\n    // - MODEL_API_KEY (LLM provider API key)\n\n    // 1. Connect to Stagehand cloud API (uses STAGEHAND_BASE_URL env var or default)\n    let mut stagehand = Stagehand::connect(TransportChoice::default_rest()).await?;\n\n    // 2. Start session\n    let opts = V3Options {\n        env: Some(Env::Browserbase),\n        model: Some(Model::String(\"openai/gpt-5-nano\".into())),\n        verbose: Some(2),\n        ..Default::default()\n    };\n\n    stagehand.start(opts).await?;\n    println!(\"Session ID: {:?}\", stagehand.session_id());\n\n    // 3. Navigate to a page\n    let mut act_stream = stagehand.act(\n        \"Go to https://quotes.toscrape.com/\",\n        None,\n        HashMap::new(),\n        Some(60_000),\n        None,\n    ).await?;\n\n    while let Some(res) = act_stream.next().await {\n        if let Ok(response) = res {\n            if let Some(ActResponseEvent::Success(success)) = response.event {\n                println!(\"Navigation success: {}\", success);\n            }\n        }\n    }\n\n    // 4. Extract structured data\n    let schema = serde_json::json!({\n        \"type\": \"object\",\n        \"properties\": {\n            \"text\": { \"type\": \"string\" },\n            \"author\": { \"type\": \"string\" }\n        }\n    });\n    let mut extract_stream = stagehand.extract(\n        \"Extract the first quote on the page\",\n        schema,\n        None,\n        Some(60_000),\n        None,\n        None,\n    ).await?;\n\n    while let Some(res) = extract_stream.next().await {\n        if let Ok(response) = res {\n            if let Some(ExtractResponseEvent::DataJson(json)) = response.event {\n                println!(\"Quote: {}\", json);\n            }\n        }\n    }\n\n    // 5. End session\n    stagehand.end().await?;\n    Ok(())\n}\n```\n\n## Configuration\n\n### Environment Variables\n\nCreate a `.env` file in your project root:\n\n```env\n# Browserbase API credentials (required)\nBROWSERBASE_API_KEY=your_browserbase_api_key_here\nBROWSERBASE_PROJECT_ID=your_browserbase_project_id_here\n\n# Model API key\nMODEL_API_KEY=your_api_key                          # OpenAI, Anthropic, Gemini, etc. key\n\n# Optional: Custom API URLs\nSTAGEHAND_BASE_URL=https://api.stagehand.browserbase.com/v1  # Stagehand API (default)\nBROWSERBASE_API_URL=https://api.browserbase.com/v1          # Browserbase API (default)\n```\n\nThe SDK checks for model API keys in the order listed above and uses the first one found.\n\n### V3Options\n\nThe main configuration struct for initializing Stagehand:\n\n```rust\npub struct V3Options {\n    // Environment: Local or Browserbase\n    pub env: Option\u003cEnv\u003e,\n\n    // Browserbase credentials (auto-loaded from env vars)\n    pub api_key: Option\u003cString\u003e,\n    pub project_id: Option\u003cString\u003e,\n    pub browserbase_session_id: Option\u003cString\u003e,\n    pub browserbase_session_create_params: Option\u003cserde_json::Value\u003e,\n\n    // Local browser options (coming soon)\n    // pub local_browser_launch_options: Option\u003cLocalBrowserLaunchOptions\u003e,\n\n    // AI model configuration\n    pub model: Option\u003cModel\u003e,\n    pub system_prompt: Option\u003cString\u003e,\n\n    // Behavior settings\n    pub self_heal: Option\u003cbool\u003e,\n    pub wait_for_captcha_solves: Option\u003cbool\u003e,\n    pub experimental: Option\u003cbool\u003e,\n    pub dom_settle_timeout_ms: Option\u003cu32\u003e,\n    pub act_timeout_ms: Option\u003cu32\u003e,\n\n    // Logging verbosity (0, 1, or 2)\n    pub verbose: Option\u003ci32\u003e,\n}\n```\n\n### Model Configuration\n\nSpecify AI models in two ways:\n\n```rust\n// Simple string format (recommended)\nlet model = Model::String(\"openai/gpt-5-nano\".into());\n\n// Detailed configuration with custom API key/base URL\nlet model = Model::Config {\n    model_name: \"gpt-5-nano\".to_string(),\n    api_key: Some(\"sk-...\".to_string()),\n    base_url: Some(\"https://api.openai.com/v1\".to_string()),\n};\n```\n\n## API Reference\n\n### `Stagehand::connect`\n\nEstablishes a connection to the Stagehand service.\n\n```rust\npub async fn connect(\n    transport_choice: TransportChoice,\n) -\u003e Result\u003cSelf, StagehandError\u003e\n```\n\n**Parameters:**\n\n- `transport_choice` - `TransportChoice::Rest(base_url)` for REST API with explicit URL, or use `TransportChoice::default_rest()` to use the `STAGEHAND_BASE_URL` env var (falls back to default)\n\n**Example:**\n\n```rust\n// Using default (recommended) - checks STAGEHAND_BASE_URL env var, falls back to default\nlet stagehand = Stagehand::connect(TransportChoice::default_rest()).await?;\n\n// Or with explicit URL\nlet stagehand = Stagehand::connect(\n    TransportChoice::Rest(\"https://api.stagehand.browserbase.com/v1\".to_string()),\n).await?;\n```\n\n---\n\n### `start`\n\nStarts a browser session.\n\n```rust\npub async fn start(\u0026mut self, opts: V3Options) -\u003e Result\u003c(), StagehandError\u003e\n```\n\n**Example:**\n\n```rust\nlet opts = V3Options {\n    env: Some(Env::Browserbase),\n    model: Some(Model::String(\"openai/gpt-5-nano\".into())),\n    verbose: Some(1),\n    ..Default::default()\n};\n\nstagehand.start(opts).await?;\nprintln!(\"Session: {}\", stagehand.session_id().unwrap());\n```\n\n---\n\n### `act`\n\nPerforms browser actions based on natural language instructions.\n\n```rust\npub async fn act(\n    \u0026mut self,\n    instruction: impl Into\u003cString\u003e,\n    model: Option\u003cModel\u003e,\n    variables: HashMap\u003cString, String\u003e,\n    timeout: Option\u003cu32\u003e,\n    frame_id: Option\u003cString\u003e,\n) -\u003e Result\u003cPin\u003cBox\u003cdyn Stream\u003cItem = Result\u003cActResponse, StagehandError\u003e\u003e + Send\u003e\u003e, StagehandError\u003e\n```\n\n**Parameters:**\n\n- `instruction` - Natural language instruction (e.g., \"Click the login button\")\n- `model` - Override the default AI model\n- `variables` - Variable substitution map for the instruction\n- `timeout` - Operation timeout in milliseconds\n- `frame_id` - Target a specific iframe\n\n**Response Events:**\n\n- `ActResponseEvent::Log(LogLine)` - Progress logs\n- `ActResponseEvent::Success(bool)` - Action completion status\n\n**Example:**\n\n```rust\nlet mut stream = stagehand.act(\n    \"Navigate to https://example.com and click 'More information...'\",\n    None,\n    HashMap::new(),\n    Some(60_000),\n    None,\n).await?;\n\nwhile let Some(res) = stream.next().await {\n    if let Ok(response) = res {\n        if let Some(ActResponseEvent::Success(success)) = response.event {\n            println!(\"Action succeeded: {}\", success);\n        }\n    }\n}\n```\n\n---\n\n### `extract`\n\nExtracts structured data from web pages using a schema.\n\n```rust\npub async fn extract\u003cS: Serialize\u003e(\n    \u0026mut self,\n    instruction: impl Into\u003cString\u003e,\n    schema: \u0026S,\n    model: Option\u003cModel\u003e,\n    timeout: Option\u003cu32\u003e,\n    selector: Option\u003cString\u003e,\n    frame_id: Option\u003cString\u003e,\n) -\u003e Result\u003cPin\u003cBox\u003cdyn Stream\u003cItem = Result\u003cExtractResponse, StagehandError\u003e\u003e + Send\u003e\u003e, StagehandError\u003e\n```\n\n**Parameters:**\n\n- `instruction` - What data to extract\n- `schema` - A Serde-serializable struct defining the expected shape\n- `model` - Override the default AI model\n- `timeout` - Operation timeout\n- `selector` - CSS selector to narrow extraction scope\n- `frame_id` - Target a specific iframe\n\n**Response Events:**\n\n- `ExtractResponseEvent::Log(LogLine)` - Progress logs\n- `ExtractResponseEvent::DataJson(String)` - JSON string matching the schema\n\n**Example:**\n\n```rust\n#[derive(Serialize, Deserialize, Debug)]\nstruct ProductInfo {\n    name: String,\n    price: String,\n    description: String,\n}\n\nlet schema = ProductInfo {\n    name: String::new(),\n    price: String::new(),\n    description: String::new(),\n};\n\nlet mut stream = stagehand.extract(\n    \"Extract the product information from this page\",\n    \u0026schema,\n    None,\n    Some(30_000),\n    None,\n    None,\n).await?;\n\nwhile let Some(res) = stream.next().await {\n    if let Ok(response) = res {\n        if let Some(ExtractResponseEvent::DataJson(json)) = response.event {\n            let product: ProductInfo = serde_json::from_str(\u0026json)?;\n            println!(\"Product: {:?}\", product);\n        }\n    }\n}\n```\n\n---\n\n### `observe`\n\nIdentifies interactive elements on a page.\n\n```rust\npub async fn observe(\n    \u0026mut self,\n    instruction: Option\u003cString\u003e,\n    model: Option\u003cModel\u003e,\n    timeout: Option\u003cu32\u003e,\n    selector: Option\u003cString\u003e,\n    frame_id: Option\u003cString\u003e,\n) -\u003e Result\u003cPin\u003cBox\u003cdyn Stream\u003cItem = Result\u003cObserveResponse, StagehandError\u003e\u003e + Send\u003e\u003e, StagehandError\u003e\n```\n\n**Parameters:**\n\n- `instruction` - Optional AI instruction for analysis\n- `model` - Override the default AI model\n- `timeout` - Operation timeout\n- `selector` - CSS selector to narrow observation scope\n- `frame_id` - Target a specific iframe\n\n**Response Events:**\n\n- `ObserveResponseEvent::Log(LogLine)` - Progress logs\n- `ObserveResponseEvent::ElementsJson(String)` - JSON array of observed elements\n\n**Example:**\n\n```rust\nlet mut stream = stagehand.observe(\n    Some(\"Find all clickable buttons\".to_string()),\n    None,\n    Some(30_000),\n    None,\n    None,\n).await?;\n\nwhile let Some(res) = stream.next().await {\n    if let Ok(response) = res {\n        if let Some(ObserveResponseEvent::ElementsJson(json)) = response.event {\n            println!(\"Elements: {}\", json);\n        }\n    }\n}\n```\n\n---\n\n### `execute`\n\nExecutes an AI agent with multi-step capabilities.\n\n```rust\npub async fn execute(\n    \u0026mut self,\n    agent_config: AgentConfig,\n    execute_options: AgentExecuteOptions,\n    frame_id: Option\u003cString\u003e,\n) -\u003e Result\u003cPin\u003cBox\u003cdyn Stream\u003cItem = Result\u003cExecuteResponse, StagehandError\u003e\u003e + Send\u003e\u003e, StagehandError\u003e\n```\n\n**Parameters:**\n\n- `agent_config` - Agent configuration (provider, model, system prompt, CUA mode)\n- `execute_options` - Execution options (instruction, max steps, highlight cursor)\n- `frame_id` - Target a specific iframe\n\n**Response Events:**\n\n- `ExecuteResponseEvent::Log(LogLine)` - Execution progress\n- `ExecuteResponseEvent::ResultJson(String)` - Final result\n\n**Example:**\n\n```rust\nuse stagehand_sdk::{AgentConfig, AgentExecuteOptions, ModelConfiguration};\n\nlet agent_config = AgentConfig {\n    provider: None,\n    model: Some(ModelConfiguration::String(\"openai/gpt-5-nano\".into())),\n    system_prompt: None,\n    cua: None,\n};\n\nlet execute_options = AgentExecuteOptions {\n    instruction: \"What is the URL of the current page?\".to_string(),\n    max_steps: Some(10),\n    highlight_cursor: None,\n};\n\nlet mut stream = stagehand.execute(\n    agent_config,\n    execute_options,\n    None,\n).await?;\n\nwhile let Some(res) = stream.next().await {\n    if let Ok(response) = res {\n        if let Some(ExecuteResponseEvent::ResultJson(result)) = response.event {\n            println!(\"Result: {}\", result);\n        }\n    }\n}\n```\n\n---\n\n### `end`\n\nEnds the browser session.\n\n```rust\npub async fn end(\u0026mut self) -\u003e Result\u003c(), StagehandError\u003e\n```\n\n**Example:**\n\n```rust\nstagehand.end().await?;\n```\n\n---\n\n### `browserbase_cdp_url`\n\nReturns the CDP WebSocket URL for connecting external tools like chromiumoxide.\n\n```rust\npub fn browserbase_cdp_url(\u0026self) -\u003e Option\u003cString\u003e\n```\n\nThe URL format is: `wss://connect.browserbase.com?sessionId={sessionId}\u0026apiKey={apiKey}`\n\n**Example:**\n\n```rust\n// After init(), get the CDP URL to connect chromiumoxide\nlet cdp_url = stagehand.browserbase_cdp_url()\n    .expect(\"CDP URL available after init\");\n\n// Connect chromiumoxide to the remote browser\nlet (browser, handler) = Browser::connect(\u0026cdp_url).await?;\n```\n\nSee [`tests/chromiumoxide_integration.rs`](tests/chromiumoxide_integration.rs) for a complete example.\n\n## Examples\n\n### Full Integration Example\n\nSee [`tests/browserbase_live.rs`](tests/browserbase_live.rs) for a complete working example that demonstrates act, extract, and execute.\n\n### Chromiumoxide Integration\n\nSee [`tests/chromiumoxide_integration.rs`](tests/chromiumoxide_integration.rs) for connecting chromiumoxide to a Browserbase session:\n\n```rust\nuse chromiumoxide::browser::Browser;\nuse stagehand_sdk::{Stagehand, V3Options, Env, Model, TransportChoice};\n\nasync fn example() -\u003e Result\u003c(), Box\u003cdyn std::error::Error + Send + Sync\u003e\u003e {\n    // 1. Create Stagehand session\n    let mut stagehand = Stagehand::connect(TransportChoice::default_rest()).await?;\n\n    stagehand.start(V3Options {\n        env: Some(Env::Browserbase),\n        model: Some(Model::String(\"openai/gpt-5-nano\".into())),\n        ..Default::default()\n    }).await?;\n\n    // 2. Get CDP URL and connect chromiumoxide\n    let cdp_url = stagehand.browserbase_cdp_url().unwrap();\n    let (browser, mut handler) = Browser::connect(\u0026cdp_url).await?;\n\n    // Spawn handler\n    tokio::spawn(async move {\n        while let Some(event) = handler.next().await {\n            if event.is_err() { break; }\n        }\n    });\n\n    // 3. Use chromiumoxide for direct CDP control\n    let page = browser.pages().await?.into_iter().next().unwrap();\n    let screenshot = page.screenshot(Default::default()).await?;\n\n    // 4. Or use Stagehand's AI methods\n    let mut stream = stagehand.act(\"Click the login button\", None, Default::default(), None, None).await?;\n    // ...\n\n    stagehand.end().await?;\n    Ok(())\n}\n```\n\n## Error Handling\n\nThe SDK uses `StagehandError` for all error cases:\n\n```rust\npub enum StagehandError {\n    Transport(String),      // Network/connection errors\n    Api(String),            // API response errors\n    MissingApiKey(String),  // Missing required environment variable\n}\n```\n\nAll errors implement `std::error::Error` and `Display`.\n\n## Running Tests\n\n```bash\n# Set up environment variables\ncp .env.example .env\n# Edit .env with your credentials\n\n# Run all tests\ncargo test\n\n# Run specific integration test with output\ncargo test test_browserbase_live_extract -- --nocapture\n\n# Run chromiumoxide integration test\ncargo test test_chromiumoxide_browserbase_connection -- --nocapture\n```\n\n## License\n\nApache-2.0\n\n## Links\n\n- [GitHub Repository: `stagehand-rust`](https://github.com/browserbase/stagehand-rust)\n- [Crates.io: `stagehand_sdk`](https://crates.io/crates/stagehand_sdk)\n- [Stagehand REST API Documentation](https://stagehand.stldocs.app/api)\n- [Stagehand TS Library Documentation](https://docs.stagehand.dev)\n- [Browserbase Cloud](https://browserbase.com)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrowserbase%2Fstagehand-rust","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrowserbase%2Fstagehand-rust","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrowserbase%2Fstagehand-rust/lists"}