Marktonderzoek automatiseren: Shopify scrapen met Python

Laatst bijgewerkt op July 9, 2026
Marktonderzoek automatiseren: Shopify scrapen met Python

Shopify’s /products.json-endpoint is een van de best bewaarde geheimen in ecommerce-data. Voeg het toe aan elke Shopify-store-URL en je krijgt gestructureerde JSON terug—geen API-sleutels, geen authenticatie, geen gedoe met het scrapen van diep geneste HTML.

Ik werk aan het team van de Thunderbit Official Website, dus ik denk dagelijks na over hoe mensen data van het web halen. En Shopify-scraping komt daarbij voortdurend terug—sales teams die concurrentieprijzen volgen, ecommerce-operations die productcatalogi benchmarken, inkoopteams die nieuwe leveranciers zoeken. Met 4,82 miljoen actieve merchants op Shopify en een marktaandeel van ongeveer 30% van de Amerikaanse ecommerce-markt, is de hoeveelheid productdata die je kunt scrapen enorm.

In deze gids nemen we het hele proces door: wat dit endpoint teruggeeft, hoe je door duizenden producten pagina voor pagina loopt, hoe je rate limits omzeilt zonder geblokkeerd te worden, en hoe je Shopify’s geneste JSON netjes omzet naar een overzichtelijke CSV- of Excel-bestand met pandas. Ik behandel ook endpoints waar bijna niemand het over heeft (/collections.json, /meta.json) en laat een no-code alternatief zien voor iedereen die Python liever overslaat.

Wat is Shopify’s /products.json-endpoint (en waarom maakt het scrapen zo makkelijk)?

Elke Shopify-store heeft een openbaar endpoint op {store-url}/products.json dat gestructureerde productdata teruggeeft. Geen API-sleutels. Geen OAuth. Geen enkele vorm van authenticatie. Je voegt letterlijk /products.json toe aan de store-URL en krijgt een JSON-array terug met elk product uit de catalogus.

Probeer het zelf: open allbirds.com/products.json of zoologistperfumes.com/products.json in je browser. Je ziet keurige, gestructureerde JSON met producttitels, prijzen, varianten, afbeeldingen, tags—alles.

Vergelijk dat eens met de alternatieve aanpak: Shopify-HTML parsën. Die pagina’s zijn diep genest, verschillen per store en veranderen zodra een merchant zijn thema aanpast. Dit is waar je dan mee te maken krijgt:

De HTML-aanpak (pijnlijk):

<div class="product-card__info">
  <h3 class="product-card__title">
    <a href="/products/classic-blue-jeans">Classic Blue Jeans</a>
  </h3>
  <span class="price price--on-sale" data-product-price>$149.00</span>
</div>

De JSON-aanpak (netjes):

{
  "title": "Classic Blue Jeans",
  "handle": "classic-blue-jeans",
  "vendor": "Hiut Denim",
  "variants": [{"price": "149.00", "sku": "HD-BLU-32", "available": true}]
}

JSON wint op consistentie, betrouwbaarheid en parse-gemak. Het endpoint ondersteunt ook twee belangrijke query-parameters—?limit= (tot 250 producten per pagina, standaard 30) en ?page= voor paginering—en die gebruiken we hieronder volop in de code.

Belangrijk onderscheid: dit is een publiek storefront-endpoint, niet de Shopify Admin API. De Admin API vereist toegangstokens van de store-eigenaar en geeft orderdata, voorraadniveaus en klantinformatie. Het openbare /products.json-endpoint bevat alleen read-only productdata die iedereen kan inzien. Dat verschil leg ik later uitgebreider uit, want daarover bestaat enorm veel verwarring in fora.

Een kanttekening: niet elke Shopify-store stelt dit endpoint beschikbaar. In mijn tests gaf ongeveer 71% van de stores geldige JSON terug (allbirds.com, gymshark.com, colourpop.com, kyliecosmetics.com werken allemaal), terwijl sommige custom configuraties een 404 teruggeven (hiutdenim.co.uk, bombas.com). De snelle check is simpel: bezoek {store-url}/products.json in je browser en kijk wat er gebeurt.

Waarom Shopify scrapen met Python? Belangrijkste zakelijke use cases

Waarom de moeite nemen? ROI. 81% van de Amerikaanse retailers gebruikt inmiddels geautomatiseerd prijs scrapen voor concurrentieanalyse, tegenover slechts 34% in 2020. En onderzoek laat zien dat een 1% verbetering in prijsstrategie gemiddeld leidt tot 11,1% meer winst. Die data is dus echt geld waard.

Dit zijn de use cases die ik het vaakst zie:

Use caseWie heeft er baat bijWat je krijgt
Prijsmonitoring van concurrentenEcommerce-operations teamsVolg prijswijzigingen, kortingen en vergelijkprijzen in concurrentencatalogi
Productonderzoek & sourcingInkoop / merchandisingVergelijk producteigenschappen, varianten, materialen en beschikbaarheid
LeadgeneratieSales teamsHaal leveranciersnamen, merkdata en contactinformatie uit store-catalogi
Markt- en categorieanalyseMarketing teamsBegrijp productmix, tags, collectie-opbouw en positionering
Voorraad- en beschikbaarheidsmonitoringSupply chain teamsVolg de voorraadstatus per variant (available: true/false) in de tijd
Detectie van nieuwe productenProduct teamsVolg created_at-timestamps om nieuwe launches van concurrenten te spotten

Python is hier een logische keuze. 69,6% van de scraping-ontwikkelaars gebruikt Python als primaire taal, en het ecosysteem—requests voor HTTP, pandas voor datamanipulatie, httpx voor async—maakt het eenvoudig om van “ik heb een URL” naar “ik heb een spreadsheet” te gaan in minder dan 80 regels code.

Volledige products.json-veldreferentie: elk veld uitgelegd

De meeste tutorials laten je alleen title, id en handle zien en gaan daarna verder. Shopify’s JSON-response bevat meer dan 40 velden over producten, varianten, afbeeldingen en opties. Weten wat er beschikbaar is vóórdat je code schrijft, bespaart je later opnieuw scrapen.

Ik heb deze referentie samengesteld uit live /products.json-responses die ik op 16 april 2026 heb opgehaald. De structuur is consistent bij alle stores die dit endpoint beschikbaar stellen.

Velden op productniveau

VeldDatatypeVoorbeeldwaardeZakelijke toepassing
idInteger123456789Unieke product-ID voor deduplicatie
titleString"Classic Blue Jeans"Productnaam voor catalogi en vergelijkingen
handleString"classic-blue-jeans"URL-slug—bouw productlinks als {store}/products/{handle}
body_htmlString (HTML) of null

Our best-selling...

Productbeschrijving voor contentanalyse en SEO-onderzoek
vendorString"Hiut Denim"Merk-/leveranciersnaam voor leadgen of sourcing
product_typeString"Jeans"Categorie-indeling voor marktanalyse
created_atISO-datetime"2024-01-15T10:30:00-05:00"Volg wanneer producten zijn toegevoegd (nieuwe launch detectie)
updated_atISO-datetime"2025-03-01T08:00:00-05:00"Detecteer recente cataloguswijzigingen
published_atISO-datetime"2024-01-16T00:00:00-05:00"Zie wanneer producten live gingen op de storefront
tagsArray van strings["organic", "women", "straight-leg"]Analyse van keywords/tags voor SEO, categorisatie en trendspotting
variantsArray van objecten(zie variantvelden hieronder)Prijs, SKU en beschikbaarheid per variant
imagesArray van objecten(zie afbeeldingsvelden hieronder)Productafbeeldingen voor catalogi en visuele analyse
optionsArray van objecten[{"name": "Size", "values": ["S","M","L"]}]Begrijp productconfiguraties (maat, kleur, materiaal)

Velden op variantniveau (genest onder elk product)

VeldDatatypeVoorbeeldToepassing
idInteger987654321Unieke variant-ID
titleString"32 / Blue"Weergavenaam van de variant
skuString"HD-BLU-32"SKU-matching voor voorraadsystemen
priceString"185.00"Prijsmonitoring (let op: dit is een string, dus cast naar float voor berekeningen)
compare_at_priceString of null"200.00"Oorspronkelijke prijs—onmisbaar voor kortingsanalyse
availableBooleantrueVoorraadbeschikbaarheid (de enige publieke voorraadindicator)
weightFloat1.2Analyse voor verzending/logistiek
option1, option2, option3String"32", "Blue", nullIndividuele optiewaarden
created_at, updated_atISO-datetime—Wijzigingen op variantniveau volgen

Velden op afbeeldingsniveau

VeldDatatypeVoorbeeldToepassing
idInteger111222333Unieke afbeelding-ID
srcString (URL)"https://cdn.shopify.com/..."Directe downloadlink voor afbeeldingen
altString of null"Front view of jeans"Alt-tekst voor toegankelijkheidsanalyse
positionInteger1Volgorde van afbeeldingen
width, heightInteger2048, 2048Afmetingen van de afbeelding

Wat er NIET in het publieke endpoint zit

Een belangrijke valkuil: inventory_quantity is NIET beschikbaar in openbare /products.json-responses. Dit veld is in december 2017 verwijderd uit publieke JSON-endpoints om veiligheidsredenen. De enige voorraadindicator die je krijgt is het booleaanse available-veld per variant (true of false). Voor echte voorraad-aantallen heb je de geauthenticeerde Admin API nodig met credentials van de store-eigenaar.

Bekijk deze tabel voordat je code schrijft en beslis welke velden relevant zijn voor jouw use case. Doe je prijsmonitoring, dan heb je variants[].price, variants[].compare_at_price en variants[].available nodig. Doe je leadgeneratie, focus dan op vendor, product_type en tags. Filter daarop—je CSV wordt veel overzichtelijker.

Verder dan products.json: Collections, meta en andere Shopify-endpoints

Bijna geen enkele vergelijkende tutorial noemt deze endpoints. Toch zijn ze essentieel voor serieuze competitive-intelligence-werkzaamheden.

/collections.json — alle storecategorieën

Geeft elke collectie (categorie) in de store terug, inclusief titels, handles, beschrijvingen en productaantallen. Ik heb dit geverifieerd op zoologistperfumes.com, allbirds.com en gymshark.com—allemaal gaven geldige JSON terug.

{
  "collections": [
    {
      "id": 308387348539,
      "title": "Attars",
      "handle": "attars",
      "published_at": "2026-03-29T12:20:32-04:00",
      "products_count": 1,
      "image": { "src": "https://cdn.shopify.com/..." }
    }
  ]
}

Wil je begrijpen hoe een concurrent zijn catalogus indeelt? Dan is dit het endpoint dat je nodig hebt.

/collections/{handle}/products.json — producten per categorie

Geeft producten terug die gefilterd zijn op een specifieke collectie. Dezelfde JSON-structuur als /products.json, maar dan beperkt tot één categorie. Dit is cruciaal voor scraping op categorieniveau—bijvoorbeeld als je alleen de "Sale"- of "New Arrivals"-collectie van een concurrent wilt volgen.

/meta.json — metadata op storeniveau

Geeft storenaam, beschrijving, valuta, land en—het belangrijkste—published_products_count terug. Met dat aantal kun je vooraf exact berekenen hoeveel paginapunten je nodig hebt: ceil(published_products_count / 250). Geen eindeloos doorklikken meer totdat je een lege response krijgt.

Welk endpoint moet je gebruiken?

Wat je wiltEndpointAuthenticatie nodig?
Alle producten (publiek)/products.jsonNee
Producten in een specifieke categorie/collections/{handle}/products.jsonNee
Store-metadata + productaantal/meta.jsonNee
Alle collecties (categorieën)/collections.jsonNee
Order-/verkoopdata (alleen eigen store)Admin API /orders.jsonJa (API key)
Voorraadhoeveelheden (alleen eigen store)Admin API /inventory_levels.jsonJa

De terugkerende forumvraag—"Kan ik zien hoeveel units een concurrent heeft verkocht?"—heeft een kort antwoord: nee. Niet via publieke endpoints. Verkoopdata en voorraadhoeveelheden vereisen de geauthenticeerde Admin API, wat betekent dat je toegang van de store-eigenaar nodig hebt. Publieke endpoints geven alleen catalogusdata.

shopify-data-access-methods.webp

Shopify scrapen met Python: stap-voor-stap setup

  • Moeilijkheidsgraad: Beginner
  • Benodigde tijd: ~15 minuten (setup + eerste scrape)
  • Wat je nodig hebt: Python 3.11+, pip, een terminal en een Shopify-store-URL om te scrapen

Stap 1: Python en vereiste libraries installeren

Zorg dat je Python 3.11 of nieuwer hebt geĂŻnstalleerd (pandas 3.0.x vereist dat). Installeer daarna de twee libraries die we nodig hebben:

pip install requests pandas

Voor export naar Excel heb je ook nodig:

pip install openpyxl

Voeg bovenaan je script deze imports toe:

import requests
import pandas as pd
import time
import random
import json

Je zou geen importfouten moeten zien wanneer je het script runt. Als pandas een versie-fout geeft, upgrade Python dan naar 3.12.

Stap 2: Productdata ophalen uit /products.json

Hier is een eenvoudige functie die een store-URL neemt, het endpoint aanroept en de geparste JSON teruggeeft:

def fetch_products_page(store_url, page=1, limit=250):
    """Haal één pagina met producten op uit een Shopify-store."""
    url = f"{store_url.rstrip('/')}/products.json"
    params = {"limit": limit, "page": page}
    headers = {
        "User-Agent": "Mozilla/5.0 (compatible; ProductResearch/1.0)"
    }
    
    response = requests.get(url, params=params, headers=headers, timeout=30)
    response.raise_for_status()
    return response.json().get("products", [])

Belangrijke details:

  • limit=250 is het maximum dat Shopify per pagina toestaat. De standaard is 30, dus dit expliciet instellen vermindert het aantal requests tot wel 8x.
  • User-Agent-header: stel altijd een realistische header in. Requests zonder User-Agent maken meer kans om Shopify’s anti-bot-systemen te activeren.
  • timeout=30: laat een request niet eindeloos hangen.

Test het met een bekende store:

products = fetch_products_page("https://allbirds.com")
print(f"Fetched {len(products)} products")
print(f"First product: {products[0]['title']}")

Je zou iets moeten zien als: Fetched 250 products en de titel van het eerste product.

Stap 3: Paginering verwerken om alle producten te scrapen

Eén request levert maximaal 250 producten op. De meeste stores hebben er meer dan dat (Allbirds heeft 1.420+). Je moet dus door de pagina’s lopen totdat je een lege response krijgt.

def scrape_all_products(store_url, delay=1.0):
    """Scrape alle producten uit een Shopify-store met paginering."""
    all_products = []
    page = 1
    
    while True:
        print(f"Fetching page {page}...")
        products = fetch_products_page(store_url, page=page, limit=250)
        
        if not products:
            print(f"No more products. Total: {len(all_products)}")
            break
        
        all_products.extend(products)
        print(f"  Got {len(products)} products (total so far: {len(all_products)})")
        page += 1
        
        # Wees netjes: wacht tussen requests
        time.sleep(delay + random.uniform(0, 0.5))
    
    return all_products

Wanneer products leeg terugkomt, ben je aan het eind.

De time.sleep() met een kleine willekeurige variatie houdt je onder Shopify’s informele rate limit (~2 requests/seconde).

Pro tip: als je eerst /meta.json hebt opgehaald, weet je al hoeveel producten er zijn en kun je exact berekenen hoeveel pagina’s je nodig hebt: pages = ceil(product_count / 250). Zo voorkom je de extra lege request aan het einde.

Stap 4: De velden selecteren die je nodig hebt

Nu je alle producten als een Python-lijst met dictionaries hebt, kun je alleen de velden extraheren die je nodig hebt. Hieronder een voorbeeld dat de meest gebruikte velden voor prijsmonitoring ophaalt:

def extract_product_data(products):
    """Haal belangrijke velden uit producten en flatten de varianten."""
    rows = []
    for product in products:
        for variant in product.get("variants", []):
            rows.append({
                "product_id": product["id"],
                "title": product["title"],
                "handle": product["handle"],
                "vendor": product.get("vendor", ""),
                "product_type": product.get("product_type", ""),
                "tags": ", ".join(product.get("tags", [])),
                "created_at": product.get("created_at", ""),
                "variant_id": variant["id"],
                "variant_title": variant.get("title", ""),
                "sku": variant.get("sku", ""),
                "price": variant.get("price", ""),
                "compare_at_price": variant.get("compare_at_price", ""),
                "available": variant.get("available", ""),
                "image_url": product["images"][0]["src"] if product.get("images") else ""
            })
    return rows

Dit maakt één rij per variant—het meest bruikbare formaat voor prijsvergelijking, omdat één product zoals "Classic Blue Jeans" 12 varianten kan hebben (6 maten × 2 kleuren), elk met een eigen prijs en beschikbaarheidsstatus.

Gescrapete Shopify-data exporteren naar CSV en Excel met pandas

Elke andere Shopify-scraping tutorial dumpt ruwe JSON naar een bestand en noemt het klaar. Prima voor developers. Vrij nutteloos voor de ecommerce-analist die vrijdag een spreadsheet nodig heeft.

Het probleem: Shopify’s JSON is genest. Eén product kan een dozijn varianten bevatten, elk met een eigen prijs, SKU en beschikbaarheid. Dat omzetten naar rijen en kolommen kost wat werk in pandas.

Geneste JSON omzetten naar een nette tabel

Er zijn twee aanpakken, afhankelijk van je use case:

Optie A: één rij per variant (beste voor prijsmonitoring en voorraadtracking)

# Gebruik de extract_product_data-functie uit Stap 4
products = scrape_all_products("https://allbirds.com")
rows = extract_product_data(products)
df = pd.DataFrame(rows)

print(f"DataFrame shape: {df.shape}")
print(df.head())

Dit geeft je een platte tabel waarin elke rij een unieke combinatie van product en variant is. Een store met 500 producten en gemiddeld 4 varianten per product levert een DataFrame van ongeveer 2.000 rijen op.

Optie B: één rij per product-samenvatting (beste voor catalogusoverzichten)

def summarize_products(products):
    """Eén rij per product met min/max prijs over de varianten."""
    rows = []
    for product in products:
        prices = [float(v["price"]) for v in product.get("variants", []) if v.get("price")]
        rows.append({
            "product_id": product["id"],
            "title": product["title"],
            "vendor": product.get("vendor", ""),
            "product_type": product.get("product_type", ""),
            "variant_count": len(product.get("variants", [])),
            "min_price": min(prices) if prices else None,
            "max_price": max(prices) if prices else None,
            "any_available": any(v.get("available", False) for v in product.get("variants", [])),
            "tags": ", ".join(product.get("tags", []))
        })
    return rows

Exporteren naar CSV, Excel en Google Sheets

# CSV-export (gebruik utf-8-sig zodat Excel speciale tekens goed leest)
df.to_csv("shopify_products.csv", index=False, encoding="utf-8-sig")

# Excel-export (openpyxl vereist)
df.to_excel("shopify_products.xlsx", index=False, engine="openpyxl")

print("Exported to shopify_products.csv and shopify_products.xlsx")

Voor Google Sheets kun je de gspread-library met een service account gebruiken, maar eerlijk gezegd—voor de meeste use cases is exporteren naar CSV en uploaden naar Google Drive sneller en eenvoudiger.

Productiesoftware voor scraping in Python: rate limits, retries en anti-blocking

Het basisscript werkt prima voor kleine stores. Maar een store met 5.000+ producten scrapen, of meerdere stores na elkaar aanroepen? Dan beginnen de problemen.

Shopify’s rate limits en blokkeringsgedrag begrijpen

Shopify’s openbare JSON-endpoints hebben geen officieel gedocumenteerde rate limits (in tegenstelling tot het leaky-bucket-model van de Admin API), maar tests in de praktijk laten het volgende zien:

  • Veilige snelheid: ongeveer 2 requests per seconde per store
  • Zachte bovengrens: ongeveer 40 requests per minuut voordat throttling optreedt
  • HTTP 429: "Too Many Requests"—de standaard rate-limit response
  • HTTP 430: een Shopify-specifieke code die op een security-block wijst (niet alleen rate limiting)
  • HTTP 403 of CAPTCHA-redirect: sommige stores met extra Cloudflare-beveiliging

Requests vanaf gedeelde cloud-infrastructuur (AWS Lambda, Google Cloud Run) worden extra vaak geblokkeerd, omdat die IP-ranges vaker misbruikt worden.

Technieken om Shopify betrouwbaar te scrapen

Hier zie je de progressie van “werkt op mijn laptop” naar “geschikt voor productie”:

NiveauTechniekBetrouwbaarheid
Basisrequests.get() + ?page=Breekt bij grote catalogi, kan geblokkeerd worden
Gemiddeldrequests.Session() + ?limit=250 + time.sleep(1) + retry bij 429Werkt voor de meeste stores
GeavanceerdAsync httpx + roterende User-Agent + exponential backoffProductiewaardig, schaalbaar tot 10K+ producten

Gemiddeld niveau (aanbevolen voor de meeste gebruikers):

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

def create_session():
    """Maak een requests-session met automatische retry-logica."""
    session = requests.Session()
    retries = Retry(
        total=5,
        backoff_factor=1,  # sleep: 0.5s, 1s, 2s, 4s, 8s
        status_forcelist=[429, 430, 500, 502, 503, 504],
        respect_retry_after_header=True
    )
    session.mount("https://", HTTPAdapter(max_retries=retries))
    session.headers.update({
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
    })
    return session

De Retry-configuratie handelt 429-responses automatisch af met exponential backoff. De backoff_factor=1 betekent dat de wachttijd tussen retries oploopt van 0,5s → 1s → 2s → 4s → 8s. Session-hergebruik (requests.Session()) geeft je bovendien connection pooling, wat de overhead verlaagt bij meerdere requests naar hetzelfde domein.

User-Agent-rotatie: scrape je meerdere stores, wissel dan tussen 3–5 realistische browser-User-Agents. Dit gaat niet om misleiding—het gaat erom dat je niet uitziet als een bot die bij elke request exact dezelfde headers stuurt.

Volledig werkend Python-script om Shopify te scrapen met CSV-export

Hier is het complete, direct te kopiëren script dat alles hierboven combineert. Het is ongeveer 75 regels echte code (plus comments), en ik heb het getest op Allbirds (1.420 producten), ColourPop (2.000+ producten) en Zoologist Perfumes (kleine catalogus).

import requests
import pandas as pd
import time
import random
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry


def create_session():
    """Maak een session met retry-logica voor rate limits."""
    session = requests.Session()
    retries = Retry(
        total=5,
        backoff_factor=1,
        status_forcelist=[429, 430, 500, 502, 503, 504],
        respect_retry_after_header=True
    )
    session.mount("https://", HTTPAdapter(max_retries=retries))
    session.headers.update({
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 (KHTML, like Gecko) "
                      "Chrome/125.0.0.0 Safari/537.36"
    })
    return session


def scrape_shopify(store_url, delay=1.0):
    """Scrape alle producten van een Shopify-store via /products.json."""
    session = create_session()
    all_products = []
    page = 1
    base_url = f"{store_url.rstrip('/')}/products.json"

    while True:
        print(f"  Page {page}...", end=" ")
        resp = session.get(base_url, params={"limit": 250, "page": page}, timeout=30)
        resp.raise_for_status()
        products = resp.json().get("products", [])

        if not products:
            break

        all_products.extend(products)
        print(f"{len(products)} products (total: {len(all_products)})")
        page += 1
        time.sleep(delay + random.uniform(0, 0.5))

    return all_products


def flatten_to_variants(products):
    """Maak van geneste product-JSON één rij per variant."""
    rows = []
    for p in products:
        base = {
            "product_id": p["id"],
            "title": p["title"],
            "handle": p["handle"],
            "vendor": p.get("vendor", ""),
            "product_type": p.get("product_type", ""),
            "tags": ", ".join(p.get("tags", [])),
            "created_at": p.get("created_at", ""),
            "updated_at": p.get("updated_at", ""),
            "image_url": p["images"][0]["src"] if p.get("images") else "",
        }
        for v in p.get("variants", []):
            row = {**base}
            row["variant_id"] = v["id"]
            row["variant_title"] = v.get("title", "")
            row["sku"] = v.get("sku", "")
            row["price"] = v.get("price", "")
            row["compare_at_price"] = v.get("compare_at_price", "")
            row["available"] = v.get("available", "")
            rows.append(row)
    return rows


if __name__ == "__main__":
    STORE_URL = "https://allbirds.com"  # Pas dit aan naar de store die je wilt scrapen
    OUTPUT_CSV = "shopify_products.csv"
    OUTPUT_EXCEL = "shopify_products.xlsx"

    print(f"Scraping {STORE_URL}...")
    products = scrape_shopify(STORE_URL)
    print(f"\nTotal products scraped: {len(products)}")

    print("Flattening to variant-level rows...")
    rows = flatten_to_variants(products)
    df = pd.DataFrame(rows)
    print(f"DataFrame: {df.shape[0]} rows x {df.shape[1]} columns")

    df.to_csv(OUTPUT_CSV, index=False, encoding="utf-8-sig")
    df.to_excel(OUTPUT_EXCEL, index=False, engine="openpyxl")
    print(f"\nExported to {OUTPUT_CSV} and {OUTPUT_EXCEL}")

Run het met python scrape_shopify.py. Voor Allbirds duurt dit ongeveer 45 seconden en krijg je een CSV met ongeveer 5.000+ rijen (één per variant). De terminaloutput ziet er ongeveer zo uit:

Scraping https://allbirds.com...
  Page 1... 250 products (total: 250)
  Page 2... 250 products (total: 500)
  ...
  Page 6... 170 products (total: 1420)

Total products scraped: 1420
Flattening to variant-level rows...
DataFrame: 5680 rows x 14 columns

Exported to shopify_products.csv and shopify_products.xlsx

Sla Python over: scrape Shopify in 2 klikken met Thunderbit (no-code alternatief)

Niet iedereen wil Python installeren, importfouten debuggen of een scraping-script onderhouden. Voor de sales rep die morgenochtend concurrentieprijzen nodig heeft, is Python vaak overdreven.

Daarom hebben we Thunderbit Official Website gebouwd—een AI-webscraper die werkt als Chrome-extensie. Geen code, geen API-sleutels, geen omgevingssetup.

Probeer de Thunderbit Chrome-extensie

Hoe Thunderbit Shopify-stores scrapt

Thunderbit heeft een speciale Shopify Scraper-template die vooraf is ingesteld voor Shopify-productpagina’s. Je installeert de Thunderbit Chrome Extension Download Page, navigeert naar een Shopify-store en klikt op "Scrape." De template haalt automatisch productnamen, beschrijvingen, prijzen, variantdetails, afbeeldingen en vendorinformatie op.

Voor stores waar de template niet perfect aansluit (custom themes, afwijkende layouts), leest Thunderbit’s AI Suggest Fields-functie de pagina en genereert automatisch kolomnamen. Je kunt die aanpassen—kolommen hernoemen, velden toevoegen, instructies schrijven zoals "haal alleen producten op met een ingestelde compare_at_price."

Een paar functies die direct overeenkomen met wat het Python-script doet:

  • Subpage scraping: bezoekt automatisch elke productdetailpagina en verrijkt de tabel met volledige beschrijvingen, reviews of variantdetails—precies wat ons Python-script doet door pagina’s te itereren, maar dan zonder code.
  • Automatische paginering: verwerkt doorklikpaginering en infinite scroll zonder configuratie.
  • Geplande scraping: zet terugkerende taken op (bijv. "elke maandag om 9:00") voor doorlopende prijsmonitoring—geen cron job of server nodig.
  • Gratis export naar CSV, Excel, Google Sheets, Airtable of Notion op alle abonnementen.

Python-script vs. Thunderbit: eerlijke vergelijking

FactorPython-scriptThunderbit (No-code)
Setup-tijd15–60 min (omgeving + code)~2 min (Chrome-extensie installeren)
Coderen nodigJa (Python)Nee
AanpasbaarheidOnbeperktAI-voorgestelde velden + custom prompts
Paginering afhandelenHandmatig coderenAutomatisch
ExportformatenZelf coderen (CSV/Excel)CSV, Excel, Google Sheets, Airtable, Notion (gratis)
Geplande runsCron job + hostingIngebouwde scheduler
Rate-limit afhandelingZelf retries/backoff coderenAutomatisch afgehandeld
Beste voorDevelopers, grootschalige datapijplijnenBusiness users, snelle extracties, terugkerende monitoring

Gebruik Python als je volledige controle nodig hebt of als je het in een grotere datapijplijn integreert. Gebruik Thunderbit als je snel data nodig hebt en geen code wilt onderhouden. Voor een diepere kijk op web scraping voor prijsvergelijking hebben we daar een aparte gids over geschreven.

python-vs-thunderbit-comparison.webp

Tips en best practices voor het scrapen van Shopify-stores

Deze gelden ongeacht je toolkeuze:

  • Gebruik altijd ?limit=250 om het totale aantal requests te minimaliseren. De standaard van 30 per pagina betekent 8x meer requests voor dezelfde data.
  • Respecteer de store: voeg 1–2 seconden vertraging toe tussen requests. Een server bestoken met razendsnelle requests is slechte praktijk en vergroot de kans op blokkering.
  • Controleer eerst robots.txt: Shopify’s standaard robots.txt blokkeert /products.json niet. Maar sommige stores voegen eigen regels toe, dus controleer dit voordat je op schaal gaat scrapen.
  • Sla eerst ruwe JSON lokaal op, en verwerk daarna pas verder. Als je parsing-logica later verandert, hoef je niet opnieuw te scrapen. Een simpele json.dump(all_products, open("raw_data.json", "w")) vóór het flattenen bespaart veel gedoe.
  • Dedupliceer op product.id: bij randgevallen in paginering kunnen dubbele producten aan paginagrenzen terugkomen. Een snelle df.drop_duplicates(subset=["product_id", "variant_id"]) lost dat op.
  • Zet price om naar float voordat je gaat rekenen. Shopify geeft prijzen als strings terug ("185.00"), niet als getallen.
  • Houd endpointwijzigingen in de gaten: hoewel /products.json al jaren stabiel is, zou Shopify dit in theorie kunnen beperken. Krijg je ineens 404’s, controleer dan eerst handmatig de store.

Voor meer over het bouwen van robuuste scrapers, bekijk onze gids over best practices voor web scraping tools.

Juridische en ethische aandachtspunten bij het scrapen van Shopify

Kort, maar belangrijk.

Het /products.json-endpoint levert publiek beschikbare productdata—dezelfde informatie die elke bezoeker ziet wanneer hij de store bekijkt. Shopify’s Servicevoorwaarden bevatten taal over het niet gebruiken van "automated means" om toegang te krijgen tot "the Services", maar die tekst verwijst naar het platform zelf (admin-dashboard, checkout), niet naar publieke storefront-data. Tot april 2026 zijn er geen Shopify-specifieke scrapingzaken aangespannen.

Belangrijke juridische precedenten ondersteunen scraping van publieke data: de hiQ v. LinkedIn-zaak stelde vast dat het scrapen van publiek toegankelijke data de CFAA niet schendt, en Meta v. Bright Data (2024) oordeelde dat TOS-beperkingen alleen gelden wanneer een gebruiker is ingelogd.

Best practices:

  • Scrape alleen publiek beschikbare productdata
  • Scrape geen persoonlijke of klantgegevens
  • Respecteer robots.txt en rate limits
  • Voldoe aan GDPR/AVG en CCPA als je persoonlijke data verwerkt (productcatalogusdata is niet-persoonlijk)
  • Identificeer jezelf met een duidelijke User-Agent-string
  • Je eigen Shopify-store scrapen via de Admin API is altijd prima

Voor een diepere duik, zie onze post over de juridische implicaties van web scraping.

Conclusie en belangrijkste inzichten

Shopify’s openbare /products.json-endpoint maakt ecommerce-data-extractie bijna zo eenvoudig als het maar kan. De workflow is: voeg /products.json toe → haal op met Python → pagineer met ?limit=250&page= → flatten met pandas → exporteer naar CSV of Excel.

Wat deze gids biedt dat andere gidsen niet doen:

  • Volledige veldreferentie: weet precies welke data beschikbaar is (40+ velden over producten, varianten en afbeeldingen) voordat je ook maar één regel code schrijft
  • Extra endpoints: /collections.json en /meta.json geven je categorie-inzicht en storemetadata die geen enkele concurrerende tutorial behandelt
  • Productiewaardige technieken: session-hergebruik, exponential backoff, User-Agent-headers en ?limit=250 om echte rate limits aan te kunnen
  • Correcte CSV/Excel-export: afgevlakte variantdata met pandas, niet alleen ruwe JSON-dumps
  • No-code alternatief: Thunderbit voor gebruikers die snelheid boven codeflexibiliteit verkiezen

Voor eenmalige of terugkerende Shopify-data-extracties zonder code, probeer de Thunderbit Chrome Extension Download Page—de Shopify Scraper-template regelt alles van paginering tot export. Voor custom datapijplijnen of scraping op schaal over veel stores biedt het Python-script in deze gids volledige controle.

Bekijk ons Thunderbit YouTube-kanaal voor video-uitleg, of lees onze gidsen over Amazon-producten scrapen en data van websites naar Excel halen voor gerelateerde technieken.

Probeer Thunderbit voor Shopify-scraping Get Started Free

FAQ’s

Kun je elke Shopify-store scrapen met products.json?

De meeste Shopify-stores stellen dit endpoint standaard beschikbaar—in tests gaf ongeveer 71% geldige JSON terug. Sommige stores met custom configuraties of extra beveiligingslagen (Cloudflare, headless setups) geven een 404 terug of blokkeren de request. De snelle check: bezoek {store-url}/products.json in je browser. Zie je JSON, dan zit je goed.

Is het legaal om Shopify-stores te scrapen?

Publieke productdata (prijzen, titels, afbeeldingen, beschrijvingen) is over het algemeen toegankelijk, en juridische precedenten zoals hiQ v. LinkedIn ondersteunen het scrapen van publiek beschikbare informatie. Controleer wel altijd de specifieke voorwaarden van de store en de lokale wetgeving. Scrape geen persoonlijke of klantgegevens en respecteer rate limits.

Hoeveel producten kun je scrapen van een Shopify-store?

Er is geen harde limiet op het totaal. Paginering met ?limit=250&page= laat je de volledige catalogus ophalen. Voor zeer grote stores (25.000+ producten) gebruik je session-hergebruik en vertragingen om rate limits te vermijden. Het /meta.json-endpoint kan je vooraf het exacte productaantal geven, zodat je weet hoeveel pagina’s je kunt verwachten.

Wat is het verschil tussen products.json en de Shopify Admin API?

/products.json is een publiek endpoint—geen authenticatie, alleen read-only productdata, toegankelijk voor iedereen. De Admin API vereist toegangstokens van de store-eigenaar en biedt orders, voorraadhoeveelheden, klantdata en schrijfrechten. Als je verkoopdata of echte voorraadniveaus nodig hebt, heb je Admin API-toegang nodig (dus je moet de store-eigenaar zijn of toestemming hebben).

Kan ik Shopify scrapen zonder Python?

Absoluut. Tools zoals Thunderbit Official Website laten je Shopify-stores scrapen vanuit een Chrome-extensie zonder code. Paginering wordt automatisch afgehandeld en export gaat direct naar CSV, Excel, Google Sheets, Airtable of Notion. Voor developers die liever andere talen gebruiken: hetzelfde /products.json-endpoint werkt ook met JavaScript, Ruby, Go—elke taal die HTTP-requests kan doen en JSON kan parsen.

Meer leren

Ke
Ke
CTO bij Thunderbit | Senior Data Scientist & ML-expert Met bijna tien jaar ervaring in machine learning en data science is Ke Shen alumnus van Columbia University en voormalig Senior Data Scientist bij Walmart Labs. Met diepgaande, door vakgenoten erkende expertise in Python, R, Java en statistiek deelt hij praktijkgerichte inzichten over hoe je complexe AI-algoritmen van theorie naar productieklare architectuur brengt.

Probeer Thunderbit

Verzamel leads en andere data in slechts 2 klikken. Aangedreven door AI.

Thunderbit downloaden Het is gratis
Extraheer data met AI
Zet data eenvoudig over naar Google Sheets, Airtable of Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week