Scraping Shopify products.json: De Endpoint Die Elke Winkel Blootlegt
Vergeet het parsen van HTML. Elke Shopify-winkel biedt je schone JSON aan op /products.json — volledige catalogus, prijzen, varianten, voorraad. Hier zijn de pagineringlimieten, de snelheidstrucs en hoe je het kunt omzetten in concurrentiebewaking.
Iedereen die e-commerce heeft gescraped kent de pijn: breekbare CSS-selectors, geneste wrapper-divs, lay-outs die veranderen en alles 's nachts breken. Shopify biedt je een uitweg. Bijna elke winkel gebouwd op Shopify stelt een openbaar /products.json endpoint bloot dat de volledige catalogus retourneert als schone, gestructureerde JSON — titels, handles, leveranciers, tags, varianten, prijzen, voorraadvlaggen en afbeeldingen. Geen HTML-parsing, geen headless browser. Deze gids behandelt hoe het endpoint werkt, de echte pagineringlimieten, een truc die het crawlen van grote winkels dramatisch sneller maakt, en hoe je het geheel kunt omzetten in concurrentieprijs- en voorraadbewaking.
Het endpoint op elke Shopify-winkel
Voeg /products.json toe aan het hoofddomein van een Shopify-winkel en je krijgt een JSON-lijst van producten. Het is dezelfde data die de storefront gebruikt, blootgelegd voor de Ajax API. Elk product heeft een stabiele numerieke id, een handle, vendor, product_type, tags, een array van variants (elk met zijn eigen prijs, SKU en available boolean), en afbeeldingen. Dat is alles waarvoor je normaal een productpagina zou scrapen, geleverd in één verzoek.
import requests
url = "https://store.example.com/products.json"
r = requests.get(url, params={"limit": 250, "page": 1}, timeout=15)
products = r.json()["products"]
print(len(products), products[0]["title"])
for v in products[0]["variants"]:
print(v["sku"], v["price"], v["available"])
Twee kanttekeningen vooraf. Shopify beperkt het openbare endpoint tot 250 producten per pagina — een limiet die je niet kunt overschrijden, ongeacht wat je doorgeeft, dus negeer advies om limit=1000000 in te stellen en alles in één keer te pakken. En een minderheid van de winkels schakelt het endpoint uit (aangepaste builds schakelen het soms uit), dus controleer op een geldige respons voordat je er een pijplijn omheen bouwt.
Pagineer tot het einde
Vanwege de limiet van 250 betekent een volledige catalogus dat je pagina's moet doorlopen totdat je een lege tegenkomt. De naïeve lus verhoogt page en stopt wanneer een pagina leeg terugkomt. Het is correct en prima voor kleine winkels — een winkel met een paar honderd producten is een paar verzoeken.
def all_products(base):
page, out = 1, []
while True:
r = requests.get(f"{base}/products.json",
params={"limit": 250, "page": page}, timeout=15)
batch = r.json()["products"]
if not batch:
break
out.extend(batch)
page += 1
return out

De 25x truc: vind eerst de laatste pagina
Sequentiële paginering is traag bij grote winkels omdat je niet kunt paralleliseren — je weet niet wanneer je moet stoppen, dus elke pagina wacht op de vorige. De oplossing is een binaire zoekopdracht: test paginanummers om de laatste niet-lege pagina te vinden, en verstuur dan alle paginaverzoeken tegelijkertijd. In een openbare benchmark tegen een winkel met 25.000 producten verspreid over 833 pagina's, verkortte dit een crawl van ongeveer 120 seconden tot ongeveer 12 bij de eerste run en rond de 5 zodra het laatste paginanummer was gecachet — een 25x versnelling. Leid de tests via roterende IP's zodat de uitbarsting van gelijktijdige verzoeken geen throttling veroorzaakt.
PROXY = "http://USER:PASS@gate.quantumproxies.io:8000"
proxies = {"http": PROXY, "https": PROXY}
def last_page(base, hi=1000):
lo, last = 1, 1
while lo <= hi:
mid = (lo + hi) // 2
r = requests.get(f"{base}/products.json",
params={"limit": 250, "page": mid},
proxies=proxies, timeout=15)
if r.json()["products"]:
last, lo = mid, mid + 1 # go higher
else:
hi = mid - 1 # go lower
return last
# then request pages 1..last_page concurrently
Zoals Rob Pike het verwoordde, zijn fancy algoritmen traag wanneer n klein is — voor een winkel met 200 producten, sla de binaire zoekopdracht over en loop gewoon. Het verdient zijn waarde bij catalogi in de duizenden, waar sequentiële paginering sleept.
Beperk de pull: collecties en enkele producten
Je wilt niet altijd de hele catalogus. Shopify stelt dezelfde JSON bloot op het collectieniveau: /collections/<handle>/products.json retourneert alleen de producten in die collectie, op dezelfde manier gepagineerd. Dat is de efficiënte weg wanneer je slechts één categorie volgt — sneakers, geuren, een enkel merk — in plaats van een hele winkel. En om één product te inspecteren, voeg .json toe aan de URL: /products/<handle>.json geeft het volledige record van dat product, inclusief elke variant en zijn voorraadvlag, wat handig is voor strakke herbevoorradingspolling op een specifieke SKU zonder de catalogus opnieuw te crawlen.
Door de twee te combineren houd je het verzoekvolume — en de bandbreedte — laag. Ontdek de catalogus eenmaal met het volledige endpoint, sla de handles op die je interesseren, en poll individuele producten of collecties op een strak schema. Dat patroon is het verschil tussen een monitor die opschaalt naar honderden winkels en een die stilletjes door je proxybudget brandt door catalogi opnieuw te downloaden die niet zijn veranderd.
Zet het om in concurrentiebewaking
De echte waarde is niet een eenmalige catalogusdump — het is het verschil over tijd. Maak een momentopname van de products.json van een concurrent op een schema, sleutel per variant id, en vergelijk runs om prijswijzigingen, nieuwe producten en herbevoorradingen te detecteren zodra ze gebeuren. Omdat available en price op elke variant staan, krijg je voorraad- en prijssignalen zonder een productpagina aan te raken.
def snapshot(base):
rows = {}
for p in all_products(base):
for v in p["variants"]:
rows[v["id"]] = {
"product": p["title"],
"sku": v["sku"],
"price": v["price"],
"available": v["available"],
}
return rows
# diff today's snapshot against yesterday's to flag price + stock moves
def changes(old, new):
for vid, cur in new.items():
prev = old.get(vid)
if prev and (prev["price"] != cur["price"] or prev["available"] != cur["available"]):
yield cur["sku"], prev, cur
Dit is de ruggengraat van concurrentieprijsbewaking en dropshipping onderzoek — beide leunen op hetzelfde momentopname-en-verschilpatroon over veel winkels tegelijk.
Krijg snelle datacenter proxies voor Shopify scraping

Welke proxies je echt nodig hebt
Het products.json endpoint is openbare JSON, geen geharde checkout flow, dus het is vergevingsgezind — maar scrape honderden winkels of hamer er één op een schema en je zult per-IP snelheidslimieten tegenkomen. Het economische antwoord is snelle datacenter proxies met rotatie: goedkoop, snel, en voldoende om verzoeken over IP's te verspreiden zodat geen enkele wordt beperkt. Reserveer residentiële IP's voor winkels die datacenterranges volledig blokkeren. Als een winkel products.json heeft uitgeschakeld en zijn catalogus verbergt achter gerenderde pagina's of botbescherming, is een Scraper API die voor je rendert en roteert de schonere uitweg. Onze gids over wanneer datacenter proxies winnen behandelt de beslissing.
Veelgestelde vragen
Hoe krijg ik alle producten van een Shopify-winkel als JSON?
Vraag /products.json aan op het domein van de winkel met ?limit=250&page=N en verhoog page totdat een pagina een lege productarray retourneert. Elke respons bevat maximaal 250 producten met hun varianten, prijzen, SKU's en voorraadvlaggen. Voor grote catalogi, zoek binaire de laatste pagina en haal pagina's gelijktijdig op.
Wat is de limiet op Shopify products.json?
Het openbare endpoint is beperkt tot 250 producten per pagina — de hoogste waarde die limit accepteert. Een groter getal doorgeven zal niet meer retourneren; je moet nog steeds door de catalogus bladeren. Dit is een harde Shopify-limiet, dus plan voor paginering in plaats van alles in één verzoek te proberen te halen.
Is het legaal om Shopify products.json te scrapen?
Het endpoint levert openbaar beschikbare productgegevens zonder inloggen, en Amerikaanse rechtbanken hebben over het algemeen het scrapen van openbare gegevens ondersteund. Dat gezegd hebbende, respecteer de servicevoorwaarden van de winkel, vermijd persoonlijke gegevens, en overbelast de server niet. Dit is algemene informatie, geen juridisch advies — controleer de specificaties voor jouw gebruiksgeval en jurisdictie.
Waarom retourneert products.json een 404 of lege respons?
Of de winkel is niet op Shopify, of de handelaar heeft het endpoint uitgeschakeld op een aangepaste build. Sommige winkels beperken ook herhaalde verzoeken van één IP, wat op een fout kan lijken. Bevestig dat de winkel Shopify is, roteer je IP, en voeg een vertraging tussen verzoeken toe voordat je aanneemt dat het endpoint verdwenen is.
Het products.json endpoint verandert Shopify scraping van een selector-worsteling in een schone JSON-pull: volledige catalogus, prijzen en voorraad in één URL, 250 per pagina, snel te crawlen met een binaire zoekopdracht, en triviaal om te vergelijken voor concurrentiebewaking. Ontdek eenmaal, poll de collecties en producten die ertoe doen, verspreid verzoeken over roterende datacenter IP's, en je kunt honderden winkels volgen op een schema zonder een enkele geblokkeerde run — geen HTML-parser, geen headless browser, geen breekbare selectors om te babysitten.