# Shopify Store Products Scraper – Prices, Stock & Variants (`glidepath/shopify-products-scraper`) Actor

Every product from any Shopify storefront's public feed. Input: store domains or collection URLs. Output: products with variants, prices, stock status, images and description. $0.83/1k products.

- **URL**: https://apify.com/glidepath/shopify-products-scraper.md
- **Developed by:** [Glidepath](https://apify.com/glidepath) (community)
- **Categories:** E-commerce, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.83 / 1,000 products

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Shopify Store Products Scraper – Prices, Stock & Variants

Get **every product from any Shopify storefront** in one clean, consistent format: title, vendor, type, all variants with price and stock status, images and description.

It reads the store's own **public `products.json` feed** — the same JSON every Shopify storefront publishes for its own storefront and app integrations (no login, no cookies, no browser), so runs are fast, cheap and stable.

### Who uses it

- **Market and competitor research** — track a competitor's catalog, prices and stock over time.
- **Price monitoring and repricing** — watch a set of stores for price or stock changes.
- **Product aggregators and dropshippers** — pull a clean product feed from any Shopify store or collection.
- **Buyers and deal hunters** — filter a store's catalog by price range or in-stock only.
- **AI agents** — a single, predictable tool for "what does store X sell, and at what price?".

### How to use it

1. Add stores to **Store domains or collection URLs** — a bare domain (`allbirds.com`), a full store URL, or a collection URL to scrape only that collection.
2. Optionally filter by price range or in-stock only, and cap how many products per store.
3. Run it and download the products as JSON, CSV or Excel — or call it via API, schedule it, or connect it to Make, Zapier, n8n, Google Sheets or your AI agent (Apify MCP).

### Input example

```json
{
  "stores": ["allbirds.com", "https://gymshark.com/collections/leggings"],
  "onlyAvailable": true,
  "maxProductsPerStore": 200
}
```

### Output example

```json
{
  "store": "allbirds.com",
  "collection": null,
  "id": 7289263685712,
  "handle": "mens-wool-runner-natural-black",
  "title": "Men's Wool Runner - Natural Black",
  "vendor": "Allbirds",
  "productType": "Shoes",
  "tags": ["mens", "shoes", "wool"],
  "priceMin": 89.0,
  "priceMax": 98.0,
  "available": true,
  "variantsCount": 3,
  "variants": [
    {"id": 1001, "title": "8", "sku": "WR-8-BLK", "price": 98.0, "compareAtPrice": null, "available": true,
     "option1": "8", "option2": null, "option3": null}
  ],
  "options": [{"name": "Size", "position": 1, "values": ["8", "9", "10"]}],
  "images": [{"src": "https://cdn.shopify.com/.../wool-runner-1.jpg", "width": 1200, "height": 1200}],
  "url": "https://allbirds.com/products/mens-wool-runner-natural-black",
  "createdAt": "2025-08-29T18:36:38Z",
  "updatedAt": "2026-09-25T22:50:41Z",
  "publishedAt": "2026-09-25T22:24:49Z",
  "descriptionText": "Our original sneaker. Soft, breathable and machine washable.",
  "descriptionHtml": null,
  "scrapedAt": "2026-09-26T09:00:00Z"
}
```

| Field | Description |
|---|---|
| `store`, `collection` | Store domain and collection handle (when the input was a collection URL) |
| `id`, `handle` | Shopify product id and URL slug (use `id` to de-duplicate) |
| `title`, `vendor`, `productType`, `tags` | As published by the store |
| `priceMin`, `priceMax`, `available` | Lowest/highest variant price and whether any variant is purchasable |
| `variantsCount`, `variants` | Every variant with its own price, stock status and option values |
| `options` | Option names and their possible values (e.g. Size, Color) |
| `images` | Product images (URL, width, height); capped by **Max images per product** |
| `url` | Public product page |
| `createdAt`, `updatedAt`, `publishedAt` | ISO 8601 UTC |
| `descriptionText`, `descriptionHtml` | Plain text by default; HTML on request |

A per-store summary (products found, matched, saved, errors) is stored in the run's key-value store as `SUMMARY`.

### Pricing

Pay per result: **$0.83 per 1,000 products**, the same price on every Apify plan. A store or collection that can't be read (not a Shopify store, no products) is never charged, and the same store/collection is never charged twice in one run.

- Watch 30 stores with 100 products each, weekly: 3,000 products/week → about **$9.96/month**.
- Full export of a 5,000-product catalog → about **$4.15**.

Set a **maximum cost per run** in the run options and the Actor stops cleanly when it is reached.

### Limits and notes

- Only public storefronts on the Shopify platform are supported. An entry that isn't a live Shopify store is reported in `SUMMARY` as an error, not silently skipped.
- A collection URL (`/collections/<handle>`) scrapes only that collection; a bare domain scrapes the whole catalog.
- Prices are in the store's own currency as published (the feed does not include a currency code); compare prices only between stores that price in the same currency.
- Descriptions are cleaned to plain text. E-mail addresses and phone numbers a merchant left in a description are removed by default.
- No customer, order or checkout data is collected — product data only.
- Each store's `robots.txt` is respected: if a store disallows automated access to its product feed, that store is skipped, reported in `SUMMARY` and not charged.

### FAQ

**Is it legal to scrape Shopify product listings?** This Actor only reads the `products.json` feed every Shopify store publishes on purpose for its own storefront and third-party integrations. It checks each store's `robots.txt` first, doesn't log in, doesn't bypass any protection and doesn't collect personal or customer data. You are responsible for how you use the data; respect the store's terms if you republish listings.

**Why did a store return 0 products?** It may not be on Shopify, the domain may be wrong, the collection handle may not exist, or the store's `robots.txt` may disallow its product feed. Check `SUMMARY` for the exact error, or try the bare domain instead of a collection URL.

**Can I limit the price range or only get in-stock items?** Yes — set **Minimum/maximum price** and **Only in-stock products** in the input.

**Can I use it from an AI agent?** Yes, via the Apify MCP server or API. Pass `stores` as a list; results are the dataset items above.

### Support

Open an issue on the Actor's **Issues** tab with the input you used and the run link — we reply within a few days.

Made by **Glidepath**. See the changelog for updates.

# Changelog

This Actor's version history is a separate document: https://apify.com/glidepath/shopify-products-scraper/changelog.md

# Actor input Schema

## `stores` (type: `array`):

One entry per store. Accepts a bare domain (allbirds.com), a full store URL (https://allbirds.com), or a collection URL/path to scrape only that collection (https://allbirds.com/collections/mens-shoes or allbirds.com/collections/mens-shoes). Reads the store's own public products.json feed (no login).

## `onlyAvailable` (type: `boolean`):

Keep only products with at least one purchasable (available) variant.

## `minPrice` (type: `number`):

Keep only products with a variant priced at or above this amount (store's own currency).

## `maxPrice` (type: `number`):

Keep only products with a variant priced at or below this amount (store's own currency).

## `maxProductsPerStore` (type: `integer`):

Stop after this many products per store. Leave empty for all products in the store or collection.

## `maxProducts` (type: `integer`):

Stop the whole run after this many products. Leave empty for no limit (your maximum cost per run still applies).

## `includeDescription` (type: `boolean`):

Adds descriptionText. Turn off for smaller, faster output.

## `includeDescriptionHtml` (type: `boolean`):

Adds descriptionHtml with the original formatting.

## `includeImages` (type: `boolean`):

Adds an images array (URL, width, height) for each product.

## `maxImagesPerProduct` (type: `integer`):

Caps how many images are included per product (they add little value and a lot of size).

## `redactContactInfo` (type: `boolean`):

Recommended. A merchant's description occasionally contains a support e-mail or phone number; this removes them.

## Actor input object example

```json
{
  "stores": [
    "allbirds.com",
    "https://gymshark.com/collections/leggings",
    "kyliecosmetics.com"
  ],
  "onlyAvailable": false,
  "maxProductsPerStore": 50,
  "includeDescription": true,
  "includeDescriptionHtml": false,
  "includeImages": true,
  "maxImagesPerProduct": 5,
  "redactContactInfo": true
}
```

# Actor output Schema

## `products` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "stores": [
        "allbirds.com",
        "https://gymshark.com/collections/leggings",
        "kyliecosmetics.com"
    ],
    "maxProductsPerStore": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("glidepath/shopify-products-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "stores": [
        "allbirds.com",
        "https://gymshark.com/collections/leggings",
        "kyliecosmetics.com",
    ],
    "maxProductsPerStore": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("glidepath/shopify-products-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "stores": [
    "allbirds.com",
    "https://gymshark.com/collections/leggings",
    "kyliecosmetics.com"
  ],
  "maxProductsPerStore": 50
}' |
apify call glidepath/shopify-products-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,glidepath/shopify-products-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/rgJUrpAS0f77dM98t/builds/T63dAcHkZqZV897sE/openapi.json
