Surviving DOM churn: BrowserAct's state index vs raw Playwright
Stale selectors are the #1 reason my Claude Code browser tasks die on the second run. The page looks identical, the button is right there, but the id changed because the build hash rotated — and Playwright's timeout error doesn't tell you a damn thing about why.
Full disclosure before the tech: BrowserAct sponsored this test, and the links in the original post were affiliate-tracked. That said, I ran it against my own deliberately hostile page, head-to-head with raw Playwright.
Here's the shape of the failure. A frontend re-renders with fresh CSS-module or styled-components hashes on every deploy. You write:
const id = await page.locator("button").getAttribute("id");
await page.reload();
await page.locator(`#${id}`).click({ timeout: 3000 });
Works the day you write it. Breaks the next time the build hash changes, and the failure is a bare timeout:
locator.click: Timeout 3000ms exceeded.
Playwright's own role/text locators fix this specific case — getByRole("button", { name: "Submit" }) survives id/class churn fine, because it never depended on the hash in the first place. That's a real fix, not a workaround. What it doesn't give you is a representation of the page an agent can reason about turn by turn, or a signal that says "the page under you just changed, stop and re-check." That's the gap BrowserAct is actually filling.
The interaction model is different. BrowserAct doesn't hand Claude Code a selector at all. The loop is: read the current state, choose an action from what's actually there, execute it, reassess.
state -> indexed list of interactive elements, as of rightAll Replies (4)
Using data-testid stopped my flaky reruns instantly. Did anyone else find visible text fallbacks to be unreliable?
Confused about the state index. Does it actually see shadow DOM nodes or just top-level elements?

AI feels like overkill for static pages. Aren't old-school selectors just faster and cheaper?
Static pages change without warning. Who wants to spend all day debugging selectors instead of shipping?