EarShots.dev
Open navigation

How to make a website usable by browser agents

Build agent-usable forms with semantic HTML, explicit error states and stable controls. Test task completion separately from Lighthouse audits and WebMCP.

David ZeledonCEO, Founder of EarShots.Dev6 min readPublished Sources checked

Takeaways

Begin with a user task

Google describes browser agents inspecting visual rendering, the Document Object Model (DOM) and the accessibility tree. Make controls and interface states understandable through each of those views.[1]

Choose one important task: search a catalog, compare a product, request support, or book an appointment. Write down the steps and the information a user must provide. Then make every control and transition clear to a person using a keyboard, a screen reader, or a browser agent.

Good implementation foundations include:

Chrome’s Lighthouse Agentic Browsing audits examine a subset of accessibility checks important to machine interaction, along with stability signals such as layout shift. Accessibility supports people first; it also gives agents a more understandable representation of the interface.[2][3]

Implement and test an accessible form

Give a form an accessible name and explicit inputs

This small example uses native HTML rather than custom button or input roles. The label names the field, the hint explains the expected input and the required attribute exposes the constraint. The form submits a read-only search using GET. The destination is an example endpoint that your application must implement.

<form action="/search" method="get" aria-labelledby="search-title">
  <h2 id="search-title">Search documentation</h2>
  <label for="docs-query">Search terms</label>
  <input id="docs-query" name="q" type="search" required aria-describedby="search-hint" />
  <p id="search-hint">Enter a command, feature or error message.</p>
  <button type="submit">Search documentation</button>
</form>

Keep each id unique. A placeholder is not a replacement for the label. If validation runs in JavaScript, expose the invalid state with aria-invalid="true", associate the field with its error text and remove that state when the error is resolved. Validate submitted data on the server too. These are implementation recommendations, not a special agent protocol.[2]

Check failure and success states

State to testObservable result
Empty required searchSubmission is blocked and the required field can receive focus.
Valid searchThe request carries the entered query and the returned page shows results or an explicit no-results state.
Server failureThe page shows a recoverable error, retains useful input and does not announce success.
Pending requestThe interface indicates progress without moving controls. For state-changing requests, repeat activation does not apply the change twice.
Consequential actionThe person can review and confirm the action; the server checks permission before applying it.

For results updated without navigation, announce a concise status, such as the result count, through a status region. Keep the full results available in the page. Keep errors as visible text associated with the affected field. Do not rely only on a toast, color change or spinner. For a native page navigation, the returned page should contain a clear result heading.

Test controls by their accessible names

The following Python test uses Playwright's async application programming interface (API). Set FORM_PAGE_URL to a test page that contains the example form. Install the Python Playwright package and its Chromium browser before running it. The check finds the example controls by accessible name and tests native required-field validation. It does not submit a valid query or call the search endpoint.

import asyncio
import os
from playwright.async_api import async_playwright, expect

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        page = await browser.new_page()
        await page.goto(os.environ["FORM_PAGE_URL"])
        field = page.get_by_role("searchbox", name="Search terms")
        submit = page.get_by_role("button", name="Search documentation")
        await expect(field).to_be_visible()
        await submit.click()
        assert await field.evaluate("el => el.validity.valueMissing")
        await expect(field).to_be_focused()
        await field.fill("connection timeout")
        assert await field.evaluate("el => el.checkValidity()")
        await browser.close()

asyncio.run(main())

Run a separate end-to-end check against your actual search handler: submit a known query, verify the returned results, then test no results and a controlled server failure. Accessible-name selectors expose missing or ambiguous labels, but this script does not establish screen-reader compatibility or an agent's success at the whole task.

Use Lighthouse as a diagnostic

Chrome documents an Agentic Browsing category in Lighthouse with deterministic audits and a pass ratio. It does not produce a weighted score from 0 to 100. The category and WebMCP audits are experimental, and the documented setup depends on supported Chrome versions and WebMCP trial or flag settings.[3]

Use the report to find concrete issues, such as unnamed controls or problems in the accessibility tree. Record the browser version, Lighthouse version, page, and audit results so that later runs can be compared meaningfully. A passing report is evidence about the checks run on that page in that environment. It is not a guarantee that every agent can complete every task.

Describe content with relevant schema

We recommend applicable Schema.org structured data that describes visible page content, such as Article for an editorial article or Product for a product page. Include only supported facts and keep them consistent with the text.

Markup describes content; it does not name an unlabeled button, handle a form error or authorize an action. Validate the markup and test those interactions separately.

Where WebMCP fits

Web Model Context Protocol (WebMCP) is a proposed web standard for exposing structured tools to browser agents. A site can declare tools through annotated HTML forms or register tools through JavaScript. The goal is to make a capability and its inputs explicit, giving an agent a defined action to invoke with specified inputs.[4]

As of Chrome’s documentation checked on October 17, 2026, WebMCP is available through an origin trial and local development settings. Browser support and client support are still evolving. A browser or agent must visit the site to discover its page-level tools, so WebMCP does not function as a general search index for a website.[4]

WebMCP adds a new interface surface to secure. Chrome’s security guidance recommends marking read-only tools, identifying consequential actions that need confirmation, and treating externally sourced or user-generated data as untrusted where appropriate.[5]

Record task outcomes

Keep a test record for one complete task: starting URL, inputs, expected result, browser and agent versions, observed result and recovery failures. For consequential actions, verify confirmation and server-side authorization.

Record Lighthouse findings separately from task outcomes. If the workflow uses WebMCP, test tool inputs, failures and permission checks as part of the same task.

Sources

  1. Optimizing your website for generative AI features on Google Search. Google Search Central.
  2. A developer toolkit to make your website agent-ready. Chrome for Developers.
  3. Lighthouse agentic browsing scoring. Chrome for Developers.
  4. WebMCP. Chrome for Developers.
  5. WebMCP tool security. Chrome for Developers.

Last verified October 17, 2026.

Related guides

Industry Applications

Relevant Industries

Browse all industries →