<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Marcelo Bairros</title>
    <description>The latest articles on DEV Community by Marcelo Bairros (@sellooh).</description>
    <link>https://dev.to/sellooh</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3639326%2F1b59e8fe-337a-42e9-b2a9-c5d6a98748db.png</url>
      <title>DEV Community: Marcelo Bairros</title>
      <link>https://dev.to/sellooh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sellooh"/>
    <language>en</language>
    <item>
      <title>Playwright + AI = Stagehand (It's Better Than It Sounds)</title>
      <dc:creator>Marcelo Bairros</dc:creator>
      <pubDate>Mon, 01 Dec 2025 14:47:19 +0000</pubDate>
      <link>https://dev.to/sellooh/playwright-ai-stagehand-its-better-than-it-sounds-2gi4</link>
      <guid>https://dev.to/sellooh/playwright-ai-stagehand-its-better-than-it-sounds-2gi4</guid>
      <description>&lt;p&gt;&lt;em&gt;From fragile CSS selectors to "click the login button" — how I turbocharged browser automation without throwing Playwright away&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd2l7mrrgyxcr9woejb3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd2l7mrrgyxcr9woejb3g.png" alt="Playwright + AI = Stagehand" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've always valued end-to-end testing immensely.&lt;/p&gt;

&lt;p&gt;It's the type of test that catches real world issues.&lt;/p&gt;

&lt;p&gt;We know data can be messy, infrastructure shifts, but the end-to-end integration test is the test that validates core features are working.&lt;/p&gt;

&lt;p&gt;But they add considerable overhead.&lt;/p&gt;

&lt;p&gt;Even with a great framework like Playwright, without solid coordination between developers and SDETs those tests are not adding real confidence for the team if they:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are fragile to UI changes&lt;/li&gt;
&lt;li&gt;Are flaky and unreliable&lt;/li&gt;
&lt;li&gt;Don't add value for other stakeholders&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this post I'll share a library I found called Stagehand which gives you a code-first solution that makes end-to-end automations more robust and valuable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fug3g91tn9ekyi24uu2l7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fug3g91tn9ekyi24uu2l7.png" alt="Playwright VS Stagehand" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Stagehand (And What It's NOT)
&lt;/h2&gt;

&lt;p&gt;Let me clear something up right away: &lt;strong&gt;Stagehand is not a Playwright replacement. It's a Playwright enhancement.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the website they position as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We built an OSS alternative to Playwright that's easier to use and lets AI reliably read and write on the web."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But I believe there's a lot more value to gain by using them together. Playwright has a huge ecosystem and wide range of capabilities.&lt;/p&gt;

&lt;p&gt;I don't think it's worthwhile to simply throw that away, when both tools can be used together.&lt;/p&gt;

&lt;p&gt;See more: &lt;a href="https://docs.stagehand.dev/v3/integrations/playwright" rel="noopener noreferrer"&gt;https://docs.stagehand.dev/v3/integrations/playwright&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Three AI Powers: Act, Extract, Observe
&lt;/h2&gt;

&lt;p&gt;Stagehand gives you three core AI-powered methods. Each serves a different purpose, and understanding when to use each one is key to getting the most out of the library.&lt;/p&gt;

&lt;h3&gt;
  
  
  Act: "Just Do the Thing"
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;act()&lt;/code&gt; is the workhorse. You describe what you want to happen in natural language, and Stagehand figures out how to do it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Traditional Playwright:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Hope this selector doesn't change...&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button[data-testid="submit-form"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Or worse, when there's no good selector&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;xpath=//button[contains(@class, "primary") and contains(text(), "Submit")]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Stagehand:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This works even if the button's class, ID, or text changes slightly&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stagehand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;act&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click the submit button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The magic is in the resilience. If the frontend team changes the button from "Submit" to "Send" or "Confirm", your test doesn't break. The AI understands intent, not just DOM structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extract: "Pull Data Out"
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;extract()&lt;/code&gt; is for when you need to get structured data from a page. Instead of writing complex selectors to scrape text, you describe what you want in plain English.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Traditional Playwright:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Fragile and breaks if structure changes&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.product-card h2.title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productPrice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.product-card .price-tag span&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inStock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.product-card .availability&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Stagehand:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stagehand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Extract the product name, price, and availability status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;inStock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productInfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// { name: "Wireless Mouse", price: "$29.99", inStock: true }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Zod schema integration is particularly nice. You get type-safe extraction with validation built in. If the AI can't find what you're looking for, you get a structured error instead of silent failures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observe: "What Can I Do Here?"
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;observe()&lt;/code&gt; is the most interesting one conceptually. It tells you what actions are possible on the current page. This is incredibly useful for building agents that need to dynamically navigate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stagehand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// [&lt;/span&gt;
&lt;span class="c1"&gt;//   { action: "click the login button", selector: "#login-btn" },&lt;/span&gt;
&lt;span class="c1"&gt;//   { action: "enter text in the search field", selector: "input[name='q']" },&lt;/span&gt;
&lt;span class="c1"&gt;//   { action: "click the shopping cart icon", selector: ".cart-icon" },&lt;/span&gt;
&lt;span class="c1"&gt;//   ...&lt;/span&gt;
&lt;span class="c1"&gt;// ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where Stagehand starts feeling less like a testing tool and more like a foundation for AI agents. You can build systems that explore, adapt, and interact with any website without prior knowledge of its structure.&lt;/p&gt;




&lt;h2&gt;
  
  
  Self-Healing: The Differentiator That Matters
&lt;/h2&gt;

&lt;p&gt;This is the feature that sold me. Stagehand caches its AI decisions, so the second time you run the same action, it's fast. But here's where it gets clever: if the cached selector breaks, Stagehand automatically re-queries the AI to find the new correct element.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is self-healing in action.&lt;/strong&gt; Your tests become resilient to UI changes without you lifting a finger.&lt;/p&gt;

&lt;p&gt;Compare this to traditional Playwright where:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Test fails&lt;/li&gt;
&lt;li&gt;CI goes red&lt;/li&gt;
&lt;li&gt;You get paged (or worse, find out hours later)&lt;/li&gt;
&lt;li&gt;You investigate what broke&lt;/li&gt;
&lt;li&gt;You update the selector&lt;/li&gt;
&lt;li&gt;You push a fix&lt;/li&gt;
&lt;li&gt;You wait for CI again&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With Stagehand, step 1 becomes "test heals itself and passes" — no human intervention required for cosmetic changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Agent Mode: The Experimental Part (Honest Take)
&lt;/h2&gt;

&lt;p&gt;Stagehand also includes an &lt;code&gt;agent()&lt;/code&gt; method that attempts to accomplish complex goals autonomously. You give it a high-level objective, and it chains together observe → act → observe → act until it succeeds.&lt;/p&gt;

&lt;p&gt;Here's the truth: in my testing, results were mixed.&lt;/p&gt;

&lt;p&gt;When it works, it's magical. I've seen it successfully navigate complex flows that would take dozens of lines of traditional code. But I've also seen it get confused by popups, take 30 seconds for something a hardcoded test does in 2 seconds, and occasionally just… give up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My honest assessment:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Great for:&lt;/strong&gt; Exploratory testing, demos, prototyping flows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not ready for:&lt;/strong&gt; Production CI pipelines where you need predictable timing and costs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Getting better:&lt;/strong&gt; Each Stagehand release improves agent reliability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're evaluating Stagehand primarily for agent capabilities, temper your expectations. But if you're using it for the core act/extract/observe methods with occasional agent assists, you'll be happy.&lt;/p&gt;

&lt;p&gt;It's worth noting Stagehand supports Computer Use models which is a big differentiator. I think this space has a lot of room to grow.&lt;/p&gt;

&lt;p&gt;Learn more: &lt;a href="https://docs.stagehand.dev/v3/best-practices/computer-use" rel="noopener noreferrer"&gt;https://docs.stagehand.dev/v3/best-practices/computer-use&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  100% Playwright Compatibility
&lt;/h2&gt;

&lt;p&gt;This deserves its own section because it's the key to practical adoption.&lt;/p&gt;

&lt;p&gt;Stagehand gives you direct access to the underlying Playwright page object. From the Stagehand docs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Stagehand&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@browserbasehq/stagehand&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;chromium&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;playwright-core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod/v3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Initialize Stagehand&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stagehand&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Stagehand&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BROWSERBASE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;openai/gpt-5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;verbose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stagehand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Stagehand initialized&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Connect Playwright to Stagehand's browser&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chromium&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connectOverCDP&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;wsEndpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;stagehand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connectURL&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pwContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contexts&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pwPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pwContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="c1"&gt;// Navigate and interact&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pwPage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Use Stagehand's AI methods&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stagehand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;find the main heading&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pwPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Found actions:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Extract data&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;heading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stagehand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;extract the main heading text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;heading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pwPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Heading:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;heading&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Cleanup&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stagehand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This interoperability means you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start with your existing Playwright test suite&lt;/li&gt;
&lt;li&gt;Gradually add Stagehand for the flaky parts&lt;/li&gt;
&lt;li&gt;Keep precise Playwright control where it makes sense&lt;/li&gt;
&lt;li&gt;Never be locked into one approach&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You're not rewriting anything. You're enhancing selectively.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Here's the cheat sheet:&lt;/p&gt;

&lt;p&gt;✅ Stagehand complements Playwright, doesn't replace it&lt;/p&gt;

&lt;p&gt;✅ Three core methods: act (do things), extract (get data), observe (discover options)&lt;/p&gt;

&lt;p&gt;✅ Self-healing tests that survive UI changes automatically&lt;/p&gt;

&lt;p&gt;✅ 100% Playwright compatible — use both in the same test&lt;/p&gt;

&lt;p&gt;⚠️ Agent mode is experimental — promising but still limited from my tests&lt;/p&gt;

&lt;p&gt;⚠️ Not a silver bullet — use it where fragile selectors are actually your problem&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Will I rewrite all my tests in Stagehand? No. Will I reach for it every time I'm writing a selector that I know will break in two weeks? Absolutely.&lt;/p&gt;

&lt;p&gt;The best part is there's no commitment. Try it on one flaky test. See if it helps. If it does, use it more. If it doesn't fit your workflow, you've lost nothing — your Playwright code is still there, untouched.&lt;/p&gt;

&lt;p&gt;That's the kind of low-risk, high-potential tool I love discovering.&lt;/p&gt;

&lt;p&gt;Have you tried Stagehand? I'm curious what results others are getting, especially with the agent mode. Drop a comment or reach out — I'm genuinely interested in comparing notes.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;And if you like Stagehand, check out &lt;a href="https://ledda.ai" rel="noopener noreferrer"&gt;Ledda.ai&lt;/a&gt; — We are building the next platform for natural language to web automation. It's the easiest platform to create QA regression suites and synthetic monitoring for production in minutes instead of hours.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>automation</category>
      <category>javascript</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
