Shopify products.json and collections.json: what bypasses the password page

Shopify's password page doesn't protect JSON endpoints. /products.json, /collections.json, and /search.json remain public. Here's what that means for your store.

Shopify products.json exposure — catalog endpoints public behind the password page

Shopify's password page gives store owners a sense of security during pre-launch. Visitors are blocked from browsing the storefront. But several JSON API endpoints remain publicly accessible regardless of password page status — and they expose your full product catalog, pricing, inventory levels, and collection structure to anyone who knows to look.

What the password page protects vs. what it doesn't

Shopify's password page works at the storefront rendering layer. When enabled, HTML page requests return a password gate. This covers:

  • Homepage, collection pages, product pages
  • Blog posts and static pages
  • Cart and account pages

It does not cover Shopify's built-in JSON endpoints, which are part of the platform's API surface and were never gated behind the password page by design:

  • /products.json — full product list with titles, descriptions, prices, variants, images, inventory quantities (if enabled)
  • /collections.json — all collections with titles and metadata
  • /collections/{handle}/products.json — products within a specific collection
  • /search.json?q= — search results, exposing products matching any query
  • /products/{handle}.json — full detail for any individual product

Verifying the exposure

While your store's password page is active, run:

curl -s https://your-store.myshopify.com/products.json | python3 -m json.tool | head -100

If you receive product data, the endpoint is public. You don't need any authentication token or cookie. Paginate through the full catalog:

curl -s 'https://your-store.myshopify.com/products.json?limit=250&page=1'

The limit parameter caps at 250 per page. For large catalogs, iterate pages until you receive an empty array.

What the data contains

A typical /products.json response includes per-product:

  • Title, handle (URL slug), description (HTML body)
  • All variants with SKUs, prices, compare-at prices, and weight
  • Inventory quantities per variant (if your store has inventory tracking enabled)
  • All product images with CDN URLs
  • Tags, product type, vendor, and publication dates

For a pre-launch store, this means your full product strategy — including pricing, SKUs, and launch timing — is visible to competitors and suppliers before you open.

Implications

  • Pre-launch catalog scraping — competitors can extract your complete catalog and pricing structure before your launch date.
  • Inventory intelligence — if inventory tracking is enabled, competitors can monitor your stock levels in real time.
  • Pricing strategy exposure — compare-at prices (showing original price for discounts) reveal your discount structure.
  • SEO competitive intelligence — product descriptions and tags reveal your SEO strategy before you're indexed.
  • Supplier/brand relationship inference — the vendor field exposes which brands or manufacturers you're working with.

Shopify's stance and platform limitations

Shopify considers these endpoints public by design. They're part of the Storefront API surface and are used by third-party apps, headless commerce frontends, and shopping aggregators. Shopify does not gate them behind the password page, and this behavior has not changed across platform versions.

There is no Shopify admin setting to disable these endpoints while keeping the store on the Shopify platform. Shopify Plus merchants have access to additional Storefront API controls, but basic endpoint gating is not available at lower plan tiers.

Partial mitigations

  • Delay adding products until close to launch — the most effective mitigation. Only add products to your Shopify admin days before launch, not weeks in advance.
  • Use draft status for sensitive products — products in Draft status do not appear in /products.json. Only publish products when ready to go live.
  • Disable inventory tracking for pre-launch SKUs — prevents quantity data from appearing in API responses.
  • Use a non-Shopify holding page — host a pre-launch page on a separate domain/platform and configure the Shopify store with no products until launch day.
  • Cloudflare Worker proxy — for Shopify Plus or custom storefront setups, route /products.json requests through a Cloudflare Worker that requires authentication or returns empty results.

Beyond the password page: ongoing exposure

The JSON endpoints remain public after launch too. This is expected behavior — they power many legitimate storefronts and apps. But if you have products you don't want publicly discoverable (wholesale-only items, private collections), be aware that they may appear in these endpoints unless they're in Draft status or excluded via a Shopify app that controls API visibility.

# Check what your search endpoint returns
curl -s 'https://your-store.myshopify.com/search.json?q=wholesale&type=product'

Common mistakes

  • Trusting the password page for full pre-launch confidentiality — it only blocks HTML storefront browsing.
  • Adding all products to Shopify months before launch — catalog visible to scraping the entire time.
  • Setting products to Hidden visibility but Published status — Hidden visibility removes from storefront navigation; Published status keeps them in the API. Use Draft to remove from API too.
  • Assuming your theme's custom routes are protected — even if you customize storefront routes, the *.json endpoints are Shopify platform endpoints and cannot be removed by theme code.

Orb44 scans Shopify stores for JSON endpoint exposure and catalog visibility misconfigurations as part of its e-commerce security checks.

FAQ

Does this affect Shopify Plus merchants differently?

Shopify Plus merchants can use the Storefront API with access token restrictions for headless setups. However, the built-in /products.json legacy endpoint remains public on Plus stores unless explicitly proxied or blocked at the CDN/infrastructure layer. This is an architectural limitation of the Shopify platform, not a plan-tier feature gap.

Can a Shopify app block these endpoints?

Apps run in the Shopify app sandbox and cannot intercept or modify the Shopify platform's own routing for *.json endpoints. An app can control its own data but not the core Shopify product/collection APIs. A Cloudflare Worker or reverse proxy in front of the store domain is the only practical way to gate these endpoints.

Is this a Shopify security vulnerability?

Shopify considers it documented behavior, not a vulnerability. The endpoints are by design. The exposure only becomes a practical problem when store owners expect the password page to provide broader confidentiality than it actually does. Understanding the limitation is the first step to working around it.

Orb44 Journal · all posts