# Shopify Scraper: Shopify Products, Prices, Variants & Stock (`atesen-software/shopify-store-products-scraper`) Actor

Shopify product scraper for any store: all Shopify products with prices, compare-at prices, discounts, stock per variant, SKUs, vendors, tags, images and descriptions. Whole store, collection or product URLs. Optional price & stock change monitor. No browser, no proxy. $1.50 per 1,000 products.

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

## Pricing

$1.50 / 1,000 results

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 Scraper: Products, Prices, Variants & Stock Monitor

A **Shopify scraper and Shopify products exporter** for **any Shopify store**: get its **whole product catalogue** with **prices, compare-at prices, discounts, every variant with SKU, barcode and in-stock flag, vendor, product type, tags, images and description**. Give a domain (`allbirds.com`), a collection URL or product URLs. Turn on **changes-only mode** to track **price drops, new products, sold-out and back-in-stock** items on a schedule. **Price: $1.50 per 1,000 products ($0.0015 per product row, all variants included); store info and status rows are free.**

- **$1.50 per 1,000 products** (all variants included in one row). About half the price of other Shopify scrapers; start fee only $0.00005.
- **Works with custom domains**: no myshopify address or API key needed. Detects non-Shopify sites, password-protected and hidden catalogues and tells you in a free status row.
- **Price & stock monitor**: compares with the previous run and outputs only new/changed products with `changeType`, `previousPrice`, `priceChangePercent`; removed products as free rows; unchanged products are free.
- **Store info**: store name, currency, country, myshopify domain, catalogue size (free row).
- Uses Shopify's public storefront JSON (`/products.json`), no browser, no proxy, 256 MB, about 250 products per request, so a 5,000-product store takes seconds.

### Use cases

- **Competitor price monitoring** for DTC brands and resellers.
- **Product research / dropshipping**: best sellers, new launches, vendors, price points.
- **Catalogue migration and feeds**: export a store to CSV/Excel/JSON.
- **Lead generation / market maps**: what Shopify brands sell, how big their catalogue is.
- **MAP and discount tracking**: compare-at vs sale price per variant.

### Input

| Field | Description |
|---|---|
| `stores` | Store domains, collection URLs (`/collections/sale`) or product URLs (`/products/x`) |
| `maxProductsPerStore` | Default 1,000, 0 = whole catalogue |
| `keywords` | Keep only products whose title, vendor, type or tags match |
| `includeVariants`, `includeDescription`, `includeStoreInfo` | Output options |
| `changesOnly`, `monitorKey` | Price & stock monitor |

```json
{
  "stores": ["allbirds.com", "https://www.kyliecosmetics.com/collections/all-over-glow"],
  "maxProductsPerStore": 100
}
```

### Output

```json
{
  "type": "product",
  "store": "allbirds.com",
  "storeName": "Allbirds",
  "productId": 7340901859408,
  "name": "Women's Allbirds Flip Flop - Dusty Pink",
  "vendor": "Allbirds",
  "productType": "Womens Flip Flops",
  "price": 25,
  "compareAtPrice": 50,
  "discountPercent": 50,
  "currency": "USD",
  "inStock": true,
  "variantCount": 7,
  "variants": [{ "variantId": 42051234567890, "title": "W5", "sku": "AB...", "price": 25, "compareAtPrice": 50, "inStock": true }],
  "url": "https://allbirds.com/products/womens-allbirds-flip-flop-dusty-pink",
  "imageUrl": "https://cdn.shopify.com/...",
  "createdAt": "2026-04-02T10:00:00-07:00",
  "updatedAt": "2026-10-20T16:41:18-07:00"
}
```

In changes-only mode each row also has `changeType` (new, price_changed, stock_changed, variants_changed, unavailable, back_in_stock, removed), `changes`, `previousPrice`, `priceChange`, `priceChangePercent`, `previousInStock`.

### FAQ

**Does it show stock quantities?** Shopify's public storefront shows whether each variant is available, not the exact quantity. You get `inStock` per variant and `availableVariants` per product.

**A store says "hides its product feed".** A few Shopify stores disable `/products.json`. You get a free status row and are not charged.

**Can I monitor several stores daily?** Yes: put them in one input, switch on `changesOnly` and schedule the Actor. Each run returns only what changed.

### Pricing

Pay per event: **$0.0015 per result** ($1.50 per 1,000 saved rows). Each saved data row is one `result` event. Status rows, error rows and empty lookups are not charged. The run stops when it reaches the maximum cost per run. No Apify proxy and no login.

# Actor input Schema

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

Shopify store domains ("allbirds.com"), collection URLs (https://shop.com/collections/sale) or product URLs (https://shop.com/products/x). Custom domains work; no myshopify address needed.

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

0 = the whole catalogue.

## `keywords` (type: `array`):

Optional. Keep only products whose title, vendor, type or tags contain one of these words. Skipped products are free.

## `includeVariants` (type: `boolean`):

Every size/colour with its own price, compare-at price, SKU, barcode and stock flag.

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

Product description as plain text.

## `includeStoreInfo` (type: `boolean`):

One free row per store: name, currency, country, myshopify domain, products found.

## `maxConcurrency` (type: `integer`):

How many stores are scraped at the same time.

## `changesOnly` (type: `boolean`):

Compare every product with the previous run that used the same input (or the same monitor name) and write only **new** products and products whose **price or stock changed** (each row gets a changeType: new, price_changed, stock_changed, variants_changed, unavailable, back_in_stock). Products that disappeared are written as free 'removed' rows. Unchanged products are skipped and not charged. Off (default) = normal full scrape. Schedule the Actor with this on to get a daily change feed.

## `monitorKey` (type: `string`):

Optional. Runs with the same name share one snapshot. Empty = derived from your store list, so the same input continues the same watch list.

## Actor input object example

```json
{
  "stores": [
    "allbirds.com"
  ],
  "maxProductsPerStore": 1000,
  "includeVariants": true,
  "includeDescription": true,
  "includeStoreInfo": true,
  "maxConcurrency": 3,
  "changesOnly": false
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `allFields` (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"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("atesen-software/shopify-store-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"] }

# Run the Actor and wait for it to finish
run = client.actor("atesen-software/shopify-store-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"
  ]
}' |
apify call atesen-software/shopify-store-products-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,atesen-software/shopify-store-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/qbZaYHUGaha8mXcwJ/builds/MSxQNpWMuP9umSdl5/openapi.json
