Shopifys /products.json-endepunkt er en av e-handelsverdenens dårligst bevarte hemmeligheter. Legg det til på hvilken som helst Shopify-butikk-URL, så får du strukturert JSON tilbake – ingen API-nøkler, ingen autentisering, og ingen kamp med nestede HTML-strukturer.
Jeg jobber på -teamet, så jeg bruker mye tid på å tenke på hvordan folk henter data fra nettet. Og Shopify-skraping dukker opp hele tiden – salgsteam som følger konkurrentpriser, folk i e-handelsdrift som sammenligner produktkataloger, innkjøpere som leter etter nye leverandører. Med på Shopify og en plattform som står for rundt , er volumet av produktdata som kan skrapes enormt.
Denne guiden går gjennom hele prosessen: hva endepunktet returnerer, hvordan du pager gjennom tusenvis av produkter, hvordan du håndterer hastighetsbegrensninger uten å bli blokkert, og hvordan du flater ut Shopifys nestede JSON til en ryddig CSV- eller Excel-fil ved hjelp av pandas. Jeg viser også endepunktene nesten ingen andre snakker om (/collections.json, /meta.json) og en no-code-løsning for deg som helst vil slippe Python helt.
Hva er Shopifys /products.json-endepunkt, og hvorfor gjør det skraping enklere?
Hver Shopify-butikk har et offentlig endepunkt på {store-url}/products.json som returnerer strukturert produktdata. Ingen API-nøkler. Ingen OAuth. Ingen form for autentisering. Du legger bokstavelig talt bare til /products.json på butikkens URL og får tilbake en JSON-liste med alle produktene i katalogen.
Prøv selv nå: åpne eller i nettleseren. Du vil se ren, strukturert JSON med produkttitler, priser, varianter, bilder, tagger – alt.
Sammenlign det med alternativet: å analysere Shopifys HTML-temaer, som er dypt nestede, varierer fra butikk til butikk og endrer seg hver gang butikkeieren oppdaterer temaet. Dette er det du ellers måtte jobbet med:
HTML-tilnærmingen (kronglete):
1<div class="product-card__info">
2 <h3 class="product-card__title">
3 <a href="/products/classic-blue-jeans">Classic Blue Jeans</a>
4 </h3>
5 <span class="price price--on-sale" data-product-price>$149.00</span>
6</div>
JSON-tilnærmingen (ryddig):
1{
2 "title": "Classic Blue Jeans",
3 "handle": "classic-blue-jeans",
4 "vendor": "Hiut Denim",
5 "variants": [{"price": "149.00", "sku": "HD-BLU-32", "available": true}]
6}
JSON vinner på konsistens, stabilitet og enkel parsing. Endepunktet støtter også to viktige query-parametre – ?limit= (opptil 250 produkter per side, standard er 30) og ?page= for paginering – som vi bruker mye i koden nedenfor.
Viktig forskjell: dette er et offentlig storefront-endepunkt, ikke . Admin API krever tilgangstoken fra butikkinnehaveren og gir ordred data, lagerbeholdning og kundeinformasjon. Det offentlige /products.json-endepunktet er kun for lesing og er tilgjengelig for alle. Jeg forklarer forskjellen nærmere senere, fordi forvirringen rundt dette er stor.
Et forbehold: ikke alle Shopify-butikker eksponerer dette endepunktet. I testene mine returnerte omtrent 71 % gyldig JSON (allbirds.com, gymshark.com, colourpop.com og kyliecosmetics.com fungerte alle), mens noen tilpassede oppsett ga 404 (hiutdenim.co.uk, bombas.com). Den raske testen er enkel: besøk {store-url}/products.json i nettleseren og se hva du får.
Hvorfor skrape Shopify med Python? Viktigste brukstilfeller i business
Hvorfor bry seg? Avkastning. bruker nå automatisert prisskraping til konkurranseanalyse, opp fra bare 34 % i 2020. Og forskning viser at en . Disse dataene er bokstavelig talt verdt penger.
Her er de vanligste bruksområdene jeg ser:
| Bruksområde | Hvem får nytte | Hva du får |
|---|---|---|
| Overvåking av konkurrentpriser | E-handelsdrift | Følg prisendringer, rabatter og førpris på tvers av konkurrentenes kataloger |
| Produktresearch og innkjøp | Innkjøp / merchandising | Sammenlign produktegenskaper, varianter, materialer og tilgjengelighet |
| Leadgenerering | Salgsteam | Hent leverandørnavn, merkenavn og kontaktinfo fra butikkataloger |
| Markeds- og kategorianalyse | Markedsføring | Forstå produktmiks, tagger, kategoristruktur og posisjonering |
| Lager- og tilgjengelighetssporing | Forsyningskjede | Overvåk lagerstatus på variantnivå (available: true/false) over tid |
| Oppdagelse av nye produkter | Produktteam | Følg created_at-tidspunkter for å fange opp nye lanseringer hos konkurrenter |
Python er et naturlig valg for denne typen arbeid. bruker Python som hovedspråk, og økosystemet – requests for HTTP, pandas for databehandling, httpx for asynkronisering – gjør det enkelt å gå fra «jeg har en URL» til «jeg har et regneark» på under 80 linjer kode.
Komplett referanse for products.json: alle feltene forklart
Alle andre guider viser deg title, id og handle, og går så videre. Shopifys JSON-respons inneholder over 40 felt på tvers av produkter, varianter, bilder og valg. Å vite hva som faktisk finnes før du skriver skrape-koden, sparer deg for ny innsamling senere.
Jeg hentet denne referansen fra live /products.json-responser samlet inn 16. april 2026. Strukturen er lik på tvers av alle butikker som eksponerer endepunktet.
Felter på produktnivå
| Felt | Datatype | Eksempelverdi | Forretningsbruk |
|---|---|---|---|
id | Heltall | 123456789 | Unik produktidentifikator for deduplisering |
title | Tekst | "Classic Blue Jeans" | Produktnavn for kataloger og sammenligninger |
handle | Tekst | "classic-blue-jeans" | URL-slug – bygg produktsider som {store}/products/{handle} |
body_html | Tekst (HTML) eller null | Vår bestselger... | Produktbeskrivelse for innholdsanalyse og SEO-research |
vendor | Tekst | "Hiut Denim" | Merke-/leverandørnavn for leadgenerering eller innkjøp |
product_type | Tekst | "Jeans" | Kategorisering for markedsanalyse |
created_at | ISO-dato/tid | "2024-01-15T10:30:00-05:00" | Spor når produkter ble lagt til (oppdagelse av nye lanseringer) |
updated_at | ISO-dato/tid | "2025-03-01T08:00:00-05:00" | Oppdag nylige endringer i katalogen |
published_at | ISO-dato/tid | "2024-01-16T00:00:00-05:00" | Se når produktet ble publisert i butikken |
tags | Liste med tekst | ["organic", "women", "straight-leg"] | Analyse av nøkkelord/tagger for SEO, kategorisering og trendinnsikt |
variants | Liste med objekter | (se variantfeltene nedenfor) | Pris, SKU og tilgjengelighet per variant |
images | Liste med objekter | (se bildefeltene nedenfor) | Bilde-URL-er for kataloger og visuell analyse |
options | Liste med objekter | [{"name": "Size", "values": ["S","M","L"]}] | Forstå produktkonfigurasjon (størrelse, farge, materiale) |
Felter på variantenivå (nestet under hvert produkt)
| Felt | Datatype | Eksempel | Bruksområde |
|---|---|---|---|
id | Heltall | 987654321 | Unik variantidentifikator |
title | Tekst | "32 / Blue" | Navn som vises for varianten |
sku | Tekst | "HD-BLU-32" | SKU-matching mot lagersystemer |
price | Tekst | "185.00" | Prissporing (merk: dette er en tekststreng, gjør om til float ved beregning) |
compare_at_price | Tekst eller null | "200.00" | Opprinnelig pris – viktig for rabattsporing |
available | Boolsk | true | Tilgjengelighet på lager (den eneste offentlige lagerindikatoren) |
weight | Flyttall | 1.2 | Analyse for frakt og logistikk |
option1, option2, option3 | Tekst | "32", "Blue", null | Individuelle valgverdier |
created_at, updated_at | ISO-dato/tid | — | Endringssporing på variantenivå |
Felter på bildnivå
| Felt | Datatype | Eksempel | Bruksområde |
|---|---|---|---|
id | Heltall | 111222333 | Unik bildeidentifikator |
src | Tekst (URL) | "https://cdn.shopify.com/..." | Direkte nedlastingslenke til bilde |
alt | Tekst eller null | "Front view of jeans" | Alt-tekst for tilgjengelighetsanalyse |
position | Heltall | 1 | Rekkefølge på bilder |
width, height | Heltall | 2048, 2048 | Bildedimensjoner |
Dette finner du IKKE i det offentlige endepunktet
En viktig felle: inventory_quantity er IKKE tilgjengelig i offentlige /products.json-responser. Dette feltet ble fjernet fra offentlige JSON-endepunkter i desember 2017 av sikkerhetsgrunner. Den eneste lagerindikatoren du får, er den boolske available-verdien på hver variant (true eller false). For å få faktiske lagerantall må du bruke den autentiserte Admin API-en med tilgang fra butikkeieren.
Før du skriver skrape-koden, gå gjennom tabellen og avgjør hvilke felter som er viktige for ditt brukstilfelle. Hvis du skal følge priser, trenger du variants[].price, variants[].compare_at_price og variants[].available. Hvis du skal generere leads, fokuser på vendor, product_type og tags. Filtrer deretter – CSV-en din blir mye ryddigere.
Utover products.json: Collections, meta og andre Shopify-endepunkter
Ingen konkurrerende guide nevner disse endepunktene. De er helt sentrale for seriøst arbeid med konkurranseanalyse.
/collections.json – alle kategorier i butikken
Returnerer alle collections (kategorier) i butikken med titler, handles, beskrivelser og produktantall. Jeg bekreftet dette på zoologistperfumes.com, allbirds.com og gymshark.com – alle returnerte gyldig JSON.
1{
2 "collections": [
3 {
4 "id": 308387348539,
5 "title": "Attars",
6 "handle": "attars",
7 "published_at": "2026-03-29T12:20:32-04:00",
8 "products_count": 1,
9 "image": { "src": "https://cdn.shopify.com/..." }
10 }
11 ]
12}
Vil du forstå hvordan en konkurrent organiserer katalogen sin? Dette er endepunktet.
/collections/{handle}/products.json – produkter etter kategori
Returnerer produkter filtrert på en bestemt collection. Samme JSON-struktur som /products.json, men avgrenset til én kategori. Dette er kritisk for kategori-basert skraping – for eksempel hvis du bare vil overvåke konkurrentens «Sale»- eller «New Arrivals»-kolleksjon.
/meta.json – metadata på butikknivå
Returnerer butikknavn, beskrivelse, valuta, land og – her er den nyttige delen – published_products_count. Det tallet lar deg regne ut nøyaktig hvor mange pagineringsider du trenger på forhånd: ceil(published_products_count / 250). Slutt på å øke sidetallet blindt til du får et tomt svar.
Hvilket endepunkt bør du bruke?
| Det du vil ha | Endepunkt | Trengs autentisering? |
|---|---|---|
| Alle produkter (offentlige) | /products.json | Nei |
| Produkter i en bestemt kategori | /collections/{handle}/products.json | Nei |
| Butikkmetadata + produktantall | /meta.json | Nei |
| Alle collections (kategorier) | /collections.json | Nei |
| Ordre-/salgsdata (kun egen butikk) | Admin API /orders.json | Ja (API-nøkkel) |
| Lagerantall (kun egen butikk) | Admin API /inventory_levels.json | Ja |
Det tilbakevendende forumspørsmålet – «Kan jeg skrape hvor mange enheter en konkurrent har solgt?» – har et kort svar: nei. Ikke fra offentlige endepunkter. Salgsdata og lagerantall krever autentisert Admin API, altså tilgang fra butikkeieren. Offentlige endepunkter gir deg bare produktkatalogdata.

Slik skraper du Shopify med Python: steg-for-steg-oppsett
- Vanskelighetsgrad: Nybegynner
- Tidsbruk: ca. 15 minutter (oppsett + første skraping)
- Det du trenger: Python 3.11+,
pip, en terminal og en Shopify-butikk-URL du vil skrape
Steg 1: Installer Python og nødvendige biblioteker
Sørg for at du har Python 3.11 eller nyere installert (pandas 3.0.x krever det). Installer deretter de to bibliotekene vi trenger:
1pip install requests pandas
For eksport til Excel trenger du også:
1pip install openpyxl
Øverst i skriptet legger du til disse importene:
1import requests
2import pandas as pd
3import time
4import random
5import json
Du skal ikke få noen importfeil når du kjører skriptet. Hvis pandas gir en versjonsfeil, oppgrader Python til 3.12.
Steg 2: Hent produktdata fra /products.json
Her er en enkel funksjon som tar en butikk-URL, slår opp endepunktet og returnerer parsede JSON-data:
1def fetch_products_page(store_url, page=1, limit=250):
2 """Hent én side med produkter fra en Shopify-butikk."""
3 url = f"{store_url.rstrip('/')}/products.json"
4 params = {"limit": limit, "page": page}
5 headers = {
6 "User-Agent": "Mozilla/5.0 (compatible; ProductResearch/1.0)"
7 }
8 response = requests.get(url, params=params, headers=headers, timeout=30)
9 response.raise_for_status()
10 return response.json().get("products", [])
Viktige detaljer:
limit=250er maksgrensen Shopify tillater per side. Standard er 30, så ved å sette dette eksplisitt reduserer du antall forespørsler med opptil 8 ganger.User-Agent-header: Bruk alltid en realistisk variant. Forespørsler uten User-Agent har større sjanse for å trigge Shopifys anti-bot-systemer.timeout=30: Ikke la én forespørsel henge evig.
Test med en kjent butikk:
1products = fetch_products_page("https://allbirds.com")
2print(f"Hentet {len(products)} produkter")
3print(f"Første produkt: {products[0]['title']}")
Du bør se noe som: Hentet 250 produkter og tittelen på første produkt.
Steg 3: Håndter paginering for å skrape alle produkter
Én forespørsel gir maks 250 produkter. De fleste butikker har mer enn det (Allbirds har over 1 420). Du må loope gjennom sidene til du får et tomt svar.
1def scrape_all_products(store_url, delay=1.0):
2 """Skrap alle produkter fra en Shopify-butikk med paginering."""
3 all_products = []
4 page = 1
5 while True:
6 print(f"Henter side {page}...")
7 products = fetch_products_page(store_url, page=page, limit=250)
8 if not products:
9 print(f"Ingen flere produkter. Totalt: {len(all_products)}")
10 break
11 all_products.extend(products)
12 print(f" Fikk {len(products)} produkter (totalt så langt: {len(all_products)})")
13 page += 1
14 # Vær høflig: vent mellom forespørsler
15 time.sleep(delay + random.uniform(0, 0.5))
16 return all_products
Når products kommer tilbake tom, har du nådd slutten.
time.sleep() med litt tilfeldig variasjon holder deg under Shopifys uformelle hastighetsgrense (~2 forespørsler per sekund).
Profftips: Hvis du hentet /meta.json først, vet du allerede totalt produktantall og kan regne ut nøyaktig hvor mange sider du trenger: pages = ceil(product_count / 250). Da slipper du mønsteret med «én ekstra tom forespørsel på slutten».
Steg 4: Parse og velg feltene du trenger
Nå som du har alle produktene som en Python-liste av ordbøker, kan du hente ut bare feltene du bryr deg om. Her er et eksempel som trekker ut de vanligste feltene for prissporing:
1def extract_product_data(products):
2 """Hent ut nøkkelfelter fra produkter og flate ut varianter."""
3 rows = []
4 for product in products:
5 for variant in product.get("variants", []):
6 rows.append({
7 "product_id": product["id"],
8 "title": product["title"],
9 "handle": product["handle"],
10 "vendor": product.get("vendor", ""),
11 "product_type": product.get("product_type", ""),
12 "tags": ", ".join(product.get("tags", [])),
13 "created_at": product.get("created_at", ""),
14 "variant_id": variant["id"],
15 "variant_title": variant.get("title", ""),
16 "sku": variant.get("sku", ""),
17 "price": variant.get("price", ""),
18 "compare_at_price": variant.get("compare_at_price", ""),
19 "available": variant.get("available", ""),
20 "image_url": product["images"][0]["src"] if product.get("images") else ""
21 })
22 return rows
Dette lager én rad per variant – det mest nyttige formatet for prissammenligning, siden et enkelt produkt som «Classic Blue Jeans» kan ha 12 varianter (6 størrelser × 2 farger), hver med egen pris og tilgjengelighet.
Eksporter skrapet Shopify-data til CSV og Excel med pandas
Alle andre Shopify-skrapeguider dumper rå JSON til en fil og sier seg ferdige. Helt greit for utviklere. Ubrukelig for e-handelsanalytikeren som trenger et regneark innen fredag.
Problemet er at Shopifys JSON er nestet. Ett produkt kan inneholde et titalls varianter, hver med egen pris, SKU og tilgjengelighet. Å flate dette ut til rader og kolonner krever litt arbeid med pandas.
Flate ut nestet JSON til en ryddig tabell
Det finnes to tilnærminger, avhengig av behovet ditt:
Alternativ A: Én rad per variant (best for prissporing og lagerovervåkning)
1# Bruk extract_product_data-funksjonen fra steg 4
2products = scrape_all_products("https://allbirds.com")
3rows = extract_product_data(products)
4df = pd.DataFrame(rows)
5print(f"DataFrame-form: {df.shape}")
6print(df.head())
Dette gir deg en flat tabell der hver rad er en unik kombinasjon av produkt og variant. En butikk med 500 produkter og i snitt 4 varianter per produkt gir en DataFrame på rundt 2 000 rader.
Alternativ B: Én rad per produktsammendrag (best for katalogoversikt)
1def summarize_products(products):
2 """Én rad per produkt med min/maks pris på tvers av varianter."""
3 rows = []
4 for product in products:
5 prices = [float(v["price"]) for v in product.get("variants", []) if v.get("price")]
6 rows.append({
7 "product_id": product["id"],
8 "title": product["title"],
9 "vendor": product.get("vendor", ""),
10 "product_type": product.get("product_type", ""),
11 "variant_count": len(product.get("variants", [])),
12 "min_price": min(prices) if prices else None,
13 "max_price": max(prices) if prices else None,
14 "any_available": any(v.get("available", False) for v in product.get("variants", [])),
15 "tags": ", ".join(product.get("tags", []))
16 })
17 return rows
Eksporter til CSV, Excel og Google Sheets
1# CSV-eksport (bruk utf-8-sig så Excel håndterer spesialtegn)
2df.to_csv("shopify_products.csv", index=False, encoding="utf-8-sig")
3# Excel-eksport (krever openpyxl)
4df.to_excel("shopify_products.xlsx", index=False, engine="openpyxl")
5print("Eksporterte til shopify_products.csv og shopify_products.xlsx")
For Google Sheets kan du bruke gspread-biblioteket med en servicekonto, men helt ærlig – for de fleste behov er det raskere og enklere å eksportere til CSV og laste opp til Google Drive.
Produksjonsklar Python-skraping: hastighetsgrenser, retries og beskyttelse mot blokkering
Det grunnleggende skriptet fungerer fint for små butikker. Men skraping av en butikk med 5 000+ produkter, eller flere butikker etter hverandre? Da begynner ting å ryke.
Forstå Shopifys hastighetsgrenser og blokkeringsatferd
Shopifys offentlige JSON-endepunkter har ikke formelt dokumenterte hastighetsgrenser (i motsetning til Admin API sitt leaky bucket-oppsett), men praktiske tester viser:
- Trygg hastighet: ca. 2 forespørsler per sekund per butikk
- Myk grense: rundt 40 forespørsler i minuttet før throttling slår inn
- HTTP 429: «Too Many Requests» – standard respons ved hastighetsbegrensning
- HTTP 430: En Shopify-spesifikk kode som viser sikkerhetsblokkering, ikke bare rate limiting
- HTTP 403 eller CAPTCHA-omdirigering: Noen butikker har ekstra Cloudflare-beskyttelse
Forespørsler fra delt skyinfrastruktur (AWS Lambda, Google Cloud Run) utløser oftere blokkeringer fordi disse IP-områdene ofte er assosiert med misbruk.
Teknikker for å skrape Shopify pålitelig
Her er utviklingen fra «fungerer på min laptop» til «kan kjøres i produksjon»:
| Nivå | Teknikk | Pålitelighet |
|---|---|---|
| Grunnleggende | requests.get() + ?page= | Ryker på store kataloger, kan bli blokkert |
| Middels | requests.Session() + ?limit=250 + time.sleep(1) + retry ved 429 | Fungerer for de fleste butikker |
| Avansert | Asynkron httpx + roterende User-Agent + eksponentiell backoff | Produksjonsklar, skalerer til 10K+ produkter |
Middels nivå (anbefalt for de fleste):
1import requests
2from requests.adapters import HTTPAdapter
3from urllib3.util.retry import Retry
4def create_session():
5 """Opprett en requests-session med automatisk retry-logikk."""
6 session = requests.Session()
7 retries = Retry(
8 total=5,
9 backoff_factor=1, # vent: 0,5s, 1s, 2s, 4s, 8s
10 status_forcelist=[429, 430, 500, 502, 503, 504],
11 respect_retry_after_header=True
12 )
13 session.mount("https://", HTTPAdapter(max_retries=retries))
14 session.headers.update({
15 "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"
16 })
17 return session
Retry-oppsettet håndterer 429-svar automatisk med eksponentiell backoff. backoff_factor=1 betyr at ventetiden blir 0,5 s → 1 s → 2 s → 4 s → 8 s mellom forsøkene. Gjenbruk av session (requests.Session()) gir også connection pooling, som reduserer overhead når du gjør flere forespørsler til samme domene.
Rulling av User-Agent: Hvis du skraper flere butikker, roter mellom 3–5 realistiske nettleser-User-Agent-strenger. Dette handler ikke om å lure noen – det handler om å ikke se ut som en bot som sender identiske headere på hver forespørsel.
Fullt fungerende Python-skript for å skrape Shopify med CSV-eksport
Her er hele skriptet du kan kopiere og lime inn, som kombinerer alt over. Det er omtrent 75 linjer faktisk kode (pluss kommentarer), og jeg har testet det mot Allbirds (1 420 produkter), ColourPop (2 000+ produkter) og Zoologist Perfumes (liten katalog).
1import requests
2import pandas as pd
3import time
4import random
5from requests.adapters import HTTPAdapter
6from urllib3.util.retry import Retry
7def create_session():
8 """Opprett en session med retry-logikk for hastighetsgrenser."""
9 session = requests.Session()
10 retries = Retry(
11 total=5,
12 backoff_factor=1,
13 status_forcelist=[429, 430, 500, 502, 503, 504],
14 respect_retry_after_header=True
15 )
16 session.mount("https://", HTTPAdapter(max_retries=retries))
17 session.headers.update({
18 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
19 "AppleWebKit/537.36 (KHTML, like Gecko) "
20 "Chrome/125.0.0.0 Safari/537.36"
21 })
22 return session
23def scrape_shopify(store_url, delay=1.0):
24 """Skrap alle produkter fra en Shopify-butikk via /products.json."""
25 session = create_session()
26 all_products = []
27 page = 1
28 base_url = f"{store_url.rstrip('/')}/products.json"
29 while True:
30 print(f" Side {page}...", end=" ")
31 resp = session.get(base_url, params={"limit": 250, "page": page}, timeout=30)
32 resp.raise_for_status()
33 products = resp.json().get("products", [])
34 if not products:
35 break
36 all_products.extend(products)
37 print(f"{len(products)} produkter (totalt: {len(all_products)})")
38 page += 1
39 time.sleep(delay + random.uniform(0, 0.5))
40 return all_products
41def flatten_to_variants(products):
42 """Flate ut nestet produkt-JSON til én rad per variant."""
43 rows = []
44 for p in products:
45 base = {
46 "product_id": p["id"],
47 "title": p["title"],
48 "handle": p["handle"],
49 "vendor": p.get("vendor", ""),
50 "product_type": p.get("product_type", ""),
51 "tags": ", ".join(p.get("tags", [])),
52 "created_at": p.get("created_at", ""),
53 "updated_at": p.get("updated_at", ""),
54 "image_url": p["images"][0]["src"] if p.get("images") else "",
55 }
56 for v in p.get("variants", []):
57 row = {**base}
58 row["variant_id"] = v["id"]
59 row["variant_title"] = v.get("title", "")
60 row["sku"] = v.get("sku", "")
61 row["price"] = v.get("price", "")
62 row["compare_at_price"] = v.get("compare_at_price", "")
63 row["available"] = v.get("available", "")
64 rows.append(row)
65 return rows
66if __name__ == "__main__":
67 STORE_URL = "https://allbirds.com" # Endre dette til butikken du vil hente fra
68 OUTPUT_CSV = "shopify_products.csv"
69 OUTPUT_EXCEL = "shopify_products.xlsx"
70 print(f"Skraper {STORE_URL}...")
71 products = scrape_shopify(STORE_URL)
72 print(f"\nTotalt antall produkter skrapet: {len(products)}")
73 print("Flater ut til rader på variantenivå...")
74 rows = flatten_to_variants(products)
75 df = pd.DataFrame(rows)
76 print(f"DataFrame: {df.shape[0]} rader x {df.shape[1]} kolonner")
77 df.to_csv(OUTPUT_CSV, index=False, encoding="utf-8-sig")
78 df.to_excel(OUTPUT_EXCEL, index=False, engine="openpyxl")
79 print(f"\nEksporterte til {OUTPUT_CSV} og {OUTPUT_EXCEL}")
Kjør det med python scrape_shopify.py. For Allbirds tar dette rundt 45 sekunder og produserer en CSV med rundt 5 000+ rader (én per variant). Terminalutskriften ser omtrent slik ut:
1Skraper https://allbirds.com...
2 Side 1... 250 produkter (totalt: 250)
3 Side 2... 250 produkter (totalt: 500)
4 ...
5 Side 6... 170 produkter (totalt: 1420)
6Totalt antall produkter skrapet: 1420
7Flater ut til rader på variantenivå...
8DataFrame: 5680 rader x 14 kolonner
9Eksporterte til shopify_products.csv og shopify_products.xlsx
Dropp Python: Skrap Shopify på 2 klikk med Thunderbit (no-code-alternativ)
Ikke alle vil installere Python, feilsøke importfeil eller vedlikeholde et skrapeskript. For selgeren som trenger konkurrentpriser innen i morgen tidlig, er Python overkill.
Derfor bygde vi – en AI-nettskraper som kjører som en Chrome-utvidelse. Ingen kode, ingen API-nøkler, ingen miljøoppsett.
Slik skraper Thunderbit Shopify-butikker
Thunderbit har en egen Shopify Scraper-template som er forhåndskonfigurert for produktsider i Shopify. Du installerer , går til en Shopify-butikk og klikker «Scrape». Malen henter automatisk ut produktnavn, beskrivelser, priser, variantdetaljer, bilder og leverandørinformasjon.
For butikker der malen ikke matcher helt perfekt (tilpassede temaer, uvanlige layouter), kan Thunderbits AI Suggest Fields lese siden og generere kolonnenavn automatisk. Du kan tilpasse disse – gi nytt navn til kolonner, legge til felt, eller skrive instruksjoner som «hent bare produkter med compare_at_price satt».
Noen funksjoner som direkte tilsvarer det Python-skriptet gjør:
- Skraping av undersider: Besøker automatisk hver produktside og beriker tabellen med full beskrivelse, anmeldelser eller variantdetaljer – det samme som Python-skriptet vårt gjør ved å iterere gjennom sider, men uten kode.
- Automatisk paginering: Håndterer klikkbasert paginering og infinite scroll uten konfigurering.
- Planlagt skraping: Sett opp gjentakende jobber (for eksempel «hver mandag kl. 09:00») for løpende prissporing – uten cron-jobb eller server.
- Gratis eksport til CSV, Excel, Google Sheets, Airtable eller Notion på tvers av alle planer.
Python-skript vs. Thunderbit: ærlig sammenligning
| Faktor | Python-skript | Thunderbit (no-code) |
|---|---|---|
| Oppsettstid | 15–60 min (miljø + kode) | Ca. 2 min (installer Chrome-utvidelse) |
| Koding nødvendig | Ja (Python) | Nei |
| Tilpasning | Ubegrenset | AI-forslåtte felter + egendefinerte prompt |
| Håndtering av paginering | Må kodes manuelt | Automatisk |
| Eksportformater | Du må kode det selv (CSV/Excel) | CSV, Excel, Google Sheets, Airtable, Notion (gratis) |
| Planlagte kjøringer | Cron-jobb + hosting | Innebygd planlegger |
| Håndtering av rate limits | Du må kode retries/backoff | Håndteres automatisk |
| Best for | Utviklere, store datapipelines | Forretningsbrukere, raske uttrekk, gjentatt overvåking |
Bruk Python når du trenger full kontroll eller skal bygge inn data i en større pipeline. Bruk Thunderbit når du trenger data raskt og ikke vil vedlikeholde kode. For en dypere gjennomgang av , har vi skrevet en egen guide om det.

Tips og beste praksis for å skrape Shopify-butikker
Disse gjelder uansett hvilket verktøy du bruker:
- Bruk alltid
?limit=250for å minimere antall forespørsler. Standardverdien 30 per side betyr 8 ganger flere forespørsler for samme data. - Vis hensyn til butikken: Legg inn 1–2 sekunders pause mellom forespørsler. Å bombardere en server med raske forespørsler er dårlig praksis og øker sjansen for å bli blokkert.
- Sjekk
robots.txtførst: Shopifys standardrobots.txtblokkerer IKKE/products.json. Men noen butikker legger til egne regler, så verifiser før du skraper i stor skala. - Lagre rå JSON lokalt først, og bearbeid deretter. Hvis parsinglogikken din endrer seg senere, slipper du å skrape alt på nytt. En enkel
json.dump(all_products, open("raw_data.json", "w"))før du flater ut dataene sparer mye arbeid. - Dedupliser med
product.id: Kanttilfeller i paginering kan noen ganger gi dupliserte produkter ved sideoverganger. En raskdf.drop_duplicates(subset=["product_id", "variant_id"])rydder opp. - Gjør
priceom til float før du regner. Shopify returnerer priser som strenger ("185.00"), ikke tall. - Følg med på endringer i endepunktet: Selv om
/products.jsonhar vært stabilt i årevis, kan Shopify i teorien stramme inn tilgangen. Hvis skraperen plutselig får 404, sjekk butikken manuelt først.
For mer om hvordan du bygger robuste skrapere, se guiden vår om .
Juridiske og etiske hensyn ved skraping av Shopify
Kort seksjon, men viktig.
/products.json-endepunktet leverer offentlig tilgjengelige produktdata – den samme informasjonen enhver besøkende ser når de blar i butikken. Shopifys vilkår inneholder formuleringer om at «automatiserte midler» ikke skal brukes til å få tilgang til «tjenestene», men dette viser til selve plattformen (adminpanel, checkout), ikke offentlige butikkdata. Per april 2026 er det ikke reist noen Shopify-spesifikke søksmål om skraping.
Viktige rettsavgjørelser støtter skraping av offentlig data: hiQ v. LinkedIn slo fast at skraping av offentlig tilgjengelige data ikke bryter CFAA, og Meta v. Bright Data (2024) fastslo at TOS-restriksjoner bare gjelder når en bruker er logget inn.
Beste praksis:
- Skrap bare offentlig tilgjengelige produktdata
- Ikke skrap personlige data eller kundedata
- Respekter
robots.txtog hastighetsgrenser - Følg GDPR/CCPA hvis du håndterer personopplysninger (produktkatalogdata er ikke-personlige)
- Identifiser deg med en tydelig User-Agent-streng
- Å skrape din egen Shopify-butikk via Admin API er alltid greit
For en dypere gjennomgang, se innlegget vårt om .
Konklusjon og viktige læringspunkter
Shopifys offentlige /products.json-endepunkt gjør uthenting av e-handelsdata utrolig enkelt. Arbeidsflyten er: legg til /products.json → hent med Python → pager med ?limit=250&page= → flate ut med pandas → eksporter til CSV eller Excel.
Dette denne guiden dekker som andre ikke gjør:
- Komplett feltreferanse: Vet nøyaktig hvilke data som er tilgjengelige (40+ felter på tvers av produkter, varianter og bilder) før du skriver én eneste linje kode
- Ekstra endepunkter:
/collections.jsonog/meta.jsongir deg innsikt på kategorinivå og butikkmetadata som ingen konkurrentguider dekker - Produksjonsklare teknikker: Gjenbruk av session, eksponentiell backoff, User-Agent-headere og
?limit=250for å håndtere reelle hastighetsgrenser - Riktig CSV/Excel-eksport: Flate variantdata med pandas, ikke bare rå JSON-dumper
- No-code-alternativ: for deg som prioriterer fart framfor fleksibilitet i kode
For engangsuttak eller gjentatt Shopify-datahenting uten kode, prøv – Shopify Scraper-template håndterer alt fra paginering til eksport. For tilpassede datapipelines eller skraping i stor skala på tvers av mange butikker gir Python-skriptet i denne guiden deg full kontroll.
Sjekk ut for videogjennomganger, eller utforsk guidene våre om og for relaterte teknikker.
Vanlige spørsmål
Kan du skrape hvilken som helst Shopify-butikk med products.json?
De fleste Shopify-butikker eksponerer dette endepunktet som standard – i testene mine returnerte rundt 71 % gyldig JSON. Noen butikker med tilpassede oppsett eller ekstra sikkerhetslag (Cloudflare, headless-oppsett) kan returnere 404 eller blokkere forespørselen. Den raske testen: besøk {store-url}/products.json i nettleseren. Hvis du ser JSON, er du klar.
Er det lov å skrape Shopify-butikker?
Offentlige produktdata (priser, titler, bilder, beskrivelser) er som regel tilgjengelige, og rettspraksis som hiQ v. LinkedIn støtter skraping av offentlig tilgjengelig informasjon. Likevel bør du alltid sjekke den aktuelle butikkens vilkår og lokale lover. Ikke skrap personlige data eller kundedata, og respekter hastighetsgrenser.
Hvor mange produkter kan du skrape fra en Shopify-butikk?
Det finnes ingen hard grense for totalt antall. Paginering med ?limit=250&page= lar deg hente hele katalogen. For veldig store butikker (25 000+ produkter) bør du bruke session-gjenbruk og pauser for å unngå hastighetsgrenser. /meta.json-endepunktet kan gi deg eksakt produktantall på forhånd, så du vet hvor mange sider du kan forvente.
Hva er forskjellen mellom products.json og Shopify Admin API?
/products.json er et offentlig endepunkt – ingen autentisering, kun lesing, tilgjengelig for alle. Admin API krever tilgangstoken fra butikkeieren og gir ordredata, lagerantall, kundedata og skrive-tilgang. Hvis du trenger salgsdata eller faktiske lagerantall, trenger du Admin API-tilgang (som betyr at du må være butikkeier eller ha tillatelse).
Kan jeg skrape Shopify uten Python?
Absolutt. Verktøy som lar deg skrape Shopify-butikker fra en Chrome-utvidelse uten kode. Det håndterer paginering automatisk og eksporterer direkte til CSV, Excel, Google Sheets, Airtable eller Notion. For utviklere som foretrekker andre språk, fungerer samme /products.json-endepunkt med JavaScript, Ruby, Go – alle språk som kan gjøre HTTP-forespørsler og parse JSON.
Les mer