Tony Wang7 分で読めますShopify ストアをスクレイピングする方法 2026 年版(API と Python)
2026 年に Shopify ストアのプロダクトとコレクションをスクレイピングする 3 つの方法 — Python の自作、ノーコードツール、構造化 API — それぞれが何を返すのかと、法律の基本。
2026 年に Shopify ストアをスクレイピングする最速の方法は、各ストアフロントをクロールして自分でパースするのではなく、正規化された JSON(プロダクト、バリアント、価格、コレクション、ストアのメタデータ)を返す構造化 API を呼び出すことです。ほとんどの Shopify ストアは公開のプロダクトフィードを提供しているため Python での自作も可能ですが、バリアントの扱い、ページネーション、ストアごとの癖を考えると、大規模になるほど、メンテナンスされたエンドポイントのほうが手軽な選択肢になります。
Shopify 独自の Admin API と Storefront API はストアオーナーの認証情報を必要とし、自分が管理するストア向けのものです。自分が所有していないストアフロントを調査するには、公開されているプロダクト面を収集します。これがまさに、構造化スクレイピング API が正規化してくれる部分です。
Is it legal to scrape Shopify stores?
ストアフロントのプロダクトページは公開されており、公開データの収集は一般に、非公開アカウントへのアクセスとは異なる扱いを受けます。ただし、いつもの条件が伴います。
- 収集するのは公開ストアフロントのデータのみ。管理画面やチェックアウトへのアクセスは行わない。
- 各ストアの利用規約と robots ディレクティブ、そしてお住まいの地域の法律を尊重する。
- プロダクトの画像や文章を、ユースケースと法律が許す範囲を超えて再利用しない。
- 収集したものを適法かつ誠実に利用する責任は利用者にあります。
これは法的助言ではありません。全体像については Is web scraping legal in 2026? をご覧ください。
Option 1: DIY in Python (and why it breaks)
多くの Shopify ストアは公開の products.json フィードを提供しているため、最初の一手は簡単に見えます。
import csv, requests
resp = requests.get(
"https://www.allbirds.com/products.json",
params={"limit": 250, "page": 1}, # walk page=1,2,... until the list is empty
headers={"User-Agent": "Mozilla/5.0"},
)
rows = []
for p in resp.json()["products"]:
for v in p["variants"]: # flatten nested variants into rows
rows.append({"title": p["title"], "handle": p["handle"],
"variant": v["title"], "price": v["price"], "available": v["available"]})
with open("shopify.csv", "w", newline="") as f:
w = csv.DictWriter(f, fieldnames=rows[0].keys()); w.writeheader(); w.writerows(rows)
# ...then handle HTTP 430 rate limits and stores that disable /products.json
コストがかさむのはこういった点です。
- 公開状況のばらつき — 公開フィードを無効化しているストアもあり、レート制限に達すると Shopify は HTTP
430を返すため、バックオフ、プロキシ、フォールバックが必要になります。 - バリアントのフラット化 — 各プロダクトには入れ子になったバリアント、オプション、画像があり、これらを行に正規化する必要があります。
- ページネーション —
/products.jsonは 1 ページあたり最大 250 件で上限に達するため、大規模なカタログは多数のページにまたがり、たどって重複を除去する必要があります。さらに/collections.jsonは別のクロールになります。 - ストアごとの違い — 通貨、在庫状況、メタフィールドはテーマによって異なります。
Option 2: No-code and ready-made tools
ポイント&クリック式のエクスポートツールは 1 つのストアをダンプできますが、カタログと価格の監視となると、多数のストアをスケジュールに沿って再チェックし、履歴を保存することを意味します。これは手動ツールよりも API のほうがうまく処理できるパイプラインです。
Option 3: A structured Shopify API
Crawlora の Shopify API は、プロダクト、コレクション、ストアの各エンドポイントを 1 つの API キーの背後にまとめ、正規化された JSON を返します。ストアの URL を指定するだけです。
curl -G "https://api.crawlora.net/api/v1/shopify/products" \
-H "x-api-key: $CRAWLORA_API_KEY" \
--data-urlencode "url=https://www.allbirds.com" \
--data-urlencode "limit=50"
import requests
resp = requests.get(
"https://api.crawlora.net/api/v1/shopify/products",
headers={"x-api-key": "YOUR_API_KEY"},
params={"url": "https://www.allbirds.com", "limit": 50},
)
for product in resp.json()["data"]["products"]:
print(product["title"], product["price"], product["handle"])
レスポンスはそのまま保存できる正規化された JSON です(フィールドはあくまで例です。スキーマはドキュメントで確認してください)。
{
"code": 200,
"msg": "OK",
"data": {
"products": [
{
"handle": "wool-runner",
"title": "Wool Runner",
"price": 98.0,
"currency": "USD",
"available": true,
"variants": [{ "title": "US 9", "price": 98.0, "available": true }]
}
]
}
}
そこから、コレクションでカタログをマッピングしたり、handle でプロダクトの詳細を取得したり、ストアのメタデータを読み取ったりできます。すべて同じキーで行えます(どのエンドポイントもストアの url を受け取ります)。
h = {"x-api-key": "YOUR_API_KEY"}
base, store = "https://api.crawlora.net/api/v1/shopify", "https://www.allbirds.com"
collections = requests.get(f"{base}/collections", headers=h, params={"url": store}).json()["data"]
product = requests.get(f"{base}/products/wool-runner", headers=h, params={"url": store}).json()["data"]
meta = requests.get(f"{base}/store", headers=h, params={"url": store}).json()["data"]
1 つのコレクションをたどるには /collections/{handle}/products を使い、ストアフロント上のすべてのプロダクトとコレクションの URL を見つけ出すにはサイトマップのエンドポイントを使います。/products.json が無効化されている場合に便利です。
ヘッドレス Shopify ストアフロントとファセット
/products.json はほとんどのストアをカバーしますが、すべてではありません。一部のマーチャントはヘッドレス・ストアフロントを運用しています。Next.js や React のフロントエンドが Shopify のカタログバックエンドに対してサーバーサイドでページをレンダリングし、従来のフィードも、見つけられる *.myshopify.com ドメインも一切公開しないタイプです。同じエンドポイントがどちらのタイプのストアも透過的に処理します。同じ url を渡すだけで、追加のフラグは不要です。従来のフィードと myshopify ドメインへのフォールバックの両方が使えない場合、API はストアフロント自身に埋め込まれた検索結果ペイロードを解析する方式にフォールバックします。
実例を挙げます。Gymshark の米国向けストアフロント www.gymshark.com は従来型の Shopify ストアで、/products.json は通常どおり解決します。国際向けストアフロント row.gymshark.com はヘッドレスで、/products.json と /collections.json はどちらも失敗し、ページ内のどこにも myshopify ドメインはありません。それでも中身は Shopify に支えられたカタログであり、同じ呼び出しがそのまま動きます。
curl -G "https://api.crawlora.net/api/v1/shopify/collections/leggings/products" \
-H "x-api-key: $CRAWLORA_API_KEY" \
--data-urlencode "url=https://row.gymshark.com" \
--data-urlencode "limit=3"
import requests
resp = requests.get(
"https://api.crawlora.net/api/v1/shopify/collections/leggings/products",
headers={"x-api-key": "YOUR_API_KEY"},
params={"url": "https://row.gymshark.com", "limit": 3},
)
data = resp.json()["data"]
print(data["transport_mode"], data["total_items"], data["total_pages"])
この呼び出しは、コレクションの実際の一覧データとファセットデータ(執筆時点で 4 ページにわたる 186 商品)を返し、transport_mode: "ssr_embedded" というフラグが付きます。
{
"code": 200,
"msg": "OK",
"data": {
"store_url": "https://row.gymshark.com",
"source_url": "https://row.gymshark.com",
"collection": "leggings",
"page": 1,
"limit": 3,
"total_items": 186,
"total_pages": 4,
"transport_mode": "ssr_embedded",
"products": [ /* 3 商品。それぞれ下の商品と同じ形 */ ],
"facets": {
"fit": { "regular": 128, "tall": 18, "short": 10 },
"canonicalColour": { "black": 90, "pink": 12 }
},
"facets_stats": {
"price": { "min": 27, "max": 85, "avg": 56.46 }
}
}
}
facets はフィルターフィールドを「値ごとの件数」のバケットに対応付けたもので、ストアフロント自身のフィルターサイドバーを動かしているのと同じデータです。facets_stats は価格のような数値フィールドについて min/max/avg を返します。ファセットのフィールド名はストアフロントが実際に使っている名前をそのまま反映します(Gymshark のフィールドは canonicalColour のように camelCase)。固定リストではなくストア固有のものとして扱ってください。ストアフロントのペイロードにファセットデータが含まれない場合、どちらのフィールドも丸ごと省略されます。
ヘッドレス・ストアフロントの商品には、従来のフィードが決して返さないフィールドも含まれます。colour、canonical_colour、discount_percentage、rating、rating_count、collection_tags、labels、そしてバリアントごとの inventory_quantity です。row.gymshark.com の商品ページから取得した実物がこちらです。
{
"handle": "gymshark-train-t-shirt-ss-tops-black-aw26",
"title": "Train T-Shirt",
"price": 35,
"colour": "black",
"canonical_colour": "black",
"rating": 4.2,
"rating_count": 1549,
"collection_tags": ["all-products", "new-releases"],
"labels": ["new"],
"variants": [
{ "title": "XS", "price": 35, "available": true, "inventory_quantity": 16 }
]
}
別のトランスポートを設定する必要はありません。上の従来型パスと同じベース URL、同じ x-api-key ヘッダー、同じパラメータです。
同じフォールバックは一覧以外の 3 つのエンドポイントもカバーします。商品レコメンド(intent=related または intent=complementary、パラメータは従来型パスと同じ)、静的ページ(/pages.json フィードではなくストアフロント自身の CMS から解析)、コレクション一覧(ストアフロント自身のサイトマップから列挙)です。同じ url、フラグなしで動きます。
curl -G "https://api.crawlora.net/api/v1/shopify/products/gymshark-train-t-shirt-ss-tops-black-aw26/recommendations" \
-H "x-api-key: $CRAWLORA_API_KEY" \
--data-urlencode "url=https://row.gymshark.com" \
--data-urlencode "intent=related"
コレクション一覧についてひとつ注意点があります。読み取る /collections.json フィードがないため、title は URL スラッグからのベストエフォートな推定(all-products → "All Products")であって、ストアフロントの実際の表示名ではなく、コレクションごとの商品数もありません。従来型パスより忠実度は下がります。発見用として使い、実際の詳細は /shopify/collections/{handle}/products で確認してください。
結果のソートとフィルタリング
ヘッドレス・ストアフロントでは、/shopify/products と /shopify/collections/{handle}/products が sortBy パラメータとファセットごとのフィルターパラメータも受け付けます。これらは、ストアフロント自身のソート/フィルター UI が送るのとまったく同じ形で、そのストアフロントの検索インデックスに転送されます。sortBy は sortLTH(価格の安い順)、sortHTL(価格の高い順)、newest のいずれかです。フィルターはファセットのフィールド名ごとに 1 つのクエリパラメータ(その一覧の facets フィールドに現れるのと同じ名前)で、1 つのファセット内の複数の値はカンマ区切り、ファセット間は & で組み合わせます。
curl -G "https://api.crawlora.net/api/v1/shopify/collections/leggings/products" \
-H "x-api-key: $CRAWLORA_API_KEY" \
--data-urlencode "url=https://row.gymshark.com" \
--data-urlencode "sortBy=sortLTH" \
--data-urlencode "fit=regular" \
--data-urlencode "limit=5"
row.gymshark.com のレギンスコレクション(フィルターなしで 186 商品)の実数です。sortLTH でソートすると最初の 5 件は 21, 21, 27, 33, 33(非減少)、sortHTL では 85, 85, 85, 81, 76.5 になります。fit=regular だけでフィルターすると total_items は 186 から 128 に、さらに canonicalColour=black を重ねると 34 にまで絞られます。クライアント側の UI 状態ではなく、サーバー側での本物の絞り込みです。レスポンスには実際に適用された内容がそのまま返ります。
{
"total_items": 34,
"sort": "sortLTH",
"filters": { "fit": ["regular"], "canonicalColour": ["black"] }
}
従来型の Shopify ストアは、sortBy とフィルターを黙って無視するのではなく、型付きの 400 エラーで明確に拒否します。 これは当方の機能不足ではありません。Shopify 自身の公開 /products.json フィードには、サーバー側のソートもフィルターも一切存在しないのです。同じ従来型ストアの JSON を sort_by=price-ascending と sort_by=price-descending で取得すると、バイト単位で同一の商品順が返ってきます。ソートが行われるのはテーマ自身のページ内(または、ストア自身の認証情報が必要な Storefront API 経由)だけです。そのため、従来型ストアである www.gymshark.com を sortBy 付きで呼ぶと、ソート済みに見えて実はそうではないレスポンスではなく、エラーが返ります。
{ "code": 400, "msg": "sort and filters are only supported for headless storefronts served via the embedded-SSR-JSON fallback transport (transport_mode ssr_embedded); Shopify's classic public catalog JSON has no server-side sort or filter support" }
従来型ストアでソートやフィルターが必要な場合は、取得後にクライアント側で適用してください。ストアフロント自身のテーマがやっているのと同じことです。
What you can collect
- プロダクト: タイトル、handle、価格、在庫状況、画像、バリアント
- コレクションと、コレクション内のプロダクト
- ストアのメタデータとストアフロントのサイトマップ
- 検索サジェストとプロダクトのおすすめ
Limitations and common challenges
- すべてのストアがフィードを公開しているわけではありません。 一部のストアは
/products.jsonを無効化したり、レート制限(HTTP430)したりしています。store エンドポイントは公開の*.myshopify.comドメインにフォールバックできますが、カバレッジは保証されません。発見のバックアップとしてサイトマップのエンドポイントを使ってください。 - バリアントとメタフィールド。 プロダクトはバリアント、オプション、画像を入れ子で持っています。これらを行にフラット化し、テーマ固有のメタフィールドがストアごとに異なることを想定してください。
- ページネーション。 プロダクトとコレクションは 1 ページあたり最大 250 件で区切られます。ページをまたいでたどり、重複を除去してください。
- 画像と文章には著作権があります。 価格と在庫状況は収集できる事実ですが、プロダクトの写真や説明文には著作権があります。ユースケースと法律が許す範囲を超えて再公開しないでください。
Sources
Where this fits
まずは無料でお試しください: 任意の公開 URL を Free Web Scraper に通してみるか、Anti-Bot Checker でサイトがボットをブロックしているかどうかを確認できます。サインアップは不要です。
Shopify のデータは、カタログ監視、競合の価格追跡、品揃えのリサーチを支えます。消費者向けマーケットプレイスの視点を得るには Shop.app API と、チャネルをまたいだ価格比較には Amazon scraping API と組み合わせてください。すべて e-commerce product intelligence のワークフローに含まれます。他のマーケットプレイスでの同じ手順については、how to scrape Amazon product data と how to scrape eBay、または how to choose a web scraping API をご覧ください。
まずは Playground でエンドポイントをテストし、API docs でリクエストとレスポンスのスキーマを確認し、pricing page でクレジットのコストをチェックして始めましょう。
よくある質問
ブロックされずに Shopify ストアをスクレイピングできますか?
Crawlora はプロキシのルーティング、ペース調整、リトライ、フォールバックを API の背後で処理し、正規化された JSON を返します。レート制限(HTTP 430)を行うストアや、公開のプロダクトフィードを無効化しているストアについても同様です。
すべての Shopify ストアに products.json フィードがありますか?
ほとんどのストアにあります。/products.json は認証情報不要のエンドポイントで、1 ページあたり最大 250 件のプロダクトを返します。ただし、一部のストアはこれを無効化していたり、レート制限(HTTP 430)していたりします。バニティドメインがこれをブロックしている場合、Crawlora は公開の *.myshopify.com ドメインにフォールバックでき、サイトマップのエンドポイントがバックアップとしてプロダクトとコレクションの URL を発見します。
Shopify にはすでに API があるのでは?
Shopify の Admin API と Storefront API はストアオーナーの認証情報を必要とし、自分が管理するストア向けのものです。自分が所有していないストアフロントを調査するには、Crawlora が公開されているプロダクト面を正規化された JSON として収集します。
どんなデータを収集できますか?
バリアント、価格、在庫状況、画像を含むプロダクト、コレクションとその中のプロダクト、ストアのメタデータ、静的ページ、ストアフロントのサイトマップ、検索サジェスト、プロダクトのおすすめ。価格と在庫状況は事実ですが、プロダクトの画像や文章には著作権があります。
特定のストアを対象にするにはどうすればよいですか?
products エンドポイントにストアの URL を渡します。詳細を得るにはプロダクトの handle を(ストアの url とともに)使い、カタログ構造をマッピングするには collections エンドポイントを、URL を列挙するにはサイトマップのエンドポイントを使います。
価格とカタログの変化を監視できますか?
はい。product と collection の呼び出しをスケジュールに沿って再実行し、履歴を保存することで、価格の動きと品揃えの変化を追跡できます。