stagehand 4.4.0a0.dev1676__tar.gz → 4.4.1a0.dev1689__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- stagehand-4.4.1a0.dev1689/PKG-INFO +256 -0
- stagehand-4.4.1a0.dev1689/README.md +224 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/pyproject.toml +1 -1
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_extension/manifest.json +1 -1
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_extension/service-worker.js +7 -4
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_generated/protocol_version.py +1 -1
- stagehand-4.4.0a0.dev1676/PKG-INFO +0 -205
- stagehand-4.4.0a0.dev1676/README.md +0 -173
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/__init__.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_extension/blank.html +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_extension/content-script.js +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_extension/offscreen/service-worker-heartbeat.html +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_extension/offscreen/service-worker-heartbeat.js +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_extension/wake-service-worker.html +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_extension/wake-service-worker.js +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_generated/__init__.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_generated/input_types.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_generated/models.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_sdk_identity.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_validation.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/browser.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/browser_clipboard.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/browser_context.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/browserbase_connection.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/browserbase_rpc.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/browserbase_services.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/browserbase_session.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/browserbase_transport.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/cdp_client.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/client_models.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/client_types.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/extension_assets.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/file_upload.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/locator.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/page.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/py.typed +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/response.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/rpc_client.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/stagehand.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/timeouts.py +0 -0
- {stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/webmcp.py +0 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: stagehand
|
|
3
|
+
Version: 4.4.1a0.dev1689
|
|
4
|
+
Summary: Browserbase's SDK for building browser agents
|
|
5
|
+
Keywords: ai,agent,ai-agent,browser,browser-agent,browser-automation,computer-use,headless,playwright,cdp,llm,automation,web-scraping,testing
|
|
6
|
+
Author: Browserbase
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Classifier: Topic :: Software Development :: Testing
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Classifier: Framework :: AsyncIO
|
|
20
|
+
Requires-Dist: browserbase>=1.15,<2
|
|
21
|
+
Requires-Dist: httpx>=0.23,<1
|
|
22
|
+
Requires-Dist: opentelemetry-api>=1.35,<2
|
|
23
|
+
Requires-Dist: pydantic>=2.12,<3
|
|
24
|
+
Requires-Dist: typing-extensions>=4.12,<5
|
|
25
|
+
Requires-Dist: websockets>=16.1.1
|
|
26
|
+
Requires-Python: >=3.11
|
|
27
|
+
Project-URL: Homepage, https://stagehand.dev
|
|
28
|
+
Project-URL: Documentation, https://docs.stagehand.dev
|
|
29
|
+
Project-URL: Repository, https://github.com/browserbase/stagehand
|
|
30
|
+
Project-URL: Issues, https://github.com/browserbase/stagehand/issues
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
<div id="toc" align="center" style="margin-bottom: 0;">
|
|
34
|
+
<ul style="list-style: none; margin: 0; padding: 0;">
|
|
35
|
+
<a href="https://stagehand.dev">
|
|
36
|
+
<picture>
|
|
37
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_logo.png" />
|
|
38
|
+
<img alt="Stagehand" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_logo.png" width="200" style="margin-right: 30px;" />
|
|
39
|
+
</picture>
|
|
40
|
+
</a>
|
|
41
|
+
</ul>
|
|
42
|
+
</div>
|
|
43
|
+
<p align="center">
|
|
44
|
+
<strong>Stagehand is the SDK for browser agents</strong><br>
|
|
45
|
+
</p>
|
|
46
|
+
|
|
47
|
+
<p align="center">
|
|
48
|
+
<a href="https://trendshift.io/repositories/12122" target="_blank"><img src="https://trendshift.io/api/badge/repositories/12122" alt="browserbase%2Fstagehand | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
|
49
|
+
</p>
|
|
50
|
+
|
|
51
|
+
<p align="center">
|
|
52
|
+
<a href="https://docs.stagehand.dev"><strong>Docs</strong></a> ·
|
|
53
|
+
<a href="https://docs.stagehand.dev/v4/first-steps/quickstart"><strong>Quickstart</strong></a> ·
|
|
54
|
+
<a href="https://github.com/browserbase/stagehand"><strong>⭐ Star this repo</strong></a>
|
|
55
|
+
</p>
|
|
56
|
+
|
|
57
|
+
<p align="center">
|
|
58
|
+
<a href="https://github.com/browserbase/stagehand/tree/main?tab=MIT-1-ov-file#MIT-1-ov-file">
|
|
59
|
+
<picture>
|
|
60
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_license.svg" />
|
|
61
|
+
<img alt="MIT License" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_license.svg" />
|
|
62
|
+
</picture>
|
|
63
|
+
</a>
|
|
64
|
+
<a href="https://discord.gg/stagehand">
|
|
65
|
+
<picture>
|
|
66
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_discord.svg" />
|
|
67
|
+
<img alt="Discord Community" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_discord.svg" />
|
|
68
|
+
</picture>
|
|
69
|
+
</a>
|
|
70
|
+
<a href="https://deepwiki.com/browserbase/stagehand">
|
|
71
|
+
<img alt="Ask DeepWiki" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/deepwiki.svg" width="156" height="32" />
|
|
72
|
+
</a>
|
|
73
|
+
</p>
|
|
74
|
+
|
|
75
|
+
<p align="center">
|
|
76
|
+
<a href="https://stagehand.dev">
|
|
77
|
+
<img src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/stagehand-website-banner.png" alt="Stagehand homepage showing browser automation in TypeScript, Python, and Go and a speed comparison with Playwright" width="100%" />
|
|
78
|
+
</a>
|
|
79
|
+
</p>
|
|
80
|
+
|
|
81
|
+
# Stagehand Python SDK
|
|
82
|
+
|
|
83
|
+
## AI that uses the browser like humans.
|
|
84
|
+
|
|
85
|
+
Sign in once, keep the session, and pull structured data out the other side.
|
|
86
|
+
|
|
87
|
+
Replace `app.example.com` with your application's URL and set `OPENAI_API_KEY`, `APP_EMAIL`, and
|
|
88
|
+
`APP_PASSWORD` before running this example.
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
import asyncio
|
|
92
|
+
import os
|
|
93
|
+
|
|
94
|
+
from pydantic import BaseModel
|
|
95
|
+
from stagehand import Stagehand, local_browser
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class Invoice(BaseModel):
|
|
99
|
+
number: str
|
|
100
|
+
amount: float
|
|
101
|
+
paid: bool
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class Invoices(BaseModel):
|
|
105
|
+
invoices: list[Invoice]
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
async def main() -> None:
|
|
109
|
+
# Cookies persist in ./browser-data, so the next run starts already signed in
|
|
110
|
+
browser = await local_browser.launch(user_data_dir="./browser-data")
|
|
111
|
+
try:
|
|
112
|
+
stagehand = await Stagehand.create(
|
|
113
|
+
browser=browser,
|
|
114
|
+
model="openai/gpt-5.4-mini",
|
|
115
|
+
model_api_key=os.environ["OPENAI_API_KEY"],
|
|
116
|
+
)
|
|
117
|
+
try:
|
|
118
|
+
page = (await browser.context.pages())[0]
|
|
119
|
+
await page.goto("https://app.example.com/login")
|
|
120
|
+
|
|
121
|
+
# observe() returns real selectors, so credentials never reach the model
|
|
122
|
+
email = await stagehand.observe("find the email input")
|
|
123
|
+
password = await stagehand.observe("find the password input")
|
|
124
|
+
await page.locator(email.data[0].selector).fill(os.environ["APP_EMAIL"])
|
|
125
|
+
await page.locator(password.data[0].selector).fill(os.environ["APP_PASSWORD"])
|
|
126
|
+
|
|
127
|
+
# act() self-heals when the site redesigns its form
|
|
128
|
+
await stagehand.act("click the sign in button")
|
|
129
|
+
await stagehand.act("open the billing page")
|
|
130
|
+
|
|
131
|
+
# extract() returns schema-validated data
|
|
132
|
+
result = await stagehand.extract(
|
|
133
|
+
"extract every invoice in the table",
|
|
134
|
+
Invoices,
|
|
135
|
+
)
|
|
136
|
+
print(result.data.invoices)
|
|
137
|
+
finally:
|
|
138
|
+
await stagehand.close()
|
|
139
|
+
finally:
|
|
140
|
+
await browser.close()
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
asyncio.run(main())
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Install
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
pip install stagehand
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Requires Python 3.11 or later. Local runs need [Chrome](https://www.google.com/chrome/) installed.
|
|
153
|
+
Full setup: [Quickstart](https://docs.stagehand.dev/v4/first-steps/quickstart).
|
|
154
|
+
|
|
155
|
+
## Why Stagehand
|
|
156
|
+
|
|
157
|
+
- **Familiar APIs:** The Playwright-style methods you and your agents already know: `goto`, `click`, `locator`, `screenshot`.
|
|
158
|
+
- **Token efficiency:** Hybrid accessibility-tree trimming gives agents exactly the page context they need and nothing more.
|
|
159
|
+
- **Faster in production:** Stagehand runs as an extension next to the browser, cutting round-trip latency on every action.
|
|
160
|
+
- **Self-healing:** `act`, `observe`, and `extract` refresh how an action happens when the site changes underneath it.
|
|
161
|
+
- **Built for agents:** WebMCP, clipboard support, batch commands, deep locators for nested iframes and closed Shadow DOMs, OTel traces.
|
|
162
|
+
- **Three languages:** One complete browser driver across TypeScript, Python, and Go.
|
|
163
|
+
|
|
164
|
+
## Run it on Browserbase
|
|
165
|
+
|
|
166
|
+
Point the same script at [Browserbase](https://www.browserbase.com). The
|
|
167
|
+
[Model Gateway](https://docs.stagehand.dev/v4/configuration/models#model-gateway) handles model
|
|
168
|
+
routing, and [server-side caching](https://docs.stagehand.dev/v4/best-practices/caching) reuses
|
|
169
|
+
results for repeated actions.
|
|
170
|
+
|
|
171
|
+
Import `browserbase` from `stagehand`, then use these browser and client setup calls inside the
|
|
172
|
+
async `main()` above, keeping its `try`/`finally` cleanup:
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
from stagehand import browserbase
|
|
176
|
+
|
|
177
|
+
browser = await browserbase.launch(api_key=os.environ["BROWSERBASE_API_KEY"])
|
|
178
|
+
stagehand = await Stagehand.create(browser=browser, cache=True)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Use `browserbase.connect(api_key=..., session_id=...)` to attach to an existing session.
|
|
182
|
+
`browser.close()` releases the Browserbase session. For a `keep_alive=True` session, use
|
|
183
|
+
`await browser.disconnect()` to close the client and connection while keeping the session for later.
|
|
184
|
+
See [browser configuration](https://docs.stagehand.dev/v4/configuration/browser) for more options.
|
|
185
|
+
|
|
186
|
+
## Search and fetch without a browser
|
|
187
|
+
|
|
188
|
+
[Fetch](https://docs.stagehand.dev/v4/add-ons/fetch) grabs the content of a URL as markdown.
|
|
189
|
+
[Search](https://docs.stagehand.dev/v4/add-ons/search) provides fast, token-efficient web search
|
|
190
|
+
results. Both complement browser sessions without launching a browser.
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
import asyncio
|
|
194
|
+
import os
|
|
195
|
+
|
|
196
|
+
from stagehand import browserbase
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
async def search_and_fetch() -> None:
|
|
200
|
+
results = await browserbase.search(
|
|
201
|
+
api_key=os.environ["BROWSERBASE_API_KEY"],
|
|
202
|
+
query="browser agent frameworks",
|
|
203
|
+
num_results=5,
|
|
204
|
+
)
|
|
205
|
+
fetched = await browserbase.fetch(
|
|
206
|
+
api_key=os.environ["BROWSERBASE_API_KEY"],
|
|
207
|
+
url=results.results[0].url,
|
|
208
|
+
format="markdown",
|
|
209
|
+
)
|
|
210
|
+
print(fetched.content)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
asyncio.run(search_and_fetch())
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Python API notes
|
|
217
|
+
|
|
218
|
+
`Stagehand.act()`, `Stagehand.observe()`, and `Stagehand.extract()` use the active page by
|
|
219
|
+
default. Pass `page=page` to target a specific SDK `Page`.
|
|
220
|
+
|
|
221
|
+
`Page.goto()`, `reload()`, `go_back()`, and `go_forward()` return the main-document `Response`,
|
|
222
|
+
or `None` when navigation does not produce one. Response bodies and complete headers are retrieved
|
|
223
|
+
lazily while the Stagehand session remains open.
|
|
224
|
+
|
|
225
|
+
When contributing examples or tests, keep browser ownership explicit: launch or connect a
|
|
226
|
+
browser handle, pass it to `Stagehand.create()`, close Stagehand first, and close the browser in
|
|
227
|
+
the outermost `finally` block.
|
|
228
|
+
|
|
229
|
+
## Docs and resources
|
|
230
|
+
|
|
231
|
+
- [Python examples](https://github.com/browserbase/stagehand/tree/main/packages/sdk-python/examples): actions, extraction, observation, and custom LLM usage.
|
|
232
|
+
- [Page](https://docs.stagehand.dev/v4/reference/page) and [locator](https://docs.stagehand.dev/v4/reference/locator): Playwright-style browser and element APIs.
|
|
233
|
+
- [Integrations](https://docs.stagehand.dev/v4/integrations/overview): agent frameworks and coding agents.
|
|
234
|
+
- [Main README](https://github.com/browserbase/stagehand/blob/main/README.md): project overview, MCP setup, and community links.
|
|
235
|
+
|
|
236
|
+
## Contributing
|
|
237
|
+
|
|
238
|
+
Clone the [Stagehand repository](https://github.com/browserbase/stagehand) and run these commands
|
|
239
|
+
from its root. All Python projects share the root uv workspace, `uv.lock`, and `.venv`.
|
|
240
|
+
`just install` installs all workspace members, and consumers use this SDK from source.
|
|
241
|
+
See [the contributing guide](https://github.com/browserbase/stagehand/blob/main/CONTRIBUTING.md)
|
|
242
|
+
for workspace membership and package-specific commands.
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
# Install uv
|
|
246
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
247
|
+
|
|
248
|
+
# Install just
|
|
249
|
+
brew install just
|
|
250
|
+
|
|
251
|
+
just install
|
|
252
|
+
just generate
|
|
253
|
+
just check
|
|
254
|
+
just test
|
|
255
|
+
just build
|
|
256
|
+
```
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
<div id="toc" align="center" style="margin-bottom: 0;">
|
|
2
|
+
<ul style="list-style: none; margin: 0; padding: 0;">
|
|
3
|
+
<a href="https://stagehand.dev">
|
|
4
|
+
<picture>
|
|
5
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_logo.png" />
|
|
6
|
+
<img alt="Stagehand" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_logo.png" width="200" style="margin-right: 30px;" />
|
|
7
|
+
</picture>
|
|
8
|
+
</a>
|
|
9
|
+
</ul>
|
|
10
|
+
</div>
|
|
11
|
+
<p align="center">
|
|
12
|
+
<strong>Stagehand is the SDK for browser agents</strong><br>
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
<p align="center">
|
|
16
|
+
<a href="https://trendshift.io/repositories/12122" target="_blank"><img src="https://trendshift.io/api/badge/repositories/12122" alt="browserbase%2Fstagehand | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<a href="https://docs.stagehand.dev"><strong>Docs</strong></a> ·
|
|
21
|
+
<a href="https://docs.stagehand.dev/v4/first-steps/quickstart"><strong>Quickstart</strong></a> ·
|
|
22
|
+
<a href="https://github.com/browserbase/stagehand"><strong>⭐ Star this repo</strong></a>
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
<p align="center">
|
|
26
|
+
<a href="https://github.com/browserbase/stagehand/tree/main?tab=MIT-1-ov-file#MIT-1-ov-file">
|
|
27
|
+
<picture>
|
|
28
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_license.svg" />
|
|
29
|
+
<img alt="MIT License" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_license.svg" />
|
|
30
|
+
</picture>
|
|
31
|
+
</a>
|
|
32
|
+
<a href="https://discord.gg/stagehand">
|
|
33
|
+
<picture>
|
|
34
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_discord.svg" />
|
|
35
|
+
<img alt="Discord Community" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_discord.svg" />
|
|
36
|
+
</picture>
|
|
37
|
+
</a>
|
|
38
|
+
<a href="https://deepwiki.com/browserbase/stagehand">
|
|
39
|
+
<img alt="Ask DeepWiki" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/deepwiki.svg" width="156" height="32" />
|
|
40
|
+
</a>
|
|
41
|
+
</p>
|
|
42
|
+
|
|
43
|
+
<p align="center">
|
|
44
|
+
<a href="https://stagehand.dev">
|
|
45
|
+
<img src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/stagehand-website-banner.png" alt="Stagehand homepage showing browser automation in TypeScript, Python, and Go and a speed comparison with Playwright" width="100%" />
|
|
46
|
+
</a>
|
|
47
|
+
</p>
|
|
48
|
+
|
|
49
|
+
# Stagehand Python SDK
|
|
50
|
+
|
|
51
|
+
## AI that uses the browser like humans.
|
|
52
|
+
|
|
53
|
+
Sign in once, keep the session, and pull structured data out the other side.
|
|
54
|
+
|
|
55
|
+
Replace `app.example.com` with your application's URL and set `OPENAI_API_KEY`, `APP_EMAIL`, and
|
|
56
|
+
`APP_PASSWORD` before running this example.
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
import asyncio
|
|
60
|
+
import os
|
|
61
|
+
|
|
62
|
+
from pydantic import BaseModel
|
|
63
|
+
from stagehand import Stagehand, local_browser
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class Invoice(BaseModel):
|
|
67
|
+
number: str
|
|
68
|
+
amount: float
|
|
69
|
+
paid: bool
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class Invoices(BaseModel):
|
|
73
|
+
invoices: list[Invoice]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
async def main() -> None:
|
|
77
|
+
# Cookies persist in ./browser-data, so the next run starts already signed in
|
|
78
|
+
browser = await local_browser.launch(user_data_dir="./browser-data")
|
|
79
|
+
try:
|
|
80
|
+
stagehand = await Stagehand.create(
|
|
81
|
+
browser=browser,
|
|
82
|
+
model="openai/gpt-5.4-mini",
|
|
83
|
+
model_api_key=os.environ["OPENAI_API_KEY"],
|
|
84
|
+
)
|
|
85
|
+
try:
|
|
86
|
+
page = (await browser.context.pages())[0]
|
|
87
|
+
await page.goto("https://app.example.com/login")
|
|
88
|
+
|
|
89
|
+
# observe() returns real selectors, so credentials never reach the model
|
|
90
|
+
email = await stagehand.observe("find the email input")
|
|
91
|
+
password = await stagehand.observe("find the password input")
|
|
92
|
+
await page.locator(email.data[0].selector).fill(os.environ["APP_EMAIL"])
|
|
93
|
+
await page.locator(password.data[0].selector).fill(os.environ["APP_PASSWORD"])
|
|
94
|
+
|
|
95
|
+
# act() self-heals when the site redesigns its form
|
|
96
|
+
await stagehand.act("click the sign in button")
|
|
97
|
+
await stagehand.act("open the billing page")
|
|
98
|
+
|
|
99
|
+
# extract() returns schema-validated data
|
|
100
|
+
result = await stagehand.extract(
|
|
101
|
+
"extract every invoice in the table",
|
|
102
|
+
Invoices,
|
|
103
|
+
)
|
|
104
|
+
print(result.data.invoices)
|
|
105
|
+
finally:
|
|
106
|
+
await stagehand.close()
|
|
107
|
+
finally:
|
|
108
|
+
await browser.close()
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
asyncio.run(main())
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Install
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
pip install stagehand
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Requires Python 3.11 or later. Local runs need [Chrome](https://www.google.com/chrome/) installed.
|
|
121
|
+
Full setup: [Quickstart](https://docs.stagehand.dev/v4/first-steps/quickstart).
|
|
122
|
+
|
|
123
|
+
## Why Stagehand
|
|
124
|
+
|
|
125
|
+
- **Familiar APIs:** The Playwright-style methods you and your agents already know: `goto`, `click`, `locator`, `screenshot`.
|
|
126
|
+
- **Token efficiency:** Hybrid accessibility-tree trimming gives agents exactly the page context they need and nothing more.
|
|
127
|
+
- **Faster in production:** Stagehand runs as an extension next to the browser, cutting round-trip latency on every action.
|
|
128
|
+
- **Self-healing:** `act`, `observe`, and `extract` refresh how an action happens when the site changes underneath it.
|
|
129
|
+
- **Built for agents:** WebMCP, clipboard support, batch commands, deep locators for nested iframes and closed Shadow DOMs, OTel traces.
|
|
130
|
+
- **Three languages:** One complete browser driver across TypeScript, Python, and Go.
|
|
131
|
+
|
|
132
|
+
## Run it on Browserbase
|
|
133
|
+
|
|
134
|
+
Point the same script at [Browserbase](https://www.browserbase.com). The
|
|
135
|
+
[Model Gateway](https://docs.stagehand.dev/v4/configuration/models#model-gateway) handles model
|
|
136
|
+
routing, and [server-side caching](https://docs.stagehand.dev/v4/best-practices/caching) reuses
|
|
137
|
+
results for repeated actions.
|
|
138
|
+
|
|
139
|
+
Import `browserbase` from `stagehand`, then use these browser and client setup calls inside the
|
|
140
|
+
async `main()` above, keeping its `try`/`finally` cleanup:
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
from stagehand import browserbase
|
|
144
|
+
|
|
145
|
+
browser = await browserbase.launch(api_key=os.environ["BROWSERBASE_API_KEY"])
|
|
146
|
+
stagehand = await Stagehand.create(browser=browser, cache=True)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Use `browserbase.connect(api_key=..., session_id=...)` to attach to an existing session.
|
|
150
|
+
`browser.close()` releases the Browserbase session. For a `keep_alive=True` session, use
|
|
151
|
+
`await browser.disconnect()` to close the client and connection while keeping the session for later.
|
|
152
|
+
See [browser configuration](https://docs.stagehand.dev/v4/configuration/browser) for more options.
|
|
153
|
+
|
|
154
|
+
## Search and fetch without a browser
|
|
155
|
+
|
|
156
|
+
[Fetch](https://docs.stagehand.dev/v4/add-ons/fetch) grabs the content of a URL as markdown.
|
|
157
|
+
[Search](https://docs.stagehand.dev/v4/add-ons/search) provides fast, token-efficient web search
|
|
158
|
+
results. Both complement browser sessions without launching a browser.
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
import asyncio
|
|
162
|
+
import os
|
|
163
|
+
|
|
164
|
+
from stagehand import browserbase
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
async def search_and_fetch() -> None:
|
|
168
|
+
results = await browserbase.search(
|
|
169
|
+
api_key=os.environ["BROWSERBASE_API_KEY"],
|
|
170
|
+
query="browser agent frameworks",
|
|
171
|
+
num_results=5,
|
|
172
|
+
)
|
|
173
|
+
fetched = await browserbase.fetch(
|
|
174
|
+
api_key=os.environ["BROWSERBASE_API_KEY"],
|
|
175
|
+
url=results.results[0].url,
|
|
176
|
+
format="markdown",
|
|
177
|
+
)
|
|
178
|
+
print(fetched.content)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
asyncio.run(search_and_fetch())
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Python API notes
|
|
185
|
+
|
|
186
|
+
`Stagehand.act()`, `Stagehand.observe()`, and `Stagehand.extract()` use the active page by
|
|
187
|
+
default. Pass `page=page` to target a specific SDK `Page`.
|
|
188
|
+
|
|
189
|
+
`Page.goto()`, `reload()`, `go_back()`, and `go_forward()` return the main-document `Response`,
|
|
190
|
+
or `None` when navigation does not produce one. Response bodies and complete headers are retrieved
|
|
191
|
+
lazily while the Stagehand session remains open.
|
|
192
|
+
|
|
193
|
+
When contributing examples or tests, keep browser ownership explicit: launch or connect a
|
|
194
|
+
browser handle, pass it to `Stagehand.create()`, close Stagehand first, and close the browser in
|
|
195
|
+
the outermost `finally` block.
|
|
196
|
+
|
|
197
|
+
## Docs and resources
|
|
198
|
+
|
|
199
|
+
- [Python examples](https://github.com/browserbase/stagehand/tree/main/packages/sdk-python/examples): actions, extraction, observation, and custom LLM usage.
|
|
200
|
+
- [Page](https://docs.stagehand.dev/v4/reference/page) and [locator](https://docs.stagehand.dev/v4/reference/locator): Playwright-style browser and element APIs.
|
|
201
|
+
- [Integrations](https://docs.stagehand.dev/v4/integrations/overview): agent frameworks and coding agents.
|
|
202
|
+
- [Main README](https://github.com/browserbase/stagehand/blob/main/README.md): project overview, MCP setup, and community links.
|
|
203
|
+
|
|
204
|
+
## Contributing
|
|
205
|
+
|
|
206
|
+
Clone the [Stagehand repository](https://github.com/browserbase/stagehand) and run these commands
|
|
207
|
+
from its root. All Python projects share the root uv workspace, `uv.lock`, and `.venv`.
|
|
208
|
+
`just install` installs all workspace members, and consumers use this SDK from source.
|
|
209
|
+
See [the contributing guide](https://github.com/browserbase/stagehand/blob/main/CONTRIBUTING.md)
|
|
210
|
+
for workspace membership and package-specific commands.
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
# Install uv
|
|
214
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
215
|
+
|
|
216
|
+
# Install just
|
|
217
|
+
brew install just
|
|
218
|
+
|
|
219
|
+
just install
|
|
220
|
+
just generate
|
|
221
|
+
just check
|
|
222
|
+
just test
|
|
223
|
+
just build
|
|
224
|
+
```
|
{stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_extension/service-worker.js
RENAMED
|
@@ -9206,7 +9206,7 @@ function isRecord$2(value) {
|
|
|
9206
9206
|
}
|
|
9207
9207
|
var package_default$1 = {
|
|
9208
9208
|
name: "@browserbasehq/stagehand-protocol",
|
|
9209
|
-
version: "3.1.1
|
|
9209
|
+
version: "3.1.1",
|
|
9210
9210
|
"private": true,
|
|
9211
9211
|
type: "module",
|
|
9212
9212
|
exports: {
|
|
@@ -66119,7 +66119,7 @@ var WebTracerProvider = class extends BasicTracerProvider {
|
|
|
66119
66119
|
};
|
|
66120
66120
|
var package_default = {
|
|
66121
66121
|
name: "@browserbasehq/stagehand-extension",
|
|
66122
|
-
version: "1.3.
|
|
66122
|
+
version: "1.3.1-alpha-2fe947c01c828279a5df0234f0100f9750bc3b9e",
|
|
66123
66123
|
"private": true,
|
|
66124
66124
|
type: "module",
|
|
66125
66125
|
scripts: {
|
|
@@ -67067,9 +67067,12 @@ function createDeferred$1() {
|
|
|
67067
67067
|
function normaliseHeaderName(name) {
|
|
67068
67068
|
return name.toLowerCase();
|
|
67069
67069
|
}
|
|
67070
|
-
/**
|
|
67070
|
+
/**
|
|
67071
|
+
* Split multi-value header strings into discrete values while trimming. An
|
|
67072
|
+
* empty value is kept: the header was still sent, so it must stay visible.
|
|
67073
|
+
*/
|
|
67071
67074
|
function splitHeaderValues(value) {
|
|
67072
|
-
return value.split(/\r?\n/).map((part) => part.trim())
|
|
67075
|
+
return value.split(/\r?\n/).map((part) => part.trim());
|
|
67073
67076
|
}
|
|
67074
67077
|
/**
|
|
67075
67078
|
* Parse an HTTP header text block (as emitted by CDP) into an ordered array of
|
{stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_generated/protocol_version.py
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
"""Generated from packages/protocol/package.json. Do not edit."""
|
|
2
2
|
|
|
3
3
|
PROTOCOL_SEMVER_PATTERN = '^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\\+([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?$'
|
|
4
|
-
STAGEHAND_PROTOCOL_VERSION = '3.1.1
|
|
4
|
+
STAGEHAND_PROTOCOL_VERSION = '3.1.1'
|
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: stagehand
|
|
3
|
-
Version: 4.4.0a0.dev1676
|
|
4
|
-
Summary: Browserbase's SDK for building browser agents
|
|
5
|
-
Keywords: ai,agent,ai-agent,browser,browser-agent,browser-automation,computer-use,headless,playwright,cdp,llm,automation,web-scraping,testing
|
|
6
|
-
Author: Browserbase
|
|
7
|
-
License-Expression: MIT
|
|
8
|
-
Classifier: Development Status :: 5 - Production/Stable
|
|
9
|
-
Classifier: Intended Audience :: Developers
|
|
10
|
-
Classifier: Operating System :: OS Independent
|
|
11
|
-
Classifier: Programming Language :: Python :: 3
|
|
12
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
-
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
|
|
15
|
-
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
16
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
-
Classifier: Topic :: Software Development :: Testing
|
|
18
|
-
Classifier: Typing :: Typed
|
|
19
|
-
Classifier: Framework :: AsyncIO
|
|
20
|
-
Requires-Dist: browserbase>=1.15,<2
|
|
21
|
-
Requires-Dist: httpx>=0.23,<1
|
|
22
|
-
Requires-Dist: opentelemetry-api>=1.35,<2
|
|
23
|
-
Requires-Dist: pydantic>=2.12,<3
|
|
24
|
-
Requires-Dist: typing-extensions>=4.12,<5
|
|
25
|
-
Requires-Dist: websockets>=16.1.1
|
|
26
|
-
Requires-Python: >=3.11
|
|
27
|
-
Project-URL: Homepage, https://stagehand.dev
|
|
28
|
-
Project-URL: Documentation, https://docs.stagehand.dev
|
|
29
|
-
Project-URL: Repository, https://github.com/browserbase/stagehand
|
|
30
|
-
Project-URL: Issues, https://github.com/browserbase/stagehand/issues
|
|
31
|
-
Description-Content-Type: text/markdown
|
|
32
|
-
|
|
33
|
-
<div id="toc" align="center" style="margin-bottom: 0;">
|
|
34
|
-
<ul style="list-style: none; margin: 0; padding: 0;">
|
|
35
|
-
<a href="https://stagehand.dev">
|
|
36
|
-
<picture>
|
|
37
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_logo.png" />
|
|
38
|
-
<img alt="Stagehand" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_logo.png" width="200" style="margin-right: 30px;" />
|
|
39
|
-
</picture>
|
|
40
|
-
</a>
|
|
41
|
-
</ul>
|
|
42
|
-
</div>
|
|
43
|
-
<p align="center">
|
|
44
|
-
<strong>Stagehand is the SDK for browser agents.</strong><br>
|
|
45
|
-
<a href="https://docs.stagehand.dev">Read the Docs</a>
|
|
46
|
-
</p>
|
|
47
|
-
|
|
48
|
-
<p align="center">
|
|
49
|
-
<a href="https://github.com/browserbase/stagehand/tree/main?tab=MIT-1-ov-file#MIT-1-ov-file">
|
|
50
|
-
<picture>
|
|
51
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_license.svg" />
|
|
52
|
-
<img alt="MIT License" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_license.svg" />
|
|
53
|
-
</picture>
|
|
54
|
-
</a>
|
|
55
|
-
<a href="https://discord.gg/stagehand">
|
|
56
|
-
<picture>
|
|
57
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_discord.svg" />
|
|
58
|
-
<img alt="Discord Community" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_discord.svg" />
|
|
59
|
-
</picture>
|
|
60
|
-
</a>
|
|
61
|
-
</p>
|
|
62
|
-
|
|
63
|
-
<p align="center">
|
|
64
|
-
<a href="https://trendshift.io/repositories/12122" target="_blank"><img src="https://trendshift.io/api/badge/repositories/12122" alt="browserbase%2Fstagehand | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
|
65
|
-
</p>
|
|
66
|
-
|
|
67
|
-
<p align="center">
|
|
68
|
-
<a href="https://deepwiki.com/browserbase/stagehand">
|
|
69
|
-
<img alt="Ask DeepWiki" src="https://deepwiki.com/badge.svg" />
|
|
70
|
-
</a>
|
|
71
|
-
</p>
|
|
72
|
-
|
|
73
|
-
# Stagehand Python SDK
|
|
74
|
-
|
|
75
|
-
## What is Stagehand?
|
|
76
|
-
|
|
77
|
-
Stagehand is the SDK for browser agents. Playwright was built for testing, Stagehand is built for agents. Use familiar APIs, self-healing actions, and network-level security across TypeScript, Python, and Go.
|
|
78
|
-
|
|
79
|
-
## Why Stagehand?
|
|
80
|
-
|
|
81
|
-
Stagehand gives browser agents an interface built for how they actually work. It combines familiar Playwright-style APIs with self-healing actions, agent-optimized page context, and native support for complex DOM structures like out-of-process iframes and closed Shadow DOMs.
|
|
82
|
-
|
|
83
|
-
Agents use fewer tokens, recover when websites change, and complete tasks more reliably. With a complete browser driver across TypeScript, Python, and Go, Stagehand delivers the flexibility of AI without sacrificing the speed, control, determinism, reliability, and observability required in production.
|
|
84
|
-
|
|
85
|
-
For the full overview, examples, and contributing guide, see the [main README](https://github.com/browserbase/stagehand/blob/main/README.md).
|
|
86
|
-
|
|
87
|
-
## Example
|
|
88
|
-
|
|
89
|
-
The async Python SDK for Stagehand browser automation:
|
|
90
|
-
|
|
91
|
-
```python
|
|
92
|
-
import asyncio
|
|
93
|
-
import os
|
|
94
|
-
|
|
95
|
-
from pydantic import BaseModel
|
|
96
|
-
|
|
97
|
-
from stagehand import Stagehand, browserbase, local_browser
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
class PullRequest(BaseModel):
|
|
101
|
-
author: str
|
|
102
|
-
title: str
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
async def main() -> None:
|
|
106
|
-
browser = await local_browser.launch(headless=True)
|
|
107
|
-
try:
|
|
108
|
-
stagehand = await Stagehand.create(
|
|
109
|
-
browser=browser,
|
|
110
|
-
model="openai/gpt-5.4-mini",
|
|
111
|
-
model_api_key=os.environ["OPENAI_API_KEY"],
|
|
112
|
-
)
|
|
113
|
-
try:
|
|
114
|
-
page = (await browser.context.pages())[0]
|
|
115
|
-
await page.goto("https://github.com/browserbase")
|
|
116
|
-
|
|
117
|
-
# act() executes individual actions
|
|
118
|
-
await stagehand.act("click on the stagehand repo")
|
|
119
|
-
|
|
120
|
-
# observe() reports what is actionable on the page
|
|
121
|
-
observed = await stagehand.observe("find the latest PR")
|
|
122
|
-
|
|
123
|
-
# Locators give deterministic, Playwright-style actions
|
|
124
|
-
await page.locator(observed.data[0].selector).click()
|
|
125
|
-
|
|
126
|
-
# extract() returns structured data validated by a pydantic model
|
|
127
|
-
result = await stagehand.extract(
|
|
128
|
-
"extract the author and title of the PR",
|
|
129
|
-
PullRequest,
|
|
130
|
-
)
|
|
131
|
-
print(result.data.author, result.data.title)
|
|
132
|
-
finally:
|
|
133
|
-
await stagehand.close()
|
|
134
|
-
finally:
|
|
135
|
-
await browser.close()
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
asyncio.run(main())
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
See [`examples`](examples) for action, extraction, observation, and custom LLM usage.
|
|
142
|
-
|
|
143
|
-
For hosted browsers, import `browserbase` from `stagehand` and use
|
|
144
|
-
`browserbase.launch(api_key=...)` or `browserbase.connect(api_key=..., session_id=...)` instead of
|
|
145
|
-
`local_browser`. Calling `close()` on the browser handle releases the Browserbase session. To keep
|
|
146
|
-
a `keep_alive=True` session for later, call `stagehand.close()` without `browser.close()`.
|
|
147
|
-
|
|
148
|
-
The same `browserbase` facade exposes Browserbase Search and Fetch without launching a browser:
|
|
149
|
-
|
|
150
|
-
```python
|
|
151
|
-
import asyncio
|
|
152
|
-
import os
|
|
153
|
-
|
|
154
|
-
from stagehand import browserbase
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
async def search_and_fetch() -> None:
|
|
158
|
-
results = await browserbase.search(
|
|
159
|
-
api_key=os.environ["BROWSERBASE_API_KEY"],
|
|
160
|
-
query="browser agent frameworks",
|
|
161
|
-
num_results=5,
|
|
162
|
-
)
|
|
163
|
-
fetched = await browserbase.fetch(
|
|
164
|
-
api_key=os.environ["BROWSERBASE_API_KEY"],
|
|
165
|
-
url=results.results[0].url,
|
|
166
|
-
format="markdown",
|
|
167
|
-
)
|
|
168
|
-
print(fetched.content)
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
asyncio.run(search_and_fetch())
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
`Stagehand.act()`, `Stagehand.observe()`, and `Stagehand.extract()` use the active page by
|
|
175
|
-
default. Pass `page=page` to target a specific SDK `Page`.
|
|
176
|
-
|
|
177
|
-
`Page.goto()`, `reload()`, `go_back()`, and `go_forward()` return the main-document `Response`,
|
|
178
|
-
or `None` when navigation does not produce one. Response bodies and complete headers are retrieved
|
|
179
|
-
lazily while the Stagehand session remains open.
|
|
180
|
-
|
|
181
|
-
When contributing examples or tests, keep browser ownership explicit: launch or connect a
|
|
182
|
-
browser handle, pass it to `Stagehand.create()`, close Stagehand first, and close the browser in
|
|
183
|
-
the outermost `finally` block.
|
|
184
|
-
|
|
185
|
-
## Contributing
|
|
186
|
-
|
|
187
|
-
Clone the [Stagehand repository](https://github.com/browserbase/stagehand) and run these commands
|
|
188
|
-
from its root. All Python projects share the root uv workspace, `uv.lock`, and `.venv`.
|
|
189
|
-
`just install` installs all workspace members, and consumers use this SDK from source.
|
|
190
|
-
See [the contributing guide](https://github.com/browserbase/stagehand/blob/main/CONTRIBUTING.md)
|
|
191
|
-
for workspace membership and package-specific commands.
|
|
192
|
-
|
|
193
|
-
```bash
|
|
194
|
-
# Install uv
|
|
195
|
-
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
196
|
-
|
|
197
|
-
# Install just
|
|
198
|
-
brew install just
|
|
199
|
-
|
|
200
|
-
just install
|
|
201
|
-
just generate
|
|
202
|
-
just check
|
|
203
|
-
just test
|
|
204
|
-
just build
|
|
205
|
-
```
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
<div id="toc" align="center" style="margin-bottom: 0;">
|
|
2
|
-
<ul style="list-style: none; margin: 0; padding: 0;">
|
|
3
|
-
<a href="https://stagehand.dev">
|
|
4
|
-
<picture>
|
|
5
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_logo.png" />
|
|
6
|
-
<img alt="Stagehand" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_logo.png" width="200" style="margin-right: 30px;" />
|
|
7
|
-
</picture>
|
|
8
|
-
</a>
|
|
9
|
-
</ul>
|
|
10
|
-
</div>
|
|
11
|
-
<p align="center">
|
|
12
|
-
<strong>Stagehand is the SDK for browser agents.</strong><br>
|
|
13
|
-
<a href="https://docs.stagehand.dev">Read the Docs</a>
|
|
14
|
-
</p>
|
|
15
|
-
|
|
16
|
-
<p align="center">
|
|
17
|
-
<a href="https://github.com/browserbase/stagehand/tree/main?tab=MIT-1-ov-file#MIT-1-ov-file">
|
|
18
|
-
<picture>
|
|
19
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_license.svg" />
|
|
20
|
-
<img alt="MIT License" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_license.svg" />
|
|
21
|
-
</picture>
|
|
22
|
-
</a>
|
|
23
|
-
<a href="https://discord.gg/stagehand">
|
|
24
|
-
<picture>
|
|
25
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_discord.svg" />
|
|
26
|
-
<img alt="Discord Community" src="https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_discord.svg" />
|
|
27
|
-
</picture>
|
|
28
|
-
</a>
|
|
29
|
-
</p>
|
|
30
|
-
|
|
31
|
-
<p align="center">
|
|
32
|
-
<a href="https://trendshift.io/repositories/12122" target="_blank"><img src="https://trendshift.io/api/badge/repositories/12122" alt="browserbase%2Fstagehand | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
|
33
|
-
</p>
|
|
34
|
-
|
|
35
|
-
<p align="center">
|
|
36
|
-
<a href="https://deepwiki.com/browserbase/stagehand">
|
|
37
|
-
<img alt="Ask DeepWiki" src="https://deepwiki.com/badge.svg" />
|
|
38
|
-
</a>
|
|
39
|
-
</p>
|
|
40
|
-
|
|
41
|
-
# Stagehand Python SDK
|
|
42
|
-
|
|
43
|
-
## What is Stagehand?
|
|
44
|
-
|
|
45
|
-
Stagehand is the SDK for browser agents. Playwright was built for testing, Stagehand is built for agents. Use familiar APIs, self-healing actions, and network-level security across TypeScript, Python, and Go.
|
|
46
|
-
|
|
47
|
-
## Why Stagehand?
|
|
48
|
-
|
|
49
|
-
Stagehand gives browser agents an interface built for how they actually work. It combines familiar Playwright-style APIs with self-healing actions, agent-optimized page context, and native support for complex DOM structures like out-of-process iframes and closed Shadow DOMs.
|
|
50
|
-
|
|
51
|
-
Agents use fewer tokens, recover when websites change, and complete tasks more reliably. With a complete browser driver across TypeScript, Python, and Go, Stagehand delivers the flexibility of AI without sacrificing the speed, control, determinism, reliability, and observability required in production.
|
|
52
|
-
|
|
53
|
-
For the full overview, examples, and contributing guide, see the [main README](https://github.com/browserbase/stagehand/blob/main/README.md).
|
|
54
|
-
|
|
55
|
-
## Example
|
|
56
|
-
|
|
57
|
-
The async Python SDK for Stagehand browser automation:
|
|
58
|
-
|
|
59
|
-
```python
|
|
60
|
-
import asyncio
|
|
61
|
-
import os
|
|
62
|
-
|
|
63
|
-
from pydantic import BaseModel
|
|
64
|
-
|
|
65
|
-
from stagehand import Stagehand, browserbase, local_browser
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
class PullRequest(BaseModel):
|
|
69
|
-
author: str
|
|
70
|
-
title: str
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
async def main() -> None:
|
|
74
|
-
browser = await local_browser.launch(headless=True)
|
|
75
|
-
try:
|
|
76
|
-
stagehand = await Stagehand.create(
|
|
77
|
-
browser=browser,
|
|
78
|
-
model="openai/gpt-5.4-mini",
|
|
79
|
-
model_api_key=os.environ["OPENAI_API_KEY"],
|
|
80
|
-
)
|
|
81
|
-
try:
|
|
82
|
-
page = (await browser.context.pages())[0]
|
|
83
|
-
await page.goto("https://github.com/browserbase")
|
|
84
|
-
|
|
85
|
-
# act() executes individual actions
|
|
86
|
-
await stagehand.act("click on the stagehand repo")
|
|
87
|
-
|
|
88
|
-
# observe() reports what is actionable on the page
|
|
89
|
-
observed = await stagehand.observe("find the latest PR")
|
|
90
|
-
|
|
91
|
-
# Locators give deterministic, Playwright-style actions
|
|
92
|
-
await page.locator(observed.data[0].selector).click()
|
|
93
|
-
|
|
94
|
-
# extract() returns structured data validated by a pydantic model
|
|
95
|
-
result = await stagehand.extract(
|
|
96
|
-
"extract the author and title of the PR",
|
|
97
|
-
PullRequest,
|
|
98
|
-
)
|
|
99
|
-
print(result.data.author, result.data.title)
|
|
100
|
-
finally:
|
|
101
|
-
await stagehand.close()
|
|
102
|
-
finally:
|
|
103
|
-
await browser.close()
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
asyncio.run(main())
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
See [`examples`](examples) for action, extraction, observation, and custom LLM usage.
|
|
110
|
-
|
|
111
|
-
For hosted browsers, import `browserbase` from `stagehand` and use
|
|
112
|
-
`browserbase.launch(api_key=...)` or `browserbase.connect(api_key=..., session_id=...)` instead of
|
|
113
|
-
`local_browser`. Calling `close()` on the browser handle releases the Browserbase session. To keep
|
|
114
|
-
a `keep_alive=True` session for later, call `stagehand.close()` without `browser.close()`.
|
|
115
|
-
|
|
116
|
-
The same `browserbase` facade exposes Browserbase Search and Fetch without launching a browser:
|
|
117
|
-
|
|
118
|
-
```python
|
|
119
|
-
import asyncio
|
|
120
|
-
import os
|
|
121
|
-
|
|
122
|
-
from stagehand import browserbase
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
async def search_and_fetch() -> None:
|
|
126
|
-
results = await browserbase.search(
|
|
127
|
-
api_key=os.environ["BROWSERBASE_API_KEY"],
|
|
128
|
-
query="browser agent frameworks",
|
|
129
|
-
num_results=5,
|
|
130
|
-
)
|
|
131
|
-
fetched = await browserbase.fetch(
|
|
132
|
-
api_key=os.environ["BROWSERBASE_API_KEY"],
|
|
133
|
-
url=results.results[0].url,
|
|
134
|
-
format="markdown",
|
|
135
|
-
)
|
|
136
|
-
print(fetched.content)
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
asyncio.run(search_and_fetch())
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
`Stagehand.act()`, `Stagehand.observe()`, and `Stagehand.extract()` use the active page by
|
|
143
|
-
default. Pass `page=page` to target a specific SDK `Page`.
|
|
144
|
-
|
|
145
|
-
`Page.goto()`, `reload()`, `go_back()`, and `go_forward()` return the main-document `Response`,
|
|
146
|
-
or `None` when navigation does not produce one. Response bodies and complete headers are retrieved
|
|
147
|
-
lazily while the Stagehand session remains open.
|
|
148
|
-
|
|
149
|
-
When contributing examples or tests, keep browser ownership explicit: launch or connect a
|
|
150
|
-
browser handle, pass it to `Stagehand.create()`, close Stagehand first, and close the browser in
|
|
151
|
-
the outermost `finally` block.
|
|
152
|
-
|
|
153
|
-
## Contributing
|
|
154
|
-
|
|
155
|
-
Clone the [Stagehand repository](https://github.com/browserbase/stagehand) and run these commands
|
|
156
|
-
from its root. All Python projects share the root uv workspace, `uv.lock`, and `.venv`.
|
|
157
|
-
`just install` installs all workspace members, and consumers use this SDK from source.
|
|
158
|
-
See [the contributing guide](https://github.com/browserbase/stagehand/blob/main/CONTRIBUTING.md)
|
|
159
|
-
for workspace membership and package-specific commands.
|
|
160
|
-
|
|
161
|
-
```bash
|
|
162
|
-
# Install uv
|
|
163
|
-
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
164
|
-
|
|
165
|
-
# Install just
|
|
166
|
-
brew install just
|
|
167
|
-
|
|
168
|
-
just install
|
|
169
|
-
just generate
|
|
170
|
-
just check
|
|
171
|
-
just test
|
|
172
|
-
just build
|
|
173
|
-
```
|
|
File without changes
|
|
File without changes
|
{stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_extension/content-script.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_generated/__init__.py
RENAMED
|
File without changes
|
{stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/_generated/input_types.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/browserbase_connection.py
RENAMED
|
File without changes
|
|
File without changes
|
{stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/browserbase_services.py
RENAMED
|
File without changes
|
{stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/browserbase_session.py
RENAMED
|
File without changes
|
{stagehand-4.4.0a0.dev1676 → stagehand-4.4.1a0.dev1689}/src/stagehand/browserbase_transport.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|