Quickstart (Typescript)

Build AI agents that navigate the web using natural language instructions

This guide shows you how to use Stagehand with Steel browsers to create AI agents 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 project

First, create a project directory and initialize your Node.js project:

Terminal
# Create a project directory
mkdir steel-stagehand-starter
cd steel-stagehand-starter
# Initialize npm project
npm init -y
# Install required packages
npm install @browserbasehq/stagehand dotenv steel-sdk typescript zod
# Install dev dependencies
npm install --save-dev @types/node ts-node

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
4

Step 2: Create your data schemas

Typescript
index.ts
1
import { Stagehand } from "@browserbasehq/stagehand";
2
import Steel from "steel-sdk";
3
import { z } from "zod";
4
import dotenv from "dotenv";
5
6
// Load environment variables
7
dotenv.config();
8
9
const STEEL_API_KEY = process.env.STEEL_API_KEY;
10
const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
11
12
// Define data schemas for structured extraction
13
const StorySchema = z.object({
14
title: z.string(),
15
rank: z.number()
16
});
17
18
const StoriesSchema = z.object({
19
stories: z.array(StorySchema)
20
});
21

These schemas will help Stagehand extract structured data from web pages using Zod validation.

Step 3: Create a Steel browser session

Typescript
index.ts
1
async function main() {
2
console.log("๐Ÿš€ Steel + Stagehand Automation");
3
console.log("=".repeat(50));
4
5
// Initialize Steel client
6
const client = new Steel({
7
steelAPIKey: STEEL_API_KEY,
8
});
9
10
// Create a new browser session
11
const session = await client.sessions.create();
12
13
console.log("โœ… Steel browser session created!");
14
console.log(`View live session at: ${session.sessionViewerUrl}`);
15
}
16

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

Step 4: Configure and connect Stagehand

Typescript
index.ts
1
// Configure Stagehand to use Steel session
2
const stagehand = new Stagehand({
3
env: "LOCAL",
4
localBrowserLaunchOptions: {
5
cdpUrl: `${session.websocketUrl}&apiKey=${STEEL_API_KEY}`,
6
},
7
enableCaching: false,
8
modelClientOptions: {
9
apiKey: OPENAI_API_KEY,
10
},
11
});
12
13
// Initialize Stagehand
14
console.log("๐Ÿค– Initializing Stagehand...");
15
await stagehand.init();
16
17
console.log("Connected to Steel browser via Stagehand");
18

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:

Typescript
index.ts
1
try {
2
// Navigate to Hacker News
3
console.log("๐Ÿ“ฐ Navigating to Hacker News...");
4
await stagehand.page.goto("https://news.ycombinator.com");
5
6
// Extract top stories using AI
7
console.log("๐Ÿ” Extracting top stories...");
8
const stories = await stagehand.page.extract({
9
instruction: "extract the titles and ranks of the first 5 stories on the page",
10
schema: StoriesSchema,
11
});
12
13
// Display results
14
console.log("\n๐Ÿ“‹ Top 5 Hacker News Stories:");
15
stories.stories.forEach((story, index) => {
16
console.log(`${story.rank}. ${story.title}`);
17
});
18
19
console.log("\nโœ… Automation completed successfully!");
20
21
} catch (error) {
22
console.error("โŒ Error during automation:", error);
23
}
24

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:

Typescript
index.ts
1
finally {
2
// Close Stagehand
3
if (stagehand) {
4
await stagehand.close();
5
}
6
7
// Release Steel session
8
if (session && client) {
9
await client.sessions.release(session.id);
10
console.log("๐Ÿงน Resources cleaned up");
11
}
12
}
13
14
// Run the automation
15
main().catch((error) => {
16
console.error("Unhandled error:", error);
17
process.exit(1);
18
});
19

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://api.steel.dev/v1/sessions/[session-id]/player
๐Ÿค– Initializing Stagehand...
Connected to Steel browser via Stagehand
๐Ÿ“ฐ 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:

Typescript
index.ts
1
/*
2
* AI-powered browser automation using Stagehand with Steel browsers.
3
*/
4
5
import { Stagehand } from "@browserbasehq/stagehand";
6
import Steel from "steel-sdk";
7
import { z } from "zod";
8
import dotenv from "dotenv";
9
10
// Load environment variables
11
dotenv.config();
12
13
const STEEL_API_KEY = process.env.STEEL_API_KEY;
14
const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
15
16
// Define data schemas for structured extraction
17
const StorySchema = z.object({
18
title: z.string(),
19
rank: z.number()
20
});
21
22
const StoriesSchema = z.object({
23
stories: z.array(StorySchema)
24
});
25
26
async function main() {
27
console.log("๐Ÿš€ Steel + Stagehand Automation");
28
console.log("=".repeat(50));
29
30
let session: any = null;
31
let stagehand: Stagehand | null = null;
32
33
try {
34
// Initialize Steel client and create session
35
const client = new Steel({
36
steelAPIKey: STEEL_API_KEY,
37
});
38
39
session = await client.sessions.create();
40
41
console.log("โœ… Steel browser session created!");
42
console.log(`View live session at: ${session.sessionViewerUrl}`);
43
44
// Configure and initialize Stagehand
45
stagehand = new Stagehand({
46
env: "LOCAL",
47
localBrowserLaunchOptions: {
48
cdpUrl: `${session.websocketUrl}&apiKey=${STEEL_API_KEY}`,
49
},
50
enableCaching: false,
51
modelClientOptions: {
52
apiKey: OPENAI_API_KEY,
53
},
54
});
55
56
console.log("๐Ÿค– Initializing Stagehand...");
57
await stagehand.init();
58
console.log("Connected to Steel browser via Stagehand");
59
60
// Navigate and extract data
61
console.log("๐Ÿ“ฐ Navigating to Hacker News...");
62
await stagehand.page.goto("https://news.ycombinator.com");
63
64
console.log("๐Ÿ” Extracting top stories...");
65
const stories = await stagehand.page.extract({
66
instruction: "extract the titles and ranks of the first 5 stories on the page",
67
schema: StoriesSchema,
68
});
69
70
console.log("\n๐Ÿ“‹ Top 5 Hacker News Stories:");
71
stories.stories.forEach((story, index) => {
72
console.log(`${story.rank}. ${story.title}`);
73
});
74
75
console.log("\nโœ… Automation completed successfully!");
76
77
} catch (error) {
78
console.error("โŒ Error during automation:", error);
79
80
} finally {
81
// Clean up resources
82
if (stagehand) {
83
await stagehand.close();
84
}
85
if (session) {
86
const client = new Steel({ steelAPIKey: STEEL_API_KEY });
87
await client.sessions.release(session.id);
88
}
89
console.log("๐Ÿงน Resources cleaned up");
90
}
91
}
92
93
// Run the automation
94
main().catch((error) => {
95
console.error("Unhandled error:", error);
96
process.exit(1);
97
});
98

Advanced Usage Examples

Custom Data Extraction Schema

Typescript
schema.ts
1
const ProductSchema = z.object({
2
products: z.array(
3
z.object({
4
name: z.string(),
5
price: z.string(),
6
rating: z.number().optional(),
7
inStock: z.boolean(),
8
})
9
),
10
});
11
12
const productData = await stagehand.page.extract({
13
instruction: "extract product information from this e-commerce page",
14
schema: ProductSchema,
15
});
16

Complex Actions with Natural Language

Typescript
index.ts
1
// Fill out a form using natural language
2
await stagehand.page.act(
3
"fill out the contact form with name 'John Doe', email 'john@example.com', and message 'Hello!'"
4
);
5
6
// Navigate through multi-step processes
7
await stagehand.page.act(
8
"click on the 'Sign Up' button and then fill out the registration form"
9
);
10
11
// Handle dynamic content
12
await stagehand.page.act(
13
"wait for the page to load completely, then click on the first product"
14
);
15

Next Steps

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

  • Custom data extraction: Create your own Zod schemas 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: