Skip to content

Commit 1f7daf1

Browse files
committed
Initial skeleton
1 parent c18c335 commit 1f7daf1

File tree

1 file changed

+183
-0
lines changed

1 file changed

+183
-0
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
---
2+
pcx_content_type: concept
3+
title: Stagehand
4+
description: Deploy a Stagehand server that uses Browser Rendering to provide browser automation capabilities to your agents.
5+
sidebar:
6+
order: 7
7+
badge: Beta
8+
---
9+
10+
import {
11+
Render,
12+
WranglerConfig,
13+
TabItem,
14+
Tabs,
15+
PackageManagers,
16+
} from "~/components";
17+
18+
[Stagehand](https://www.stagehand.dev/) is ___
19+
20+
You can use Stagehand to ___
21+
22+
23+
## Use Stagehand in a Worker
24+
25+
After you deploy, you can interact with the Worker using this URL pattern:
26+
```
27+
https://<your-worker>.workers.dev
28+
```
29+
In this example, you will search for a movie on https://www.themoviedb.org/ and return the movie's title, year, and director, as well as a screenshot of the webpage.
30+
31+
If you want to skip the steps and get started quickly, select **Deploy to Cloudflare** below.
32+
33+
[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/playwright-mcp/tree/main/cloudflare/example)
34+
35+
1. Install dependencies:
36+
```bash
37+
npm ci
38+
```
39+
2. Make sure you have the [browser rendering](/browser-rendering/) in your wrangler configuration file:
40+
<WranglerConfig>
41+
```jsonc
42+
{
43+
"name": "cloudflare-stagehand-example",
44+
"main": "src/index.ts",
45+
"compatibility_flags": ["nodejs_compat", "enable_nodejs_fs_module"],
46+
"compatibility_date": "2025-09-01",
47+
"workers_dev": true,
48+
"upload_source_maps": true,
49+
"alias": {
50+
"playwright": "@cloudflare/playwright"
51+
},
52+
"observability": {
53+
"enabled": true
54+
},
55+
"browser": {
56+
"binding": "BROWSER",
57+
"experimental_remote": true
58+
},
59+
"ai": {
60+
"binding": "AI"
61+
}
62+
}
63+
```
64+
</WranglerConfig>
65+
66+
3. Edit the code:
67+
68+
```ts title="src/index.ts"
69+
70+
import { Stagehand } from "@browserbasehq/stagehand";
71+
import { z } from "zod";
72+
import { endpointURLString } from "@cloudflare/playwright";
73+
import { createWorkersAI } from "workers-ai-provider";
74+
import { AISdkClient } from "./aidsk";
75+
76+
export default {
77+
async fetch(request: Request, env: Env) {
78+
const url = new URL(request.url);
79+
if (url.pathname !== "/")
80+
return new Response("Not found", { status: 404 });
81+
82+
const workersai = createWorkersAI({ binding: env.AI });
83+
// @ts-ignore
84+
const model = workersai("@cf/meta/llama-3.3-70b-instruct-fp8-fast");
85+
86+
const stagehand = new Stagehand({
87+
env: "LOCAL",
88+
localBrowserLaunchOptions: { cdpUrl: endpointURLString("BROWSER") },
89+
llmClient: new AISdkClient({ model }),
90+
verbose: 1,
91+
});
92+
93+
await stagehand.init();
94+
const page = stagehand.page;
95+
96+
await page.goto('https://www.themoviedb.org/');
97+
// for multi-step actions, use observe
98+
const actions = await page.observe('Search for "The Iron Giant" and click the Search button');
99+
for (const action of actions)
100+
await page.act(action);
101+
await page.act('Click the first search result');
102+
let movieInfo = await page.extract({
103+
instruction: 'Extract movie information',
104+
schema: z.object({
105+
title: z.string(),
106+
year: z.number(),
107+
director: z.string(),
108+
}),
109+
});
110+
111+
const screenshot = await page.screenshot();
112+
await stagehand.close();
113+
114+
return new Response(`
115+
<html>
116+
<head>
117+
<title>Cloudflare Stagehand Example</title>
118+
<style>
119+
body {
120+
font-family: system-ui, -apple-system, sans-serif;
121+
}
122+
</style>
123+
</head>
124+
<body>
125+
<h1>Stagehand Example</h1>
126+
<p>This example shows how to use <a href="https://www.stagehand.dev/">stagehand</a> to extract information from a web page.</p>
127+
<h2>Movie Information</h2>
128+
<div>
129+
<p><b>Title:</b> ${movieInfo.title}</p>
130+
<p><b>Release Year:</b> ${movieInfo.year}</p>
131+
<p><b>Director:</b> ${movieInfo.director}</p>
132+
</div>
133+
<img src="data:image/png;base64,${screenshot.toString('base64')}" />
134+
</body>
135+
</html>
136+
`, {
137+
headers: {
138+
"Content-Type": "text/html; charset=utf-8",
139+
},
140+
});
141+
},
142+
};
143+
```
144+
4. Build the project:
145+
```bash
146+
npm run build
147+
```
148+
5. Deploy to Cloudflare Workers:
149+
```bash
150+
npm run deploy
151+
```
152+
153+
## Use a custom model
154+
155+
Instead of using a model from [Workers AI](/workers-ai/), you can use a custom model for which you supply your own credentials.
156+
157+
In this example, you will configure Stagehand to use [OpenAI](https://openai.com/). You will need an OpenAI API key. Cloudflare recommends storing your API key with [secrets](/workers/configuration/secrets/).
158+
159+
```typescript
160+
const stagehand = new Stagehand({
161+
env: "LOCAL",
162+
localBrowserLaunchOptions: { cdpUrl: endpointURLString("BROWSER") },
163+
modelName: "openai/gpt-4.1",
164+
modelClientOptions: {
165+
apiKey: env.OPENAI_API_KEY,
166+
},
167+
});
168+
```
169+
170+
## Use Cloudflare AI Gateway
171+
172+
173+
```typescript
174+
const stagehand = new Stagehand({
175+
env: "LOCAL",
176+
localBrowserLaunchOptions: { cdpUrl: endpointURLString("BROWSER") },
177+
modelName: "openai/gpt-4.1",
178+
modelClientOptions: {
179+
apiKey: env.OPENAI_API_KEY,
180+
baseURL: `https://gateway.ai.cloudflare.com/v1/${env.CLOUDFLARE_ACCOUNT_ID}/${env.AI_GATEWAY_ID}/openai`,
181+
},
182+
});
183+
```

0 commit comments

Comments
 (0)