Can You Disable products.json on Shopify? The Honest Answer
Every Shopify store publishes its full product list at /products.json with no password. Here is exactly what it exposes, why you cannot switch it off, and what actually reduces the damage.
On this page
TL;DR: Every Shopify store publishes its entire product list at
/products.json: titles, descriptions, images, SKUs, stock levels and live prices, with no password. You cannot turn it off unless you are on Shopify Plus, because Shopify serves the file, not your theme. No app can close it either, whatever the App Store listing says. What you can control is the repeat crawling that follows, which is where the actual cost lives. Check what your store exposes in about fifteen seconds.
Open a new tab and type your store address followed by /products.json. Most Shopify owners have never done this. What comes back is your entire published catalog as machine-readable data: every product, every variant, every price, no login and no rate limit.
This is not a bug and it is not a leak. It is documented Shopify behaviour that powers plenty of legitimate integrations. But almost nobody who runs a store knows it is on, and the question that follows is always the same one: can I switch it off? This post gives the honest answer, which is mostly no, and then covers what is actually worth doing instead.
What /products.json returns
The endpoint returns your published products as JSON, thirty at a time by default and up to 250 per page with ?limit=250. Paging through it takes a few seconds even on a large catalog.
For each product you get:
- Title, handle, full description HTML, vendor, product type and tags
- Every image URL, at full resolution
- Every variant, with
price,compare_at_price,sku,barcode,weight,optionvalues andavailable
That last field is the one merchants tend to react to. available and, on many themes, the inventory quantity, tell an outsider what is selling. Combined with a crawl every few hours, someone can watch your stock move and work out your sales velocity per SKU without ever placing an order.
What it does not expose is worth stating just as clearly, because this gets exaggerated online. There are no customers, no orders, no email addresses, no draft or unpublished products, no cost prices, no margins and nothing from your admin. Your customer data is not involved. This is a commercial exposure, not a breach.
Why you cannot turn it off
Here is the part that surprises people, and the reason so many forum threads on this go nowhere.
/products.json is served by Shopify, not by your theme. When a request comes in for that path, Shopify's own infrastructure answers it directly. Your theme's Liquid never runs. Your app embeds never load. Anything you can edit in your theme editor sits downstream of a response that has already been sent.
Three consequences follow, and they are all worth knowing before you spend money on this:
- There is no setting in your admin. Not under Preferences, not under Sales channels. On Basic, Grow and Advanced there is no supported way to disable the endpoint.
- No app can block it. This is the important one. An app that promises to hide your product feed is either mistaken or misleading you. Every Shopify app that touches your storefront does so through a theme app extension, which is JavaScript running in a visitor's browser. A script that requests
/products.jsonnever loads your theme, never runs any JavaScript, and never encounters the app at all. That includes ours: Cordon cannot close this endpoint, and we will not tell you otherwise. - Shopify Plus is the exception. Plus merchants have access to custom rules at the CDN layer and can restrict or rate-limit the path there, above where the theme lives. If you are on Plus and this genuinely matters to your business, that is the conversation to have with your merchant success manager.
What about robots.txt?
Since Shopify allows editing robots.txt.liquid, this comes up constantly as a suggested fix. It is not one.
Robots.txt is a voluntary request. Googlebot honours it, Bingbot honours it, and the well-behaved commercial crawlers mostly honour it. A scraper built to collect your prices does not, and reading your robots.txt is a reasonable way for one to learn which paths you consider valuable. Adding a Disallow line changes nothing about what the server returns.
It is still worth editing for the crawlers that do obey it, which we cover in should you block AI crawlers on Shopify. Just do not file it under "problem solved".
So what actually matters
The single anonymous request is not what costs you money. Someone downloading your catalog once is roughly equivalent to them browsing your store with a notepad. Annoying, harmless, unstoppable.
What costs you money is the repetition, and repetition is a completely different technical problem, because it is visible.
- A competitor's repricing engine polling your feed every fifteen minutes so it can sit one euro under you, forever. We covered the mechanics in how to stop competitors scraping your Shopify prices.
- A counterfeit operation walking your product pages to lift images and descriptions onto a marketplace listing. That is catalog theft, and it needs far more than one request.
- Bulk crawlers that inflate your session numbers, wreck your conversion rate in analytics, and on a busy day compete with real shoppers for server time.
All three share a property the one-off download does not have: they come back. Something that comes back thousands of times leaves a pattern, and a pattern can be recognised and refused.
One of our merchants, a jewellery store, turned detection on and found that a single operation running from rented servers in Singapore accounted for 77% of all traffic to their store, 82,064 requests against their product pages. The owner had no idea. Nothing in the Shopify admin surfaces that, because as far as Shopify is concerned those were all just visits.
What is worth doing instead
In rough order of effort against payoff:
1. Look at your feed once, so you know what is in it. Check for anything genuinely sensitive that has crept into a product description or tag: internal SKU logic, supplier names, unreleased product names sitting on a published-but-unlinked product. Draft products are safe. Published-but-hidden ones are not: if it is published, it is in the feed, whether or not it appears in a collection.
2. Unpublish rather than hide. If a product should not be public, set it to unpublished rather than removing it from navigation. Anything published is in the feed regardless of whether a shopper could find it by clicking.
3. Edit robots.txt for the crawlers that listen. Ten minute job, real if modest benefit, no illusions about what it does.
4. Watch the networks your traffic comes from. Real shoppers arrive from home broadband and mobile carriers. Automated collection arrives from hosting providers: AWS, Alibaba Cloud, Tencent, Hetzner, OVH, and a long tail of VPS resellers. A single hosting network accounting for a large share of your traffic is the clearest signal there is, and it is the unit worth acting on. See what an ASN block is.
5. Refuse the repeat visitors, not the first one. Blocking by network, by country where you do not ship, and by behaviour turns a copycat's fifteen-minute refresh into an expensive problem for them. A determined operation can move to residential proxies and browse at human pace, which costs them real money and slows them from minutes to days. That gap is usually enough for a promotion to run before it gets matched.
6. Keep your sitemap. It lists every product URL you own, which feels like the same problem, but Google needs it and removing it costs you far more than it saves. The answer is controlling who walks the map, not burning the map.
Check your own store
You can inspect the feed yourself in a browser tab, and you should. If you want the fuller picture in one go, our free store scan checks what your feed returns, counts the product pages published in your sitemap, reads your robots.txt, and tells you whether anything is currently filtering your visitors. It takes about fifteen seconds, needs no signup, and tells you plainly which findings are fixable and which are not.
Cordon handles the part that is: the repeat crawling, the hosting networks, the proxies and the bots that come back to your store day after day. It cannot close /products.json, and now you know why nothing else can either.