If you sell on Shopify, most of your competitors probably do too, and their prices, discounts and stock levels are visible to anyone who opens their store. Monitoring apps turn that into dashboards, but you can collect the same data yourself, for exactly the stores and products you care about, and keep the history. This is price intelligence at the scale of a single store owner, and Shopify makes the first step easier than most platforms.
This guide covers where the data is, what to record per product, how to compare markets by country, and how to run it reliably.
Why build it yourself
Apps are quick to start, but they come with limits. They usually cap the number of competitors or products, refresh on their own schedule, and keep the raw history inside the app. A small collector of your own gives you:
- Your list of rivals, including small stores no app tracks.
- Your schedule, for example every few hours during a sale and once a day the rest of the time.
- Your data, in a spreadsheet or database you can join with your own sales and margins.
The trade-off is a little setup and the need to keep requests polite and steady, which is where proxies come in.
Where the data is: the public product JSON
Most Shopify storefronts publish their public catalogue in a machine-readable form:
/products.jsonlists products with their variants, in pages. Add?limit=250&page=2and so on to walk through a large catalogue./products/<handle>.jsonreturns one product, where the handle is the last part of the product URL./collections/<handle>/products.jsonlists the products in one collection, useful when you only follow a category.
Each variant carries the fields you need: price, compare_at_price (the crossed-out “was” price), available, sku and timestamps. This is far lighter than loading the rendered product page with its images and scripts, and it does not change when the store switches theme.
Not every store leaves it open. Some return an error or a password page, and headless storefronts may not expose it at all. In those cases, read the structured data embedded in the product page instead; we explain that approach in extracting JSON-LD instead of parsing HTML.
What to record per product
Track variants, not products. A T-shirt in five sizes is five variants, and a competitor often discounts only the sizes that are not selling.
Per variant, per check:
- Store, product handle, variant ID, SKU and variant title (size, colour).
priceandcompare_at_price.available(in stock or not).- The time of your check, the country you checked from and the currency shown.
Signals to derive:
- Discount depth: the gap between
compare_at_priceandprice, and when a discount starts and ends. - Price changes: every time a variant’s price moves, with the old and new value.
- Stock-outs: variants that switch to unavailable, often a sign of strong demand or supply problems.
- New and removed products: what the competitor launches and what it quietly drops.
Store only the changes plus a daily snapshot, and the history stays small even across dozens of stores.
Markets: the same store, different prices by country
Shopify Markets lets one store sell in many countries with local currencies and, often, different prices. Which market a visitor gets usually depends on their location, sometimes with a country subfolder such as /en-ca/ or a currency selector.
That matters for monitoring. If you collect everything from one server in one country, you only ever see that market. To compare what shoppers in the US, the UK and Germany pay:
- Request the store from an IP in each country you sell in, so the store picks the market a local shopper gets.
- Record the currency and price you received, not a converted value.
- Check one product by hand per market the first time, against the rendered page, to confirm the JSON you collect shows the local price for that store.
Country targeting is enough for most Shopify comparisons. City-level targeting only matters when a store changes delivery options or stock by region.
A minimal collector
The script below reads one store’s catalogue through a proxy and prints each variant’s price and stock. Run it per store and per country on a schedule, and write the rows to your database.
import time
import requests
PROXY = "http://customer-USERNAME-country-us:PASSWORD@p.shifter.io:443"
STORE = "https://competitor-store.example"
def fetch_catalogue(store):
page = 1
while True:
r = requests.get(
f"{store}/products.json",
params={"limit": 250, "page": page},
proxies={"http": PROXY, "https": PROXY},
timeout=30,
)
r.raise_for_status()
products = r.json().get("products", [])
if not products:
break
yield from products
page += 1
time.sleep(2) # stay polite between pages
for product in fetch_catalogue(STORE):
for v in product["variants"]:
print(product["handle"], v["id"], v["title"],
v["price"], v["compare_at_price"], v["available"])
Change country-us in the username to collect the same store as a shopper in another market sees it.
Proxy setup
| Job | Rotation | Targeting |
|---|---|---|
| Daily catalogue snapshot | Per request | Country of the market |
| Frequent checks on key products during a sale | Per request | Country of the market |
| Checking the cart or checkout total | Sticky session | Country of the market |
Shopify’s storefronts limit how fast one address can request pages, and a monitoring server hitting the same stores every day stands out quickly. Residential proxies with a new IP per request spread the checks across real household connections in the country you target, so the store answers as it would for a local shopper.
A few habits keep the collection stable:
- Pause a second or two between pages of the same store, and spread stores across the day.
- Check key products often and the full catalogue once a day; most prices do not move hourly. Our study of how fast online prices change helps you pick a sensible frequency.
- Treat an HTML response or a challenge page as a failure, not as data, and retry later.
How this fits a wider setup
Shopify stores are usually one part of the picture. If you also follow suppliers and marketplaces, our guide to proxies for dropshipping covers product research and supplier monitoring alongside competitor stores.
The bottom line
You do not need an app to watch competitor Shopify stores. Read the public product JSON, record each variant’s price, “was” price and stock with the time and country of the check, and keep only the changes. Collect each market from an IP in that country, and use rotating residential proxies so a daily schedule runs without blocks.