DEV Community

Cover image for We Built a Chrome Extension That Discovered 1,480 Agent-Ready Stores. Here's Exactly How It Works.
Benji Fisher
Benji Fisher

Posted on • Originally published at ucpchecker.com

We Built a Chrome Extension That Discovered 1,480 Agent-Ready Stores. Here's Exactly How It Works.

Wappalyzer didn't become a 3-million-user tool by being clever. It became essential by answering one question passively: what is this site built with?

We built something similar for a different question: is this store agent-ready?

The UCP Checker Chrome extension probes /.well-known/ucp on every storefront you visit and shows you the result in your toolbar. Green dot = valid UCP manifest. Gray dot = not detected. Zero clicks required.

Six weeks after shipping it, the extension has fed 1,480 unique domains into our monitoring pool — making it our single largest discovery source, ahead of our crawler, web submissions, and bulk checks combined. With a 98.4% verified rate — meaning almost every store it finds has a live, valid manifest.

This post is the full technical breakdown: how the detection works, what the permission model looks like compared to other ecommerce extensions, what the extension discovered, and what we're building next.

If you read our first post on running 180 agent shopping sessions across 11 models, this is the prequel — the detection layer that feeds the stores into the system those agents shop on.


The architecture: four components, one HTTP request

Compare this to how Wappalyzer works: it injects content scripts into every page, reads meta tags, checks JavaScript globals, and matches against a database of 1,000+ technology fingerprints. Or Shopify Theme Inspector, which hooks into Chrome DevTools, intercepts the Server-Timing header, and renders Liquid flame graphs.

UCP Checker does none of that. The entire detection mechanism is a single HTTP request.

1. Navigation listener

javascript// webNavigation.onCompleted fires on new domain
// No content scripts. No DOM injection. No page content access.
// Only completed navigations — not iframes, AJAX, or redirects.
chrome.webNavigation.onCompleted.addListener(handleNavigation);
Enter fullscreen mode Exit fullscreen mode

2. Manifest probe

javascript// One fetch() per domain visit. That's it.
const response = await fetch(
  `https://${domain}/.well-known/ucp`,
  { credentials: "omit" }  // No cookies, no session tokens, no auth headers
);
// Parse: HTTP status, response time, manifest structure
Enter fullscreen mode Exit fullscreen mode

This is architecturally closer to how a browser checks /.well-known/security.txt or /.well-known/openid-configuration than how Wappalyzer fingerprints a stack. No heuristic matching, no DOM analysis, no pattern library to maintain. Either the endpoint exists and returns a valid manifest, or it doesn't.

3. Badge system

Green dot  → valid UCP manifest found (store is agent-ready)
Gray dot   → no manifest detected (404/redirect)
No change  → error states (timeouts, network failures — stay silent)
Enter fullscreen mode Exit fullscreen mode

4. Optional telemetry

A toggle — on by default — labelled "Share anonymous uptime stats." When enabled, the extension sends the public manifest data to our monitoring pool:

json{
  "domain": "example-store.com",
  "status": "verified",
  "http_status": 200,
  "response_time_ms": 142,
  "manifest_version": "2026-01-23",
  "transports": ["mcp", "embedded"],
  "timestamp": "2026-03-02T14:23:01Z"
}
Enter fullscreen mode Exit fullscreen mode

No user ID. No session ID. No IP forwarding. No referrer. The credentials: "omit"flag ensures no cookies leave the browser. The domain enters the monitoring pool. The connection to the individual browse event is not retained.
That's the entire technical surface. Four components, one HTTP request per domain, zero page content access.


The permission model: why it's the narrowest in the category

This is where it gets interesting for anyone who's built or evaluated Chrome extensions.

Wappalyzer requires <all_urls> and content script injection — broad access in exchange for broad detection. Koala Inspector (250K+ users, Shopify competitive intelligence) needs similar DOM access to extract product data and sales estimates. Shopify Theme Inspector hooks into the network layer to read server timing headers.

Here's ours:

json{
  "permissions": ["activeTab", "webNavigation", "storage"],
  "host_permissions": ["https://*/.well-known/ucp*"]
}
Enter fullscreen mode Exit fullscreen mode

That's it.

Permission breakdown:
──────────────────────────────────────────────────────────────────
activeTab        → read current tab's URL (domain only)
                   Most restrictive tab permission Chrome offers
webNavigation    → detect domain navigations for auto-probe
storage          → save badge state locally (no cloud sync)
host_permissions → ONLY https://*/.well-known/ucp*
                   Cannot access any other path on any domain
──────────────────────────────────────────────────────────────────

What we DON'T request:
──────────────────────────────────────────────────────────────────
tabs             → would give access to all tab URLs
cookies          → would give access to session data
history          → would give access to browsing history
<all_urls>       → would give access to every page
content scripts  → would give access to page DOM
──────────────────────────────────────────────────────────────────

Enter fullscreen mode Exit fullscreen mode

The extension literally cannot read what's on the page you're viewing. It can only check whether a specific well-known URL exists. Auditable in Chrome's extension management page in seconds.

Manifest V3 and why it matters

The extension ships on Manifest V3 — Chrome's current platform with a stricter security model than V2. Service workers replace persistent background pages, host_permissions are declared explicitly, and CSP blocks inline script execution.

This matters because the December 2024 Chrome extension supply chain attack — which compromised extensions affecting 2.6 million users — exploited V2-era permission patterns that V3 structurally prevents. Our V3 architecture, combined with path-scoped host permissions, means even a compromised build couldn't read page content or access arbitrary URLs. The worst case is a bad probe to/.well-known/ucp — a public endpoint that returns public data.


What the extension discovered

Here's where the modest debugging tool turned into something bigger.

Discovery source        Domains    % of pool    Verified rate
─────────────────────────────────────────────────────────────
Browser extension         1,480      73.7%          98.4%
Crawler                     407      20.3%          87.2%
Web submissions             120       6.0%          64.2%
Bulk check                    1       0.0%            —
─────────────────────────────────────────────────────────────
Total                     2,008     100.0%          83.1%
Enter fullscreen mode Exit fullscreen mode

*98.4% verified *— nearly every store the extension finds has a live UCP manifest. Compare that to web submissions (64.2%), where people are testing domains that don't have UCP yet. The extension finds real merchants because it only fires on storefronts people are actually visiting.

The profile is distinctive: niche DTC brands that don't appear in any Shopify directory. Regional retailers in markets our crawler doesn't cover — Southeast Asia, Scandinavia, South America. The extension's geographic reach follows wherever our users browse.

This is the pattern Wappalyzer pioneered — crowdsourced technology detection at scale. But where Wappalyzer's telemetry feeds a commercial intelligence database (API pricing starts at $250/month for 5,000 lookups), ours feeds a public monitoring pool. The domain data powers our free benchmarks at UCP Checker, the UCP Alerts system, and the weekly adoption stats newsletter.

The extension users are building the map. And the map is open.

Privacy architecture

Extension-discovered domains are attributed only as "browser extension" in our data. We don't track which user discovered which domain, we don't store browsing sessions, and we don't build user profiles.

This is a fundamentally different approach to extension telemetry than the competitive intelligence tools. Koala Inspector and Commerce Inspector are designed to extract data from stores you visit — product listings, pricing, sales estimates. Our extension extracts nothing from the store's page. It checks a single public endpoint and reports the result.

The Hacker News thread: static vs. runtime

When we posted the extension to HN, the most substantive feedback wasn't about the extension itself. It was about what happens after validation.

The argument: a static manifest check tells you the endpoint exists and conforms to the spec. But it doesn't tell you what happens when an agent actually fetches content. A valid manifest can serve tool responses containing prompt injection, credential exfiltration patterns, or behavioural steering in product descriptions.

The commenter framed it as pairing manifest validation with runtime guardrails — classify and strip instructions in fetched content, detect exfiltration patterns, enforce policies before tool responses reach the LLM.

The timing was interesting. When we read that feedback, we were already building UCP Playground — which does exactly this from the observation side. Playground connects to a store's MCP server, runs live agent sessions, and shows you every JSON-RPC message flowing between the agent and the store.

The HN feedback didn't change our direction. It confirmed we were on the right track.

But it sharpened a distinction:

Static layer (UCP Checker + extension)
────────────────────────────────────────────────────────
Schema validation, capability declarations,
reachability, access policies.
Question: "Is this a valid, accessible UCP endpoint?"

Runtime layer (Playground — observes, doesn't enforce)
────────────────────────────────────────────────────────
Tool response content, instruction injection patterns,
checkout flow completeness, schema quality per tool.
Question: "What happens when an agent shops here?"
Enter fullscreen mode Exit fullscreen mode

The open question: should the runtime layer move from observation to enforcement? And who owns that — merchants sanitising their MCP responses, model providers extending safety layers to tool responses, or the UCP spec itself defining content security policies like CSP headers in browsers?

We think observability comes first (Playground), enforcement will follow as the ecosystem matures.


What we're building next

The extension currently does one thing. Here's what's on the table — and we'd genuinely like feedback on which of these matter to you.

Local discovery history

Your personal log of every domain you've visited and its UCP status — stored entirely in storage.local, never transmitted. A personal UCP audit trail. Browse stores all week, review which ones are agent-ready. No new permissions, no API calls.

Richer popup with grading

We already grade tool schemas A through F in UCP Playground. Surfacing that grade in the extension popup:

┌─────────────────────────────────────┐
│  ● allbirds.com          VERIFIED   │
│                                     │
│  Grade: B+    Response: 142ms       │
│  Transports: MCP, Embedded          │
│  Bot access: All allowed            │
│                                     │
│  [Open in Playground]  [Run Audit]  │
└─────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

One glance: green dot, B+ grade, 142ms, MCP + Embedded. Useful density for an agency evaluating agent readiness. Trade-off: additional API call per domain.

One-click Playground link

Visit allbirds.com → see green dot → click "Open in Playground" → watching Claude shop for running shoes. The detection-to-testing flow should be one click.

One-click alert setup

"I noticed this store has UCP" → "I want to know if it breaks" should be seamless. Deep-link from the popup to the alerts page with the domain pre-filled. Requires a logged-in account on ucpchecker.com — the extension just handles the link.

Quick audit run

A one-click "audit this domain" — the full scoring pipeline: schema quality, capability coverage, response times, bot access. Think of it as Lighthouse for UCP: right-click, audit, see the score.

What we're deliberately not building

DOM inspection or content analysis. Would require content script injection and broader permissions — a fundamentally different trust model. The extension stays manifest-only.

Automated testing or agent execution. That's what Playground is for. The extension detects. Playground tests.


Where the extension fits

Detection          Analysis            Testing             Monitoring
─────────          ────────            ───────             ──────────
Extension    →     UCP Checker    →    Playground     →    Alerts
"Is it ready?"     "How ready?"        "Does it work?"     "Did it change?"
Enter fullscreen mode Exit fullscreen mode

The extension sits at the top of the funnel — the lightest-touch interaction. A passive signal in your toolbar.

Compare to how Wappalyzer evolved: the extension was the entry point, but the value migrated to the API and intelligence platform. The extension stayed free and lightweight; the business built on the data it generated. Same pattern here — the extension generates discovery data, the platform turns it into developer tools.

1,480 domains later, the community is building the map by browsing.


What I'd love to hear

We're at a decision point with the extension. It's stable, lightweight, and trusted. The question is what to add — and what to leave out.

  • What would make you open the extension popup more often? A grade? Response time? Transport info?
  • Quick audit from the toolbar — would you use it, or just go to ucpchecker.com?
  • Runtime enforcement: who should own it? Merchant-side gateway, agent-provider responsibility, or protocol-level spec?
  • The permission model — does the narrow scope matter to you when evaluating extensions?

Drop a comment below or reach out at ucpchecker.com/contact. I read everything.

Try it:

Install the extension — free, no account, Manifest V3
UCP Checker — full domain analysis and benchmarking
UCP Playground — watch agents shop in real time
UCP Alerts — get notified when manifests change

Top comments (0)