Skip to content

Commit abd9305

Browse files
committed
Merge remote-tracking branch 'origin/stainless' into stainless
2 parents 7e55db7 + 7ebf5f6 commit abd9305

File tree

4 files changed

+398
-12
lines changed

4 files changed

+398
-12
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ If you're looking for other languages, you can find them
4949
</picture>
5050
</div>
5151

52+
> [!TIP]
53+
> Migrating from the old v2 Python SDK? See our [migration guide here](https://docs.stagehand.dev/v3/migrations/python).
54+
5255
## What is Stagehand?
5356

5457
Stagehand 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.
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
"""
2+
Example: use a Playwright Page with the Stagehand Python SDK.
3+
4+
What this demonstrates:
5+
- Start a Stagehand session (remote Stagehand API / Browserbase browser)
6+
- Attach Playwright to the same browser via CDP (`cdp_url`)
7+
- Pass the Playwright `page` into `session.observe/act/extract` so Stagehand
8+
auto-detects the correct `frame_id` for that page.
9+
10+
Environment variables required:
11+
- MODEL_API_KEY
12+
- BROWSERBASE_API_KEY
13+
- BROWSERBASE_PROJECT_ID
14+
15+
Optional:
16+
- STAGEHAND_BASE_URL (defaults to https://api.stagehand.browserbase.com)
17+
"""
18+
19+
from __future__ import annotations
20+
21+
import os
22+
import sys
23+
from typing import Optional
24+
25+
from stagehand import Stagehand
26+
27+
28+
def main() -> None:
29+
model_api_key = os.environ.get("MODEL_API_KEY")
30+
if not model_api_key:
31+
sys.exit("Set the MODEL_API_KEY environment variable to run this example.")
32+
33+
bb_api_key = os.environ.get("BROWSERBASE_API_KEY")
34+
bb_project_id = os.environ.get("BROWSERBASE_PROJECT_ID")
35+
if not bb_api_key or not bb_project_id:
36+
sys.exit(
37+
"Set BROWSERBASE_API_KEY and BROWSERBASE_PROJECT_ID to run this example."
38+
)
39+
40+
try:
41+
from playwright.sync_api import sync_playwright # type: ignore[import-not-found]
42+
except Exception:
43+
sys.exit(
44+
"Playwright is not installed. Install it with:\n"
45+
" uv pip install playwright\n"
46+
"and ensure browsers are installed (e.g. `playwright install chromium`)."
47+
)
48+
49+
session_id: Optional[str] = None
50+
51+
with Stagehand(
52+
server="remote",
53+
browserbase_api_key=bb_api_key,
54+
browserbase_project_id=bb_project_id,
55+
model_api_key=model_api_key,
56+
) as client:
57+
print("⏳ Starting Stagehand session...")
58+
session = client.sessions.create(
59+
model_name="openai/gpt-5-nano",
60+
browser={"type": "browserbase"},
61+
)
62+
session_id = session.id
63+
64+
cdp_url = session.data.cdp_url
65+
if not cdp_url:
66+
sys.exit(
67+
"No cdp_url returned from the API for this session; cannot attach Playwright."
68+
)
69+
70+
print(f"✅ Session started: {session_id}")
71+
print("🔌 Connecting Playwright to the same browser over CDP...")
72+
73+
with sync_playwright() as p:
74+
# Attach to the same browser session Stagehand is controlling.
75+
browser = p.chromium.connect_over_cdp(cdp_url)
76+
try:
77+
# Reuse an existing context/page if present; otherwise create one.
78+
context = browser.contexts[0] if browser.contexts else browser.new_context()
79+
page = context.pages[0] if context.pages else context.new_page()
80+
81+
page.goto("https://example.com", wait_until="domcontentloaded")
82+
83+
print("👀 Stagehand.observe(page=...) ...")
84+
actions = session.observe(
85+
instruction="Find the most relevant click target on this page",
86+
page=page,
87+
)
88+
print(f"Observed {len(actions.data.result)} actions")
89+
90+
print("🧠 Stagehand.extract(page=...) ...")
91+
extracted = session.extract(
92+
instruction="Extract the page title and the primary heading (h1) text",
93+
schema={
94+
"type": "object",
95+
"properties": {
96+
"title": {"type": "string"},
97+
"h1": {"type": "string"},
98+
},
99+
"required": ["title", "h1"],
100+
"additionalProperties": False,
101+
},
102+
page=page,
103+
)
104+
print("Extracted:", extracted.data.result)
105+
106+
print("🖱️ Stagehand.act(page=...) ...")
107+
_ = session.act(
108+
input="Click the 'More information' link",
109+
page=page,
110+
)
111+
print("Done.")
112+
finally:
113+
browser.close()
114+
115+
116+
if __name__ == "__main__":
117+
main()
118+

0 commit comments

Comments
 (0)