Commerce paths answer shopping-agent User-Agents the way they answer a browser
What it checks
Issues paired live requests with a browser User-Agent and with two OpenAI agent User-Agents: ChatGPT-User and OAI-SearchBot. These are the two agents a purchase depends on. GPTBot is a training crawler and is read from robots.txt only. OAI-AdsBot visits only pages submitted as ads, so it is not probed.
The targets are the homepage, the first two other scanned pages, /cart, and the linked terms and privacy pages. The two sampled pages are not filtered by page type. A probe fails on under 60% of the browser’s text, or on a pay-per-crawl 402 with a price. It warns on a bot challenge (a challenge marker the browser response does not carry, a Cloudflare challenge header, or an Anubis proof-of-work page), or on any non-2xx where the browser got a 2xx: 403, 429, 503 and the rest.
The probe comes from the scanner’s address, so it is never the verified agent, and an edge can refuse it while admitting the real one. robots.txt is also read: a rule that disallows either agent on a sampled page or the cart fails the audit. These blocks live at the WAF or CDN edge, where a robots.txt-only audit cannot see them.
Why it matters
Falsifiable claim: OpenAI operates four separately-tokened agents with separately published IP ranges — OAI-SearchBot (ChatGPT search indexing), ChatGPT-User (user-initiated fetches, i.e. the shopper’s agent), GPTBot (training), OAI-AdsBot (ad landing-page validation). A PDP may return 403, 429, 503 or a bot-challenge interstitial to ChatGPT-User or OAI-SearchBot, while returning 200 to a browser UA. ChatGPT then cannot read live price and availability, and cannot follow the buy link. The product cannot be surfaced or transacted, whatever the feed quality. This block lives at the WAF/CDN edge and is therefore invisible to any audit that only parses robots.txt. Disproof condition: a site 403ing ChatGPT-User on its PDPs still showing live, accurate prices in ChatGPT.
What a scan can observe is narrower than the claim. The scanner’s request names ChatGPT-User but does not come from OpenAI’s published ranges, so a 403, a 429, a 503 or a challenge to it does not show that the real agent is refused (Limits). Those answers warn. A stub page and a priced 402 say something about the site whoever asks, so they fail.
Evidence
- OpenAI Bots / Crawler documentation — OpenAI (vendor-doc, verified 2026-10-17)
- Four distinct user agents with separate robots.txt tokens and separate published IP-range files: OAI-SearchBot (surfaces sites in ChatGPT search — openai.com/searchbot.json), OAI-AdsBot (validates ad landing pages — openai.com/adsbot.json), GPTBot (model training — openai.com/gptbot.json), ChatGPT-User (user-initiated actions: web visits and GPT Actions — openai.com/chatgpt-user.json). ChatGPT-User is the agent that fetches on a shopper’s behalf. Crucially these are separately controllable: blocking GPTBot does not block OAI-SearchBot or ChatGPT-User, and vice versa.
- OAI-SearchBot published IP ranges — OpenAI (dataset, URL verified 2026-08-20)
- Live JSON with creationTime (2026-01-02T11:00:00.000000) and a prefixes[] array of 35 IPv4 CIDR blocks (/24 to /28), e.g. 104.210.140.128/28 and 172.182.193.224/28. Machine-consumable, so an auditor can both spoof the documented UA and tell a merchant exactly which ranges to allowlist at the WAF.
- ACP Concepts: Security — Agentic Commerce Protocol (spec, URL verified 2026-08-20)
- All ACP endpoints use HTTPS and send/receive JSON. Bearer-token authentication between agent and seller; sellers retrieve tokens through the agent’s application. Mandatory headers: Authorization: Bearer
<token>, Content-Type: application/json, Accept: application/json.
Limits
- Every probe leaves the scanner’s own address with an OpenAI agent’s name in the User-Agent. It shows how the site answers a request that names the OpenAI agent. It does not show what the real OpenAI agent receives.
- Real bots are told apart by network or signature, not by the string. Cloudflare grants verified status to a bot that “declares who it is deterministically, through a cryptographic Web Bot Auth signature, a published IP list with a stable user-agent, or reverse DNS” (Cloudflare verified bots policy (verified 2026-10-19)). OpenAI publishes one IP-range file per bot, for example openai.com/gptbot.json and openai.com/chatgpt-user.json (OpenAI crawlers and user agents (verified 2026-10-19)). Google, whose crawlers this audit does not probe, illustrates the same rule: it documents a reverse-DNS check, or a match against its published IP ranges (Verifying Google crawlers and fetchers (verified 2026-10-19)). The scanner can present none of these.
- A CDN block of a request naming an OpenAI agent is ambiguous evidence. Without a signature, a published IP list or reverse DNS, the request is by definition not the verified bot (Cloudflare verified bots policy (verified 2026-10-19)), so an edge may treat it as unknown automated traffic. Cloudflare does ship managed rules that flag an unverified request naming Googlebot or Bingbot as a fake bot (Cloudflare fake bot managed rules (verified 2026-10-19)).
It documents no such rule for AI crawlers, and the scanner never sends either of those names. The analogy shows the mechanism exists. It is not evidence about the bots probed here. A refusal is consistent with the real bot being refused too. It does not prove it.
- A pass does not prove access either. A rule keyed on the verified bot’s identity rather than its string can refuse the real bot and still let the probe through.
- OpenAI tells merchants to allowlist its published ranges, and this audit’s fix says the same. A merchant who follows that advice admits the real agent and may still refuse the probe.
- An edge can answer the two differently by design. Cloudflare’s own example rules do exactly this:
(cf.bot_management.verified_bot)skips all remaining custom rules, so “Known good bots … bypass all custom rules”, and(cf.bot_management.score lt 30 and not cf.bot_management.verified_bot)blocks other automated traffic (Cloudflare Challenge bad bots (verified 2026-10-20)). Super Bot Fight Mode likewise gives “Definitely automated traffic”, “Likely automated traffic” and “Verified bots” separate responses (Cloudflare Super Bot Fight Mode (verified 2026-10-20)). Its rules can readcf.client.bot, which “Indicates whether the request originated from a known good bot or crawler” (Cloudflare cf.client.bot (verified 2026-10-20)). - For these reasons a challenge marker, and any non-2xx where a browser got a 2xx, warn rather than fail. This matches
access-crawl-control/ai-crawler-edge-parity. Two probe answers still fail. A stub under 60% of the browser text, with no challenge marker, is a different page body. A pay-per-crawl 402 carries the site’s price. Cloudflare says a crawler on content protected by pay per crawl “receives a HTTP status code 402” with the cost in a header, and that “To access this content, you must verify your AI crawler” (Cloudflare pay per crawl: Verify your AI crawler (verified 2026-10-20)). - An agent probe with no HTTP response is not compared. A request that was not sent, timed out or failed in transport says nothing about how the site treats the agent, so it is listed as not assessed with its cause. A redirect loop is an answer and warns like any other refusal. When only unassessed probes remain without a finding, the audit returns not applicable.
How it scores
Tier per evidence policy: scored — grade A meets the A/B bar required for scored audits.
A robots.txt rule that disallows either agent on a commerce path, a stub page, or a priced 402 fails at Critical. A challenge marker or another non-2xx to the probe warns at Medium. Everything else passes.
Example finding
A merchant sets User-agent: * / Allow: / and passes every robots.txt audit, but its Cloudflare Bot Fight Mode returns a 403 ‘Just a moment…’ interstitial to ChatGPT-User. The site scores 100 on competitor AI-readiness tools while every request that names ChatGPT-User is refused on the product pages. The audit warns: if the rule keys on the string, the real agent is refused too, and if it keys on verified identity, it is not.
A product page that answers the same request with a 200 carrying a fifth of the text fails. Second pattern: robots.txt blocks GPTBot only, but the WAF rule was written against a substring match on ‘GPT’ and therefore also blocks nothing visible in robots.txt while silently 429ing OAI-SearchBot.
Sources
- OpenAI crawlers and user agents — OpenAI, vendor-doc (verified 2026-10-19)
- OAI-SearchBot published IP ranges — OpenAI, dataset (verified 2026-08-20)
- ACP Concepts: Security — Agentic Commerce Protocol, spec (verified 2026-10-19)
- Chromium Dash — current Stable release (Mac) — Google (Chromium project), dataset (verified 2026-10-19)
- Verified bots policy — Cloudflare — Cloudflare, vendor-doc (verified 2026-10-19)
- Verifying Google crawlers and fetchers — Google, vendor-doc (verified 2026-10-19)
- Fake bot managed rules — Cloudflare WAF troubleshooting — Cloudflare, vendor-doc (verified 2026-10-19)
- Challenge bad bots — Cloudflare WAF custom rules — Cloudflare, vendor-doc (verified 2026-10-20)
- Super Bot Fight Mode — Cloudflare — Cloudflare, vendor-doc (verified 2026-10-20)
- cf.client.bot field — Cloudflare Rules language — Cloudflare, vendor-doc (verified 2026-10-20)
- Pay per crawl — Verify your AI crawler and Crawl pages — Cloudflare, vendor-doc (verified 2026-10-20)