browser-harness, Playwright, and Puppeteer: which browser automation tool should you choose?

A comparison of browser-harness, Playwright, and Puppeteer across positioning, browser support, auto-waiting, contexts, tooling, and suitable scenarios.

In browser automation and automated testing, Playwright and Puppeteer are two of the most commonly compared tools. Both can control browsers, click pages, extract content, generate screenshots or PDFs, and both are closely related to Chrome DevTools Protocol.

Once browser-use/browser-harness is added to the picture, the question is no longer simply “which testing framework is stronger.” It becomes a comparison between two kinds of tools:

  • Playwright / Puppeteer: tools for engineers to write deterministic scripts.
  • browser-harness: a tool for AI agents to operate real browsers.

The first group fits testing, scraping, and engineered automation. The second is closer to a browser control layer for agents such as Claude Code, Codex CLI, and Gemini.

The relationship between Playwright and Puppeteer

Puppeteer was originally launched by the Google Chrome team and naturally focuses on Chromium and Chrome automation. Its API is concise, the ecosystem is mature, and it is especially convenient for screenshots, PDF generation, page scraping, and lightweight automation around Chrome.

Playwright is maintained by Microsoft, and its team has deep historical links to early Puppeteer work. It absorbed many lessons from Puppeteer and added stronger cross-browser support, auto-waiting, context isolation, test reports, and debugging tools.

In short:

  • If you only need lightweight Chrome-based tasks, Puppeteer is still very pleasant to use.
  • If you are doing cross-browser E2E tests, complex SPA automation, or team-level test engineering, Playwright is usually the better fit.

Core differences

Dimension Puppeteer Playwright
Maintainer Google Microsoft
Browser support Mainly Chrome / Chromium Chromium, Firefox, WebKit
Language support Mainly JavaScript / TypeScript JavaScript / TypeScript, Python, Java, .NET
Auto-waiting More explicit waiting Strong Locator and auto-waiting
Context isolation Supported, but less central Excellent BrowserContext workflow
Tooling Simple, mature, foundational Codegen, Trace Viewer, reports
Typical use Chrome automation, screenshots, PDF, lightweight scraping Cross-browser E2E tests, complex frontend automation

Browser support

Puppeteer is strongest with Chrome. It integrates tightly with Chromium. If your goal is to control Chrome, generate PDFs, take screenshots, or run simple scraping tasks, Puppeteer has a low mental overhead.

Playwright is stronger for cross-browser work. It natively supports Chromium, Firefox, and WebKit. WebKit is especially important because many Safari-related issues cannot be detected through Chrome alone. For applications that need coverage across desktop, mobile, and multiple browser engines, Playwright is the better main tool.

This is the first decision boundary: if you only care about Chrome, Puppeteer is fine. If you are serious about cross-browser testing, choose Playwright first.

Auto-waiting and stability

The most annoying part of browser automation is often not “how to click,” but whether the page is ready. An element may not be attached to the DOM, may be covered, may still be animating, or may still be disabled.

In Puppeteer, you often write:

1
2
await page.waitForSelector('#submit-btn');
await page.click('#submit-btn');

This works, but engineers must think through the waiting logic themselves. The more complex the page, the more likely the script will accumulate waitForSelector, waitForTimeout, and retry logic.

Playwright’s Locator and auto-waiting mechanism is more complete:

1
await page.locator('#submit-btn').click();

Before clicking, Playwright checks whether the element is visible, actionable, stable, and not covered, then retries within a reasonable time. This matters a lot for modern React, Vue, and Next.js applications with heavy asynchronous rendering, and it reduces flaky tests.

Multi-account workflows and context isolation

If you need to simulate multiple users, or let many tasks share one browser process while isolating Cookie, LocalStorage, and Session, BrowserContext matters.

Puppeteer also supports context isolation, but Playwright makes it a core capability. You can quickly create multiple independent contexts inside one browser instance. Each context behaves like a clean browser environment without repeatedly starting full browser processes.

This is useful for:

  • Multi-account concurrent tests.
  • Multi-role workflow tests.
  • Ecommerce, messaging, and collaborative document scenarios.
  • Scraping tasks that need isolated Cookie and login state.

Tooling differences

Playwright is the more engineering-oriented option. It includes many tools used in test development:

  • codegen: operate on a webpage and generate scripts automatically.
  • Trace Viewer: replay screenshots, DOM snapshots, network requests, and console logs after failures.
  • Test Runner: assertions, parallelism, retries, reports, and project matrices.
  • Locator: element selection by text, role, label, test id, and CSS.

Puppeteer is more like a lightweight browser control library. It is not bloated, its API is direct, and it is easy to embed in scripts, server-side jobs, and custom automation flows.

If you are building an enterprise-grade test system, Playwright’s tooling saves a lot of work. If you only need a Node.js script to convert webpages to PDFs or take scheduled screenshots, Puppeteer may be cleaner.

Where browser-harness fits

browser-harness is not the same kind of tool as Playwright or Puppeteer.

Playwright and Puppeteer mostly assume that humans write scripts. Engineers choose selectors, waiting conditions, assertions, and exception handling. They pursue determinism: the same script should produce the same result under the same page state.

browser-harness mostly assumes that an AI agent operates the browser. Its goal is not to provide a huge high-level API, but to connect to real Chrome through CDP and expose screenshots, coordinate clicks, DOM, network requests, and helpers to the agent. The agent can observe the page, decide the next step, add helpers when capabilities are missing, and turn site experience into skills.

That makes it better for open-ended tasks:

  • Log in to a backend and download invoices.
  • Fill a group of forms in an internal system.
  • Handle OA or SaaS pages that change often.
  • Explore a page according to a user goal instead of running a fixed script.
  • Give tools such as Claude Code and Codex CLI browser operation capability.

What browser-harness is

Structurally, browser-harness is closer to a browser runtime for agents than a browser extension for manual users.

Its core ideas are:

  • Connect directly to Chrome or Chromium.
  • Control pages through a CDP WebSocket.
  • Let agents combine screenshots, coordinate clicks, DOM inspection, network requests, and raw CDP.
  • Put task-specific helpers in agent-workspace/agent_helpers.py.
  • Store site-specific experience in agent-workspace/domain-skills/.
  • Keep the core thin instead of turning it into a large automation platform.

The README says the core architecture is roughly four core files and about 1,000 lines of code, covering install.md, SKILL.md, src/browser_harness/, agent-workspace/agent_helpers.py, and agent-workspace/domain-skills/.

The point is not to ship built-in support for every website. The point is to give the agent an operation layer close enough to a real browser, so it can fill in missing capabilities for the task at hand.

How it differs from traditional browser automation

Traditional browser automation usually revolves around testing frameworks such as Playwright, Selenium, or Puppeteer. They are good for deterministic scripts: open a page, locate an element, click it, and assert the result.

browser-harness targets a different kind of work. A user gives a goal, and the agent explores the page, judges the state, handles popups, adds helpers, and reuses site knowledge. It emphasizes adaptation during interaction.

The difference can be summarized like this:

  • Playwright is better when humans write scripts and agents run them.
  • browser-harness is better when agents look at the page and act step by step.
  • Traditional automation favors fixed flows.
  • browser-harness favors open-ended tasks.
  • Traditional scripts often depend on selectors.
  • browser-harness encourages screenshots first, visible UI actions next, and DOM or CDP when needed.

This does not mean it replaces Playwright. For stable tests, Playwright is still more mature. browser-harness is valuable because it turns real webpages into an environment an agent can operate, especially when page structure is complex, steps are not fixed, and situational judgment matters.

Why real Chrome matters

Many browser-agent tools use isolated headless browsers. That is simple to deploy and good for batch jobs, but it does not always reuse the user’s real working environment: login state, extensions, history, bookmarks, and daily browser setup.

browser-harness supports local Chrome and the Browser Use cloud browser. For local browsers, it offers two approaches:

  • Use chrome://inspect/#remote-debugging to allow the current Chrome instance to be connected.
  • Start an isolated profile with --remote-debugging-port=9222 --user-data-dir=....

If you want an agent to help with tasks inside real accounts, the docs lean toward the first approach because it reuses everyday Chrome login state, extensions, and bookmarks. For unattended automation, or when you do not want popups to interrupt work, an isolated profile or cloud browser is usually safer.

The trade-off is clear: real Chrome is closer to the user’s workflow, but the security boundary is more sensitive. An isolated browser is easier to control, but login and environment setup must be handled again.

Editable helpers and domain skills

The most interesting part of browser-harness is that it designs “what the agent learns” into the project structure.

agent-workspace/agent_helpers.py stores helpers that are created during tasks. For example, if an agent needs to upload a file and the existing tools are not enough, it can add a stable upload helper. The next time it sees a similar page, it does not have to start from scratch.

agent-workspace/domain-skills/ stores site-level experience. The README mentions areas such as LinkedIn outreach, Amazon ordering, and reimbursement systems. The project recommends letting agents generate these skills from real tasks instead of hand-writing them, because they should reflect actual page behavior.

This fits browser automation well. The hard part is often not “how to click a button,” but:

  • How a website redirects after login.
  • Which popups block the main flow.
  • Which selectors are stable and which are temporary class names.
  • How uploads, downloads, iframes, shadow DOM, and cross-origin components behave.
  • What hidden waits and asynchronous states exist in a specific backend.

If this knowledge only stays in one run log, it is quickly lost. Turning it into domain skills gives the agent a chance to improve over time.

Suitable scenarios

browser-harness is better suited for:

  • Operating real web admin panels for users.
  • Completing repeated flows in systems without APIs.
  • Personal or enterprise web tasks that depend heavily on login state.
  • Complex interactions where screenshots are needed to judge page state.
  • Agents that need to add tools and site knowledge while running.
  • Multiple sub-agents each using an isolated browser.
  • Researching browser-agent runtime design.

Concrete examples include organizing web tables, submitting internal forms, downloading invoices, uploading files, handling reimbursement workflows, checking order status, configuring SaaS dashboards, and extracting information from logged-in pages.

If the task is only to fetch static pages, a browser may not be needed. The project’s own SKILL.md also notes that static pages can often be fetched through HTTP in bulk. Browsers should be reserved for tasks that truly need page state, login state, and interaction.

Risks to watch

Letting an AI agent control real Chrome is powerful, but risky.

First, the permission boundary must be clear. Real Chrome may contain email, payment dashboards, cloud consoles, company systems, and personal accounts. Once an agent can operate the browser, it effectively has access to part of those webpage permissions.

Second, do not hand credentials to the model. For login pages, payment verification, and second confirmations, the user should handle the sensitive step. The agent can wait for login to finish, but it should not read or enter passwords, verification codes, or payment details from screenshots.

Third, automation is not the same as delegation. Many web tasks look simple but may involve risk controls, mistaken clicks, data deletion, bulk submissions, or irreversible operations. Start with read-only, low-risk, reversible workflows.

Fourth, domain skills should not leak private data. Site knowledge can be shared, but account names, internal URLs, customer data, coordinate logs, and one-off task details should not be written into skills.

Fifth, choose the browser connection mode carefully. Reusing daily Chrome is convenient when login state matters. For long-running automation, an isolated profile or cloud browser is more controllable.

Why it matters for AI agent tools

browser-harness represents a pragmatic direction for agent tooling: build less platform, and give the model a direct interface to the real environment.

Many agents fail at two ends. On one end, the model can reason but cannot touch the real page. On the other, automation frameworks are powerful but require humans to hard-code the flow. browser-harness tries to connect the two: the browser holds real-world state, while the agent observes, decides, and adds tools.

That is also the meaning of a self-improving harness. It does not mean the agent magically becomes smarter. It means reusable operation experience is placed into the project structure, so the next task can avoid some of the same detours.

For developers, its value is mainly in three areas:

  • A browser control layer for personal agents.
  • A reference for studying browser automation and agent workflows.
  • An experimental framework for turning web workflows into reusable skills.

It is not the answer to every browser automation problem, but it points in a clear direction: when agents truly help people do work, the tool layer should not only call APIs. It should also understand and operate the web interfaces people use every day.

What domain skills are

You can think of domain skills as site-operation manuals for agents.

They are not ordinary user documentation, and they are not one-off scripts. They are closer to field-tested site knowledge:

  • Whether the site is suitable for browser automation.
  • Which API should be used first if an API exists.
  • Which URL should be used when the browser is necessary.
  • Which DOM structures, aria-labels, and button behaviors have been verified.
  • Which common approaches fail.
  • Which scenarios should stop and ask for human intervention.

This content can be reviewed by humans and read by agents during tasks. It turns on-the-spot exploration into maintainable experience.

They are not about blind clicking

A good browser agent should not turn every problem into opening a webpage, looking at screenshots, and clicking buttons.

One important kind of experience in domain skills tells the agent when not to use the browser.

For sites such as ArXiv, paper search, metadata, and abstracts can be fetched directly through the Atom API or HTML meta tags. HTTP requests are usually faster, more stable, and easier to parse than opening a browser.

GitHub follows a similar pattern. Repository, user, and release data should use the REST API first. File contents should use raw.githubusercontent.com first. Only pages such as GitHub Trending, which do not have an equivalent API, need browser interaction.

This shows that browser-harness is not based on “the browser solves everything.” It puts the browser in the right place: when APIs, HTTP, and static pages cannot solve the problem, let the agent operate a real page.

They store site-level knowledge

Traditional automation scripts are usually written around one task, for example:

1
Open page -> enter keyword -> click button -> download file

That script may complete the task, but the experience is scattered inside code. When the site changes, the script may fail. When the task changes, much of the experience may not be reusable.

domain skills are closer to a site-level knowledge base. They care about:

  • Which container selector is stable in Amazon search results.
  • Which GitHub data should go through the REST API.
  • How LinkedIn invitation buttons differ in aria-label.
  • Which Shopify Admin pages are embedded apps.
  • Why Shopify Polaris inputs cannot always be filled with normal JS value assignment.
  • How Browser Use Cloud browser instances are created, listed, and cleaned up.

These are not steps for one task. They are decision-making knowledge that many future tasks can reuse.

For Amazon product search, the important part is not only how to search, but which path is more stable.

A more reliable approach is to use a direct search URL instead of opening the homepage and simulating typing every time. Search results can be extracted from a container such as [data-component-type="s-search-result"]. Field extraction also has details: title, price, rating, review count, and sponsored status each have more stable DOM sources.

This kind of experience is valuable for an agent. Without it, the agent may guess buttons from screenshots and repeatedly try selectors. With it, the agent can go directly to a more stable extraction path.

More importantly, a skill can record traps. For example, some selectors that look usable may misread sponsored results or cross-sell areas. You only learn that from field testing.

Example: LinkedIn invitation management

LinkedIn is closer to a real account workflow, and the risk is higher.

On the invitation manager page, the Accept and Ignore buttons use different aria-label formats. You cannot simply derive one from the other. Some invitation cards even render Accept as an <a> element rather than a <button>, and ordinary CDP clicks may not trigger the accept action.

This shows that real web automation does not end when an element is located. Button labels, event binding, soft navigation, and component implementation all affect whether an action really works.

For an agent, this experience also has a safety meaning. Operations involving social accounts, invitations, messages, and posting should not be fully delegated. A skill can record the path and traps, but accepting invitations in bulk, sending content externally, or changing account details should keep human confirmation.

Example: Shopify Admin

Shopify Admin shows another issue: backend systems are often not one page, but a combination of embedded apps and complex components.

Many Shopify apps run inside iframes. Polaris React inputs, Web Components, and embedded apps all behave differently. Some inputs cannot be filled with element.value = ...; they need CDP keystrokes that are closer to real keyboard input.

The value of this kind of skill is that it lets the agent first identify what kind of UI it is looking at, then choose the right operation method.

Shopify experience also emphasizes “do not use the browser if you do not have to”:

  • For read-only product and inventory data, use the Storefront API first.
  • If an Admin API token exists, use the Admin API first.
  • For theme code editing, use Shopify CLI first.
  • Use the browser only when there is no API, the change is rare, or you are exploring the admin.

That is a mature tool-selection logic for agents.

Example: Browser Use Cloud

domain skills do not only serve webpage clicking. They can also record API experience around browser runtimes.

Browser Use Cloud experience can record how to create cloud browsers through REST APIs, list running browsers, clean up zombie browsers, and obtain liveUrl and cdpUrl.

This means a skill is not limited to “how to click a button.” Any recurring task with a stable method can become a skill:

  • API call patterns.
  • Authentication header format.
  • Request and response structure.
  • Verified status codes.
  • Common failure modes.
  • Resource cleanup and recycling methods.

For agents, all of these are reusable capabilities.

Why this is more reliable than ad-hoc reasoning

Many people expect a large model to understand the webpage by itself every time. In real tasks, relying only on ad-hoc reasoning is unstable.

The reasons are simple:

  • Web UI changes often.
  • The same button may have multiple implementations.
  • Visible does not mean clickable.
  • Clickable does not mean the action really worked.
  • Some tasks should use APIs instead of browsers.
  • Some operations require human confirmation and should not be decided by the model alone.

Writing these experiences into files brings several benefits:

  • Humans can review them.
  • Wrong experience can be corrected.
  • Site knowledge can accumulate over time.
  • New agents can inherit old experience.
  • Temporary task discoveries can become long-term knowledge.

This is more stable than putting everything into a prompt or chat context.

How teams can use it

In a team, domain skills can become a lightweight automation knowledge base.

Useful content to record includes:

  • Post-login paths in internal systems.
  • Report export flows.
  • Common popup handling.
  • Which buttons require human confirmation.
  • Which pages have API alternatives.
  • Which selectors were tested and found reliable.
  • Which tasks agents are not allowed to run automatically.

This knowledge does not need to be complete at the beginning. A practical path is to start with low-risk, frequent, reversible workflows: read-only tasks, downloads, organization, and checks. Once the flow is stable, turn the experience into a skill.

For team managers, skill files also make automation boundaries visible. You can inspect what the agent knows, what it can do, and where it should stop.

Boundaries to keep

domain skills can improve an agent’s success rate, but they should not fully automate high-risk operations.

Several boundaries matter:

  • Do not record passwords, Cookie, token, customer data, or sensitive internal URLs.
  • Keep human confirmation for payments, deletion, bulk submission, account changes, and external publishing.
  • Record verification date and scope.
  • Allow skills to expire after site changes and require revalidation.
  • Do not make bypassing risk controls or platform limits a goal.

In other words, domain skills make agents steadier. They do not give agents unlimited permission.

Three-way comparison

Dimension Puppeteer Playwright browser-harness
Target user Engineers Engineers and test teams AI Agent
Main goal Control Chrome Stable cross-browser automation Let agents operate real browsers
Script style Hand-written JS/TS automation Scripts plus test framework User gives a goal, agent executes steps
Element targeting CSS, XPath, DOM API Locator, text, role, CSS Screenshots, coordinates, DOM, CDP
Waiting More manual control Strong auto-waiting Agent observes and adjusts
Browser environment Usually automated browser Usually test browser Often real Chrome
Best fit Chrome scripts, screenshots, PDF, lightweight scraping E2E tests, cross-browser validation, complex SPA AI assistants, open web tasks, real-account workflows

Code feel

Puppeteer feels closer to directly controlling Chrome:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');

  await page.waitForSelector('#submit-btn');
  await page.click('#submit-btn');

  await browser.close();
})();

Playwright emphasizes Locator and auto-waiting:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');

  await page.locator('#submit-btn').click();

  await browser.close();
})();

browser-harness feels completely different. You usually do not write a full script. You give a goal inside an agent environment:

1
Open the admin panel, download last month’s invoice, and organize it for reimbursement.

The agent then repeatedly uses browser-harness to:

  • Take screenshots and understand the current page.
  • Click a coordinate or locate an element.
  • Enter text, upload files, and download files.
  • Decide how to close popups.
  • Add helper code when something is missing.
  • Turn reusable flows into domain skills.

This is not the style of traditional test scripts. It is the workflow of a browser agent.

How to choose

Choose Puppeteer when:

  • The project mainly runs in Node.js.
  • You only need Chrome or Chromium.
  • The task is screenshot, PDF generation, simple page scraping, or lightweight automation.
  • You want a simple API, fewer dependencies, and more manual control.
  • You rely deeply on Chrome DevTools Protocol.

Choose Playwright when:

  • You are building standard UI automation or E2E tests.
  • You need Chromium, Firefox, and WebKit coverage.
  • Your team’s main language may be Python, Java, or C#.
  • The page is a complex SPA with many asynchronous states and potential flaky tests.
  • You need codegen, Trace Viewer, test reports, and parallel testing.

Choose browser-harness when:

  • You are building or using AI agents.
  • You want the model to operate a real browser like a human.
  • The task steps are not fixed and require page-by-page judgment.
  • The target site changes often, or has many popups, iframes, and shadow DOM.
  • You want real web workflows handled by Claude Code, Codex CLI, or similar tools.

Conclusion

Playwright and Puppeteer are browser automation tools whose core goal is to let humans write reliable scripts. Puppeteer is lighter and closer to Chrome. Playwright is more complete and better for cross-browser testing and complex frontend applications.

browser-harness is a different direction. It is not designed to replace Playwright or Puppeteer for tests. It is designed to let AI agents control real browsers. It gives up some traditional script determinism in exchange for stronger adaptability in open-ended tasks.

So the answer is not to pick only one. Choose by task layer:

  • Test engineering: prefer Playwright.
  • Lightweight Chrome scripts: Puppeteer fits well.
  • AI agents doing work on the web: look at browser-harness.

References: