How AgentScore renders your pages in a real browser
Some AI agents read your HTML exactly as your server sends it. Others drive a real browser, run your scripts and look at the finished page. To score your site for both, AgentScore looks at your key pages twice: once as served, and once rendered in a headless browser. Here is exactly what that browser does, how we keep it safe, and what it deliberately never does.
Why render at all
Several checks only make sense as a comparison between the page before and after JavaScript. Content loads without JavaScript measures how much of the rendered page's text was already in the HTML: 70% or more passes, 30% to 70% is a warning, and less than that fails. Structured data describes your business and products, Product pages give price and stock in a form agents can read and Prices are in the page HTML all look for the same thing: data that only appears once scripts have run, which agents that read the HTML never see. Our guide to JavaScript-only content covers why that matters.
The Navigability checks need a rendered page too: whether a button is visible or a banner covers the screen depends on layout, which only exists once a browser has drawn the page.
Which pages we render
A scan renders at most four pages, each in its own browser session:
| Page | When it's rendered | What we look at |
|---|---|---|
| Home page | Every scan | The Navigability checks, image alt text, text and structured data after JavaScript, WebMCP tools |
| Product page | When we find one and it loads for a browser | The add-to-cart button, prices and product data after JavaScript, WebMCP tools |
| Pricing page | When we find one and it loads for a browser | The sign-up or buy button, prices after JavaScript, WebMCP tools |
| Checkout | Only when the HTML we were sent has no form fields and the checkout didn't send us back to the cart | The form fields a checkout builds with JavaScript |
The cart is fetched but not rendered. How AgentScore works explains how key pages are found and lists every page a scan requests.
The browser and its settings
- Chromium, headless. The engine behind Chrome, driven by Playwright.
- A fresh, isolated session for every page. No cookies or storage carry over, so every page sees a first-time visitor.
- A desktop screen, 1280 by 900 pixels, and a desktop Chrome user agent. These requests aren't signed, so your site treats them as it would any desktop visitor.
- No downloads and no service workers.
- Up to 20 seconds to load. We wait for the HTML to be parsed, then up to 5 more seconds for network activity to settle, so content built in the browser and consent banners have time to appear. Pages with chat widgets or analytics beacons rarely go quiet, so after 5 seconds we inspect whatever is there.
If a page fails to load or render, the checks that depend on it are marked "not tested" with a note explaining why. A render failure never counts as a fail.
What we inspect once it's drawn
On the home page, a script reads the finished page and records:
- Every visible button and link, and whether it has a name an agent can read: its text, an
aria-label, a referenced label, a title, or the alt text of an image inside it. - Every visible form field, and whether a label is connected to it. Fields with only placeholder text are counted separately, as a warning.
- The largest fixed or sticky element covering at least 15% of the screen, leaving out ordinary header bars along the top, and whether it has a clearly labelled button such as "Accept", "Close" or "No thanks".
- Things that look clickable but aren't buttons or links, the
<main>and<nav>landmarks, and images with noaltattribute.
On product and pricing pages, we look for the main action by its text, such as "Add to cart", "Buy now", "Start free trial" or "Sign up". We scroll it into view, check whether it's a real button or link, and ask the browser what element sits at its center. If that's a cookie banner rather than the button, an agent's click would land on the banner, and Agents can find and press your add-to-cart or sign-up button fails.
The WebMCP probe
WebMCP is a proposal for a browser feature, navigator.modelContext, that lets a page offer tools directly to an AI agent in the browser, such as "search products" or "add to cart". It isn't generally available in browsers yet, so sites that support it check for it first, roughly like this:
if ("modelContext" in navigator) {
navigator.modelContext.registerTool({
name: "search_products",
description: "Search the Northwind catalog by keyword",
inputSchema: { type: "object", properties: { query: { type: "string" } } },
execute: async ({ query }) => searchCatalog(query),
});
}
Before your scripts run, we add a stand-in for navigator.modelContext that writes down the name of every tool a page registers. A page that checks for WebMCP then registers its tools just as it would in a browser that supports it. We also look for forms marked up with a toolname attribute. We run the probe on the home, product and pricing pages and record names only: our stand-in never calls a tool. The result feeds Agents can use your site through MCP or WebMCP, where a missing setup is a warning, never a fail. Our guide to MCP and WebMCP for websites explains both.
Keeping the browser safe
A service that opens any URL it's given is a target: someone could submit an address that points at an internal network or a cloud metadata service. So every connection the scanner makes is checked:
- Only http and https. Other schemes are refused.
- Public addresses only. Every address a host name resolves to must be publicly routable. Private, loopback, link-local, shared, reserved, documentation and multicast ranges are refused, for IPv4 and IPv6, including IPv4 addresses hidden inside IPv6 ones. Cloud metadata addresses are always refused.
- Checked twice. Each request the page makes is checked before it goes out. Then all browser traffic, WebSockets included, passes through a small proxy that looks up the host name itself and connects only to addresses that pass. A host can't answer with a public address for the check and a private one for the connection.
- Limits on plain fetches. Requests made without the browser are checked again at every redirect, follow at most five redirects, time out after 15 seconds and stop reading at a size limit, 5 MB for an ordinary page.
What the browser never does
- It never clicks, types, signs in, adds to cart or submits a form. The only interaction is scrolling the main button into view to see what's on top of it.
- It doesn't dismiss your cookie banner. We measure the page as a first-time visitor meets it, because that's how most agents arrive.
- It doesn't pretend to be an AI agent. Comparisons between agents use plain requests, as described in Why our scanner sometimes wears other agents' names.
- It doesn't test a mobile layout, and it can't see a checkout that only opens with items in the cart. Checks that depend on one say "not tested" rather than guess.
Finishing a real task is a different job. That's what Ghost Agents do in the app: real AI agents run your journeys, stop at the payment form, and give you a step-by-step replay. The free scan marks Task completion as not tested and scores the other three categories.
To reproduce a finding: open the page in a private window at desktop size and compare "View source" with what's on screen. If the price, product details or button is on screen but not in the source, agents that read the HTML don't get it. If a banner sits over the button on arrival, a browser agent meets it first.