Quickstart (Python)

Build scripts that navigate the web using natural language instructions

This guide shows you how to use Stagehand with Steel browsers to create scripts that can interact with websites using natural language commands. We'll build a simple automation that extracts data from Hacker News and demonstrates search functionality.

Prerequisites

Ensure you have the following:

Step 1: Set up your environment

First, create a project directory and install the required packages:

Terminal
# Create a project directory
mkdir steel-stagehand-starter
cd steel-stagehand-starter
# Install required packages
pip install steel-sdk stagehand pydantic python-dotenv

Create a .env file with your API keys:

ENV
.env
1
# .env
2
STEEL_API_KEY=your_steel_api_key_here
3
OPENAI_API_KEY=your_openai_api_key_here

Step 2: Create your data models

Python
main.py
1
import asyncio
2
import os
3
from dotenv import load_dotenv
4
from pydantic import BaseModel, Field
5
from steel import Steel
6
from stagehand import StagehandConfig, Stagehand
7
8
# Load environment variables
9
load_dotenv()
10
11
# Get API keys from environment
12
STEEL_API_KEY = os.getenv("STEEL_API_KEY")
13
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
14
15
# Define data models for structured extraction
16
class Story(BaseModel):
17
title: str = Field(..., description="Story title")
18
rank: int = Field(..., description="Story rank number")
19
20
class Stories(BaseModel):
21
stories: list[Story] = Field(..., description="List of top stories")
22

These models will help Stagehand extract structured data from web pages.

Step 3: Create a Steel browser session

Add the session creation logic to connect with Steel's cloud browsers:

Python
main.py
1
async def main():
2
print("🚀 Steel + Stagehand Automation")
3
print("=" * 50)
4
5
# Initialize Steel client
6
client = Steel(steel_api_key=STEEL_API_KEY)
7
8
# Create a new browser session
9
session = client.sessions.create()
10
11
print("✅ Steel browser session created!")
12
print(f"View live session at: {session.session_viewer_url}")
13

When you run this, you'll see a URL where you can watch your browser session live.

Step 4: Configure and connect Stagehand

Now we'll connect Stagehand to your Steel session:

Python
main.py
1
# Configure Stagehand to use Steel session
2
config = StagehandConfig(
3
env="LOCAL",
4
model_name="gpt-4o-mini",
5
model_api_key=OPENAI_API_KEY,
6
local_browser_launch_options={
7
"cdp_url": f"{session.websocket_url}&apiKey={STEEL_API_KEY}",
8
}
9
)
10
11
# Initialize Stagehand
12
stagehand = Stagehand(config)
13
await stagehand.init()
14
15
print("🤖 Stagehand connected to Steel browser")
16

This connects Stagehand to your Steel browser session via Chrome DevTools Protocol.

Step 5: Navigate and extract data

Add the automation logic to navigate to a website and extract information:

Python
main.py
1
try:
2
# Navigate to Hacker News
3
print("📰 Navigating to Hacker News...")
4
await stagehand.page.goto("https://news.ycombinator.com")
5
6
# Extract top stories using AI
7
print("🔍 Extracting top stories...")
8
stories_data = await stagehand.page.extract(
9
"Extract the titles and ranks of the first 5 stories on the page",
10
schema=Stories
11
)
12
13
# Display results
14
print("\n📋 Top 5 Hacker News Stories:")
15
for story in stories_data.stories:
16
print(f"{story.rank}. {story.title}")
17
18
print("\n✅ Automation completed successfully!")
19
20
except Exception as error:
21
print(f"❌ Error during automation: {error}")
22

You'll see the extracted story titles and rankings printed to your console.

Step 6: Add proper cleanup

Always clean up your resources when finished:

Python
main.py
1
finally:
2
# Close Stagehand
3
if stagehand:
4
await stagehand.close()
5
6
# Release Steel session
7
if session and client:
8
client.sessions.release(session.id)
9
print("🧹 Resources cleaned up")
10
11
# Run the automation
12
if __name__ == "__main__":
13
asyncio.run(main())
14

Step 7: Run your automation

Execute your script:

You should see output like this:

Terminal
🚀 Steel + Stagehand Automation
==================================================
Steel browser session created!
View live session at: https://app.steel.dev/v1/sessions/uuid
🤖 Stagehand connected to Steel browser
📰 Navigating to Hacker News...
🔍 Extracting top stories...
📋 Top 5 Hacker News Stories:
1. Ask HN: What are you working on this week?
2. Show HN: I built a tool to analyze my GitHub contributions
3. The future of web development
4. Why I switched from React to Vue
5. Building scalable microservices with Go
Automation completed successfully!
🧹 Resources cleaned up

Complete Example

Here's the complete script that puts all steps together:

Python
main.py
1
"""
2
AI-powered browser automation using Stagehand with Steel browsers.
3
https://github.com/steel-dev/steel-cookbook/tree/main/examples/steel-stagehand-python-starter
4
"""
5
6
import asyncio
7
import os
8
from dotenv import load_dotenv
9
from pydantic import BaseModel, Field
10
from steel import Steel
11
from stagehand import StagehandConfig, Stagehand
12
13
# Load environment variables
14
load_dotenv()
15
16
# Replace with your own API keys
17
STEEL_API_KEY = os.getenv("STEEL_API_KEY") or "your-steel-api-key-here"
18
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") or "your-openai-api-key-here"
19
20
# Define Pydantic models for structured data extraction
21
class Story(BaseModel):
22
title: str = Field(..., description="Story title")
23
rank: int = Field(..., description="Story rank number")
24
25
class Stories(BaseModel):
26
stories: list[Story] = Field(..., description="List of top stories")
27
28
async def main():
29
print("🚀 Steel + Stagehand Python Starter")
30
print("=" * 60)
31
32
if STEEL_API_KEY == "your-steel-api-key-here":
33
print("⚠️ WARNING: Please replace 'your-steel-api-key-here' with your actual Steel API key")
34
print(" Get your API key at: https://app.steel.dev/settings/api-keys")
35
return
36
37
if OPENAI_API_KEY == "your-openai-api-key-here":
38
print("⚠️ WARNING: Please replace 'your-openai-api-key-here' with your actual OpenAI API key")
39
print(" Get your API key at: https://platform.openai.com/")
40
return
41
42
session = None
43
stagehand = None
44
client = None
45
46
try:
47
print("\nCreating Steel session...")
48
49
# Initialize Steel client with the API key from environment variables
50
client = Steel(steel_api_key=STEEL_API_KEY)
51
52
session = client.sessions.create(
53
# === Basic Options ===
54
# use_proxy=True, # Use Steel's proxy network (residential IPs)
55
# proxy_url='http://...', # Use your own proxy (format: protocol://username:password@host:port)
56
# solve_captcha=True, # Enable automatic CAPTCHA solving
57
# session_timeout=1800000, # Session timeout in ms (default: 5 mins)
58
# === Browser Configuration ===
59
# user_agent='custom-ua', # Set a custom User-Agent
60
)
61
62
print(f"\033[1;93mSteel Session created!\033[0m")
63
print(f"View session at \033[1;37m{session.session_viewer_url}\033[0m")
64
65
config = StagehandConfig(
66
env="LOCAL",
67
model_name="gpt-4.1-mini",
68
model_api_key=OPENAI_API_KEY,
69
# Connect to Steel session via CDP
70
local_browser_launch_options={
71
"cdp_url": f"{session.websocket_url}&apiKey={STEEL_API_KEY}",
72
}
73
)
74
75
stagehand = Stagehand(config)
76
77
print("Initializing Stagehand...")
78
await stagehand.init()
79
80
print("Connected to browser via Stagehand")
81
82
print("Navigating to Hacker News...")
83
await stagehand.page.goto("https://news.ycombinator.com")
84
85
print("Extracting top stories using AI...")
86
87
stories_data = await stagehand.page.extract(
88
"Extract the titles and ranks of the first 5 stories on the page",
89
schema=Stories
90
)
91
92
print("\n\033[1;92mTop 5 Hacker News Stories:\033[0m")
93
for story in stories_data.stories:
94
print(f"{story.rank}. {story.title}")
95
96
print("\n\033[1;92mAutomation completed successfully!\033[0m")
97
98
except Exception as error:
99
print(f"Error during automation: {error}")
100
import traceback
101
traceback.print_exc()
102
103
finally:
104
if stagehand:
105
print("Closing Stagehand...")
106
try:
107
await stagehand.close()
108
except Exception as error:
109
print(f"Error closing Stagehand: {error}")
110
111
if session and client:
112
print("Releasing Steel session...")
113
try:
114
client.sessions.release(session.id)
115
print("Steel session released successfully")
116
except Exception as error:
117
print(f"Error releasing session: {error}")
118
119
# Run the main function
120
if __name__ == "__main__":
121
asyncio.run(main())

Next Steps

Now that you have a working Stagehand + Steel automation, try these enhancements:

  • Custom data extraction: Create your own Pydantic models for different websites

  • Complex interactions: Use stagehand.page.act() for clicking, typing, and navigation

  • Multiple pages: Navigate through multi-step workflows

  • Error handling: Add retry logic and better error management

For more advanced features, check out: