# Shopify Store Product & Price Extractor (`rowcrate/shopify-catalog-price-extractor`) Actor

Extract every product, variant, SKU and price from any public Shopify store. One row per variant, CSV or JSON.

- **URL**: https://apify.com/rowcrate/shopify-catalog-price-extractor.md
- **Developed by:** [Nicolas](https://apify.com/rowcrate) (community)
- **Categories:** E-commerce, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 product rows

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Shopify Store Product & Price Extractor

Pull the entire public catalogue of any Shopify store — every product, every variant, every
SKU, every price — into a spreadsheet you can open in Excel or push into your own database.

Give it a store address. Get back one row per variant.

### What people use it for

**Watch a competitor's prices.** Run it on a schedule and you have a price history: what they
charge, what they discount, what they mark as sold out, and when any of that changes. The
`compare_at_price` column tells you the sticker price they are discounting *from*, so you can
see the real depth of a promotion instead of guessing.

**Check your own catalogue.** Missing SKUs, products with no image, variants that quietly went
out of stock, price typos with a stray zero. Easier to spot in a spreadsheet of 4,000 rows than
in the Shopify admin.

**Size up a market before entering it.** Run it across 30 stores in a niche and you have a
picture of the price bands, the product types, and how deep each brand's range goes.

**Build a supplier or dropshipping catalogue.** Product titles, handles, images, weights and
prices in one file, ready to map into your own store.

**Feed a comparison site or a deal alert.** Fresh prices every morning, no manual copying.

### What you get back

One row per variant by default. Here are five rows from a real run, trimmed to fit:

| store\_domain | product\_title | variant\_title | sku | price | compare\_at\_price | available |
|---|---|---|---|---|---|---|
| trailhead.com | Merino Runner | US 9 / Grey | TR-MR-9-GY | 128.00 | 148.00 | true |
| trailhead.com | Merino Runner | US 10 / Grey | TR-MR-10-GY | 128.00 | | false |
| trailhead.com | Merino Runner | US 11 / Black | TR-MR-11-BK | 128.00 | 148.00 | true |
| trailhead.com | Trail Cap | Default Title | TR-CAP | 32.00 | | true |
| trailhead.com | Alpine Shell | S / Storm | TR-AS-S-ST | 245.00 | 245.00 | true |

Full field list:

| Field | What it is |
|---|---|
| `store_domain` | The store the row came from. Lets you run many stores into one file. |
| `product_id`, `product_title`, `handle` | Shopify's own product identifiers and name. |
| `product_url` | Direct link to the product page. |
| `vendor`, `product_type`, `tags` | How the store itself classifies the product. |
| `variant_id`, `variant_title`, `sku` | The specific size / colour / option and its stock code. |
| `price` | Current selling price. |
| `compare_at_price` | The "was" price. Empty when the item is not on sale. |
| `available` | `true` / `false` — whether that exact variant is in stock right now. |
| `grams` | Shipping weight, when the store publishes it. |
| `image_url` | First product image. |
| `product_published_at`, `variant_updated_at` | When it went live and when it last changed. |
| `source_url`, `collected_at`, `collection_method`, `record_hash` | Where each row came from, when, and a stable fingerprint so you can dedupe against your own data. |

Download as **CSV, JSON, Excel or XML**, or pull it straight from the Apify API.

**A note on currency:** Shopify's public catalogue does not publish a currency code, so prices
come back as plain numbers in the store's own currency. If you are comparing across countries,
set the currency per store on your side.

### Settings

| Setting | Default | What it does |
|---|---|---|
| **Shopify store URLs** | — | One or more store addresses. Paste the homepage, custom domains included. |
| **One row per variant** | On | Off gives you one row per product instead, using the first variant's price. |
| **Only items in stock** | Off | On drops sold-out variants. |
| **Max products per store** | 1000 | `0` means the whole catalogue. This is your cost dial. |
| **Requests per second** | 1 | Polite by default and works everywhere. There is rarely a reason to raise it. |

### What it costs

Pay per event — you pay for what a run actually produces, not for time:

| Event | Price |
|---|---|
| Run started | $0.01 |
| Store processed | $0.02 |
| Row returned | $0.0005 |

A 2,000-row catalogue from one store costs about **$1.03**. Ten stores at 500 rows each is
about **$2.71**. A run that finds nothing costs a cent.

### Good to know

- **This reads public data only.** It uses the same public product endpoint your browser hits
  when it loads a store's collection page. Nothing behind a login, no customer data, no orders.
- **It respects `robots.txt`.** If a store asks crawlers to stay out, this actor stays out and
  tells you which store it skipped, rather than pretending the store has no products.
- **Sites that are not on Shopify are reported, not hidden.** Add a URL you are unsure about;
  it comes back in the run's `SKIPPED` record with the reason.
- **Rate limited on purpose.** One request per second per store by default.
- **It is cheap to run because it is simple.** No headless browser, so no browser-sized bill.

### Questions or a broken run?

Open an issue on the actor and I answer within 12 hours. If you need this shaped differently —
a specific set of stores on a weekly schedule, delivered as a file to your inbox or a Google
Sheet — that is what I do: **rowcrate.com**.

# Actor input Schema

## `storeUrls` (type: `array`):

One or more Shopify store addresses. Paste the homepage - for example https://allbirds.com. Works with custom domains too. Not sure a site runs on Shopify? Add it anyway: the actor checks and tells you in the results instead of failing.

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

On (recommended): every size and colour gets its own row with its own price and SKU. Off: one row per product, using the first variant price. Turn this off if you only need a product list.

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

Skip sold-out variants. Useful when you are tracking what a competitor is actually selling right now.

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

Stops after this many products in each store. Set 0 for the whole catalogue. Keeping a limit is the simplest way to control what a run costs.

## `requestsPerSecond` (type: `integer`):

How fast to read each store. The default is deliberately polite and works everywhere. Raising it does not usually make the run cheaper and may get you rate-limited.

## Actor input object example

```json
{
  "storeUrls": [
    "https://allbirds.com",
    "https://shop.example.com"
  ],
  "includeVariants": true,
  "onlyAvailable": false,
  "maxProductsPerStore": 1000,
  "requestsPerSecond": 1
}
```

# Actor output Schema

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

One row per variant: product, SKU, price, compare-at price and stock flag, each with the URL it came from and when it was collected.

## `runSummary` (type: `string`):

Row count, request count, and the error categories that came up. Read this first when a run looks off.

## `skipped` (type: `string`):

Targets that returned nothing and why. Showing the gap is what makes the rest of the file trustworthy.

# 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 = {
    "storeUrls": [
        "https://gymshark.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("rowcrate/shopify-catalog-price-extractor").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 = { "storeUrls": ["https://gymshark.com"] }

# Run the Actor and wait for it to finish
run = client.actor("rowcrate/shopify-catalog-price-extractor").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 '{
  "storeUrls": [
    "https://gymshark.com"
  ]
}' |
apify call rowcrate/shopify-catalog-price-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rowcrate/shopify-catalog-price-extractor"
        }
    }
}

```

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/VoOwvlCFYYwEzUI4e/builds/u1qrjz7EFfnVzfVr4/openapi.json
