BlogFindings

Shopify AI crawlers: 38 stores served 1,112 products as open JSON

Lantad requested /products.json from the 49 hostnames in a 123 host sample whose home pages loaded Shopify storefront assets, on 9 September 2026. 39 answered HTTP 200, 38 of those parsed as a product array holding 1,112 products, and not one of the 49 robots.txt files mentions the path.

14 min read Lantad

On 9 September 2026 we requested the home page of 123 hostnames, once each, sent as LantadBot/1.0 with redirects followed. The list was hand built across direct to consumer retail, news publishing and developer infrastructure, and it was written before any platform detection ran, though it was deliberately stocked with consumer retail, so the share of it that turned out to be Shopify says nothing about the web and everything about how the list was drawn. 49 of the 123 home page responses referenced Shopify storefront assets. For each of those 49 we then requested two more things: /robots.txt, and /products.json. The second request is the one that is rarely made and it is the one this post is about, including what it means for anyone following the Shopify guide on this site.

In short

  • Shopify AI crawlers are almost always discussed as a robots.txt question, and on 9 September 2026 Lantad measured a second surface: 38 of 49 Shopify signalled hostnames returned a parseable JSON product array at /products.json, carrying 1,112 product objects between them.
  • None of the 49 robots.txt files Lantad read on 9 September 2026 contains the string products.json, while 33 of the 49 disallow /recommendations/products, so those files govern one JSON product endpoint and leave the other unnamed.
  • 889 of the 1,112 product objects carried a non-empty body_html field, holding 62,223 words of description prose once the tags were stripped, a mean of 70 words for each product that carried any.
  • Every one of the 1,112 product objects carried a price on its first variant, 1,066 carried tags and 985 carried a product_type, so the structured fields were near complete on a set where a fifth of the prose was missing.
  • OpenAI's file upload overview, read on 9 September 2026, instructs a merchant to push feeds to OpenAI via SFTP, and Lantad's own scanner requests no product endpoint at all: no file under core/src, worker/src or site/src references that path.
StepHostsNote
Hostnames requested123Home page, one attempt each
Home page answered HTTP 200906 hostnames returned a transport error
Referenced Shopify storefront assets49cdn.shopify.com, myshopify.com, Shopify.theme or shopify-features in the HTML
Served robots.txt at HTTP 20049Every one of the 49
Answered /products.json at HTTP 20039Of which 38 parsed as an object with a products array
Returned a product array381,112 product objects between them
Measured by Lantad on 9 September 2026. One GET per URL, sent as LantadBot/1.0 with redirects followed, a single attempt and a 20 second timeout. The 123 hostnames were a hand built list across direct to consumer retail, news and developer infrastructure, drawn before platform detection ran. 123 hostnames is 123 hostnames and not a survey of Shopify.

What Shopify AI crawlers can fetch without asking anyone

A page is a rendering decision. A theme takes the product record, chooses which of its fields to print, wraps them in whatever markup the designer preferred, and returns a document that a client then has to take apart again. Every scanner and every crawler that reads a storefront is doing that reconstruction, and the method behind this scanner is largely a description of how carefully it is done. The JSON endpoint skips the whole exercise. It returns the record.

Of the 49 hostnames whose home pages referenced Shopify storefront assets, 39 answered a GET of /products.json with HTTP 200. 38 of those returned a body that parsed as a JSON object with a products array in it. One returned HTTP 200 with an HTML document instead, which is a storefront answering a request for a path it does not serve rather than a refusal. Nine returned HTTP 404 and one returned HTTP 403.

One methodological note belongs here rather than in a caption, because it bounds every count in this post. No Shopify specific response header reached this client on any of the 123 requests, so the platform detection rested entirely on asset references in the returned HTML. That is a weaker signal than a header and it is why the endpoint request is treated as the test and the HTML reference only as the reason to run it. The single HTTP 403 was one attempt on one day from one network location and was not retried, so it is recorded as a refusal to this client rather than as a closed endpoint.

The nine 404s matter more than their count suggests, because one of them is a news publication whose home page loads Shopify assets for a merchandise store that does not live at the site root. The HTML signal found it and the endpoint test corrected it. That is the honest reading of the whole sample: an asset reference in a home page says something about how a page was built, and only the request settles what a path returns. It is the same discipline as reading a real storefront's response rather than its reputation, and it is why every figure here comes from a request this scanner made, under the crawler conduct policy it publishes, rather than from an inference about a platform.

  • Parsed as a product array 38 hosts HTTP 200, a JSON content type, and an object carrying a products array
  • HTTP 200, HTML body 1 host A document rather than a feed, so the path is served by the theme
  • HTTP 404 9 hosts Includes a publisher whose merchandise store is not at the site root
  • HTTP 403 1 host Refused to this client on this attempt, which was not retried
Response to one GET of /products.json, sent by Lantad as LantadBot/1.0 on 9 September 2026, across the 49 sampled hostnames whose home pages referenced Shopify storefront assets.

Thirty products is a page, not a catalogue

The 38 stores returned 1,112 product objects between them, and 35 of the 38 returned exactly 30. A number that repeats that precisely across unrelated businesses is not a fact about their catalogues, so we tested it rather than reporting it. On allbirds.com, everlane.com and taylorstitch.com we requested the same path again with a limit parameter of 250, and all three returned 250 products. We then asked for the second page at the same limit, and got 44, 250 and 250 respectively.

So 30 is a default page size and 1,112 is the size of the first page of 38 catalogues. Everlane and Taylor Stitch each published at least 500 products to an unauthenticated client in two requests, and the second page was still full, which means the real figure is higher than anything measured here. This post deliberately does not extrapolate it. The 1,112 is what 38 default requests returned and nothing else, which is the same reason a sitemap's declared URL count is reported separately from the links a crawl actually found.

That distinction changes what the endpoint is worth to a machine. A crawler working through HTML pays one request per product and has to find the product URLs first. A client using this path pays one request per 250 products and needs no discovery at all, which puts a mid sized catalogue inside a handful of round trips and well inside the kind of byte ceiling that Googlebot applies to a single document.

HostDefault requestlimit=250limit=250 and page=2
allbirds.com3025044
everlane.com30250250
taylorstitch.com30250250
Pagination probe run by Lantad on 9 September 2026. Three of the 38 hosts, each requested three times: the bare path, then with limit=250, then with limit=250 and page=2. Counts are products returned in the response body.

The robots.txt names one JSON endpoint and not the other

All 49 hostnames served a robots.txt at HTTP 200, and every one of the 49 carried a Sitemap line. The files are long: several run past 150 directive lines, and after masking the numeric shop identifier that appears inside the checkout and order paths, no two of the 49 were identical. They are clearly generated from a common template and then diverged.

What the template covers is specific. 46 of the 49 disallow /cart, 33 disallow /recommendations/products, and 19 disallow /search. None of the 49 contains the string products.json anywhere in the file, and none disallows any path ending in .json. So a file that is careful enough to name a JSON product recommendation endpoint, and careful enough to keep crawlers out of faceted collection sorts and preview theme identifiers, leaves the bulk product feed unnamed.

Unnamed is not neutral. RFC 9309 settles it in the crawler's favour: a path that no Disallow rule matches is allowed, so silence here is permission, and you can see the same evaluation on any file with the robots.txt tester on this site. That is worth holding next to what these files say about AI specifically. Six of the 49 name at least one of the 15 AI crawler tokens in this scanner's crawler directory in a user-agent line. The other 43 name none, which is the same shape found in the WordPress sample measured the day before and the same reason a wildcard group is doing more work than most site owners think. The difference on this platform is that the unaddressed crawler is not only being allowed to read the pages. It is being allowed to read the database view behind them.

Directive or stringFiles of 49What it governs
Sitemap:49Discovery of the page level URL list
Disallow: /cart46The basket path
Disallow: /recommendations/products33A JSON product recommendation endpoint
Disallow: /search19Internal search result pages
Any mention of products.json0The bulk product feed, named by nothing
Any Disallow of a .json path0No file blocks a JSON path by suffix
Directives counted by Lantad on 9 September 2026 across the 49 robots.txt files, each fetched once. Counts are the number of the 49 files containing a matching line.

How much product prose is actually in there

An open endpoint is only interesting if the thing behind it is worth reading, so we counted what came back. Across the 1,112 product objects, 889 carried a non-empty body_html field. Stripped of markup and entities, those descriptions came to 62,223 words, a mean of 70 words for every product that had any. The distribution is not even: on 19 of the 38 stores every single product carried a description, and on three of them, being kyliecosmetics.com, peakdesign.com and marinelayer.com, not one product did.

The structured fields tell a different story from the prose. All 1,112 objects carried a price on their first variant, 1,066 carried tags and 985 carried a product_type. So the fields a machine can act on without understanding anything were close to complete, while a fifth of the descriptions were absent, which is roughly the split you would expect when merchandising lives in the theme and the record holds only what the admin form required.

That gap is the interesting one for anyone thinking about prose parity, because it runs the opposite way to the usual finding. The common failure is a page whose text is present for a browser and missing for a crawler. Here the text is missing from the record and present on the page, put there by a theme section that the endpoint never sees. It is a reminder that a catalogue is stored in more than one place, and it sits alongside what we found when counting the JSON-LD on five captured pages: structured data in a page and a product record in a database are different assertions about the same object, and the vocabulary they are written in, such as the schema.org Product type, does not make them agree.

  • Carried a price on the first variant 1112 of 1,112 Every product object in the set
  • Carried tags 1066 of 1,112 96 percent of the set
  • Carried a product_type 985 of 1,112 89 percent of the set
  • Carried a non-empty body_html 889 of 1,112 62,223 words of prose, a mean of 70 per product that had any
  • Carried no description at all 223 of 1,112 Three stores accounted for 90 of these
Counted by Lantad on 9 September 2026 across the 1,112 product objects returned by 38 hosts. body_html was stripped of tags and HTML entities before words were counted.

OpenAI asks for the same data over SFTP

The reason to write this down now is that the same fields are being asked for elsewhere, through a much narrower door. OpenAI's commerce documentation sets out a product feed specification, and its file upload overview, read on 9 September 2026, states the delivery mechanism in one sentence: push feeds to OpenAI via SFTP. A merchant registers, prepares a file and transmits it. We covered the shape of that file when twelve of its required fields turned out not to be things a page publishes, and the delivery method is the part that has not changed.

So there are two routes for one set of facts. On the first, the merchant does nothing and the platform already publishes prices, variants, tags and most descriptions to any client that requests a path no robots.txt names. On the second, the merchant does integration work to hand a curated file to one company over an authenticated channel. The second route is the one being built, and it is the one that carries commercial terms, which is the honest reason it exists rather than an oversight in the first.

What a store owner should take from that is narrow and worth stating plainly. Publishing the endpoint is not a distribution strategy and closing it is not a protection strategy, because neither has been shown here to change what any engine does. Nothing in this measurement observed a single AI crawler requesting the path, and this post makes no claim that any of them do. What it establishes is that the data is reachable, which is a precondition for being cited rather than evidence of it, and precisely the sort of thing worth knowing before drawing conclusions about AI visibility from page level scans alone.

Two routes for the same product fields. The left route was measured by Lantad on 9 September 2026. The right route is described by OpenAI's file upload overview, read the same day. Neither route was observed being used by any AI crawler in this measurement.

What to check on your own store

All of this is checkable in a minute on a site you control, and the checks are worth running in order, because the first two decide whether the rest apply at all.

The first check is the only one that settles anything: request the path and read what comes back. If it returns a products array, everything else in this post applies to your store, and if it returns a document or a 404 then none of it does. The limit and page parameters answer the question the default request hides, which is how much of the catalogue one unauthenticated client can collect and how quickly. Reading a single body_html against the description a shopper actually sees is the check most likely to surprise a merchant, because a theme section that adds copy at render time leaves the record untouched, and the record is what a bulk client receives.

The last check is the one worth writing down somewhere durable. Adding a Disallow line closes the path to a crawler that reads robots.txt and to nothing else, so the decision is about which well behaved clients you want reading the catalogue in bulk, not about whether the data can be taken. Both answers are defensible on those terms.

The inconvenient part of the finding belongs to this scanner rather than to the stores. Lantad does not request this path. No file under core/src, worker/src or site/src references it, which was verified in the repository on 9 September 2026, so every grade this product has ever issued about a storefront was formed from HTML pages alone. That is a real limit and it points at a real gap: a page level scan tells you what a crawler reads from a document, and it says nothing about a bulk endpoint sitting one path away. Seeing what a page returns to GPTBot remains the right first question, and it is now visibly not the only one. The same caution applies to the wider claim that an agent ready storefront performs better: that result was measured on pages and tasks, not on feeds.

Sample Illustrative, not a measurement of any real site.

  • Request /products.json on your own domain A JSON body with a products array means the endpoint is live. HTML or a 404 means it is not served at that path.
  • Add ?limit=250 and then &page=2 Shows how much of the catalogue one unauthenticated client can collect, rather than the default first page.
  • Search your robots.txt for products.json None of the 49 files measured on 9 September 2026 contained the string. A path no Disallow rule matches is allowed.
  • Read one body_html field Compare it with the description a shopper sees. Text added by a theme section is not in the record.
  • Decide deliberately, then write it down Open and closed are both defensible. An unexamined default is the only answer this measurement argues against.
Checks a store owner can run without any tool, in the order that decides whether the later ones apply. Not a measurement of any site.

Written by

Lantad

Published .

Advice about Shopify AI crawlers nearly always ends in the same place, which is the robots.txt file and which tokens it names. That is a reasonable place to end if the only thing an AI crawler can do with a storefront is request HTML pages and read what a theme rendered. It is not the only thing on offer. A storefront on this platform also answers a bulk JSON request for its catalogue, in one round trip, with prices and variants and descriptions already parsed, and it answers it to any client that asks.

Common questions

Do AI crawlers fetch /products.json from Shopify stores?

This measurement does not answer that and does not claim to. Lantad requested the path itself on 9 September 2026 and recorded what 49 hostnames returned. No crawler request was observed, no access log was read, and no vendor documentation examined here names the path. What the measurement establishes is that the data is reachable by an unauthenticated client and that no robots.txt in the sample disallows it, which is a statement about availability and not about use.

Does robots.txt block products.json on a Shopify store?

Not on any of the 49 files Lantad read on 9 September 2026. None of them contains the string products.json and none disallows a path by a .json suffix, while 33 of the 49 do disallow /recommendations/products, which is a different JSON product endpoint. Under RFC 9309 a path that no Disallow rule matches is allowed, so an unnamed path is an open one. A store owner who wants it closed has to add the rule, and should expect that a robots.txt rule is a request rather than an enforcement.

Why did 1,112 products come from 38 stores?

Because 35 of the 38 returned exactly 30 products, which is the default page size rather than the size of their catalogues. A follow-up probe on allbirds.com, everlane.com and taylorstitch.com returned 250 products each when asked with a limit of 250, and a second page returned 44, 250 and 250. The true catalogue totals are therefore higher than 1,112 and were not measured, so no figure for them appears in this post.

Does Lantad check this endpoint when it scans a store?

No. Verified in the repository on 9 September 2026: no file under core/src, worker/src or site/src references products.json, so the scanner has never requested it and no grade it has issued reflects it. Lantad measures what a crawler can read from HTML documents, which is a narrower question than what a storefront publishes in total. That limit is stated here rather than in a footnote because a scan that does not look at something cannot report on it.

See what AI can read on your site

Run a free scan and get a graded report of exactly what AI crawlers can and cannot read, with ranked fixes.