# Product Page Scraper – Price, Stock & GTIN from Any Store (`gazidev/product-page-extractor`) Actor

Extract price, currency, stock, SKU, GTIN, brand, rating, images and variants from any online store's product URLs (Shopify, WooCommerce, Magento, BigCommerce, custom). Monitor mode reports price and stock changes. HTTP only, robots.txt respected, $0.001 per product.

- **URL**: https://apify.com/gazidev/product-page-extractor.md
- **Developed by:** [Cemal Atakli](https://apify.com/gazidev) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 product extracteds

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

## Product Page Scraper – Price, Stock & GTIN from Any Store

Paste product page URLs from **any online store** and get clean product JSON: **name, brand, price, currency, sale and regular price, availability (InStock / OutOfStock / PreOrder), SKU, GTIN / EAN / UPC, MPN, rating, review count, images, category, seller and variants**. The Actor works on Shopify, WooCommerce, Magento, BigCommerce, PrestaShop, Shopware, Wix, Squarespace and custom shops.

Turn on **monitor mode** and schedule the Actor to get price drops, price rises and stock changes since the last run.

It costs **$0.001 per product**. Failed URLs are free.

### What it does

1. It fetches each product URL with plain HTTP. There is no browser and no residential proxy. robots.txt is always respected, and each store gets one request at a time, at least 1 s apart.
2. It reads the structured data the store publishes for Google Shopping:
   - **schema.org Product JSON-LD** (including ProductGroup / hasVariant and AggregateOffer)
   - **microdata**
   - **RDFa**
   - **OpenGraph `product:` tags**
3. It enriches the result from the store's own public product JSON:
   - **Shopify** `/products/<handle>.js`: every variant with options, SKU, barcode (GTIN), price, compare-at price and availability.
   - **WooCommerce** Store API: price range, stock and variations.
4. It returns one normalised row per URL. Rows record the `extractionMethod` and the detected `platform`.

### Use cases

- **Price monitoring and competitor tracking:** schedule a daily run with `monitor: true` to get only the products whose price or stock changed.
- **MAP enforcement for brands:** check retailer product pages against your minimum advertised price.
- **Dropshipping and catalogue sync:** pull supplier prices, stock, GTINs and images into your store or spreadsheet.
- **Comparison sites and affiliate feeds:** normalise product data from many small shops into one schema.
- **AI agents:** give an agent clean product JSON from a URL instead of raw HTML.

### Input example

```json
{
  "productUrls": [
    "https://www.allbirds.com/products/mens-tree-runners",
    "https://mercantile.wordpress.org/product/blue-wordpress-flannel-button-down/",
    "https://www.sparkfun.com/sparkfun-redboard-qwiic.html"
  ],
  "includeVariants": true,
  "monitor": false,
  "maxItems": 100
}
```

There are two other ways to supply URLs:

- **`sitemapUrls`:** for example `https://store.com/sitemap_products_1.xml`. Product URLs are selected with `urlPattern`.
- **`datasetId`:** the output of another Actor, with the field name in `datasetUrlField`.

### Output example

```json
{
  "url": "https://www.sparkfun.com/sparkfun-redboard-qwiic.html",
  "status": "ok",
  "name": "SparkFun RedBoard Qwiic",
  "brand": null,
  "sku": "DEV-15123",
  "gtin": null,
  "mpn": "DEV-15123",
  "price": 21.95,
  "currency": "USD",
  "salePrice": null,
  "regularPrice": null,
  "availability": null,
  "image": "https://www.sparkfun.com/media/catalog/product/.../15123-SparkFun_RedBoard_Qwiic-01a.jpg",
  "seller": "SparkFun Electronics",
  "platform": "magento",
  "extractionMethod": "json-ld",
  "variantCount": 0,
  "variants": [],
  "charged": true,
  "fetchedAt": "2026-10-28T12:05:10Z"
}
```

Each variant has these fields: `variantId`, `sku`, `gtin`, `name`, `options` (e.g. `{"Size": "M", "Color": "Red"}`), `price`, `regularPrice`, `currency`, `availability`, `url` and `image`.

Monitor mode adds these fields: `changeStatus` (`new`, `price-down`, `price-up`, `stock-change` or `unchanged`), `previousPrice`, `priceChange`, `priceChangePercent`, `previousAvailability` and `availabilityChanged`.

A URL that cannot be extracted becomes a free row with a `status` explaining why:

- `blocked`
- `robots-disallowed`
- `no-product-data`
- `not-found`
- `unsupported-site`
- `invalid-url`
- `error`

### Pricing

| Event | Price |
|---|---|
| Product extracted | **$0.001** |
| Price or stock change (monitor mode, extra) | $0.001 |
| Actor start | $0.00005 |
| Failed / blocked / unsupported URL | free |

How this compares with similar Actors in the Apify Store (prices as listed on 2026-10-28):

| Actor | Price | Monitor mode | Variants |
|---|---|---|---|
| **This Actor** | **$0.001 / product** | yes | yes (JSON-LD, Shopify, WooCommerce) |
| apify/e-commerce-scraping-tool | $0.006 / product (free tier) to $0.0005 (Diamond) + $0.0005 / search | no | partial |
| fetch_cat/ecommerce-product-page-scraper | $0.005 start + $0.00039 / item | no | – |
| lofomachines/universal-ecommerce-scraper | $0.01 start + $0.004 / item | no | – |
| scrapebench/shopify-change-tracker | $0.01 / change | yes | Shopify only |

### Supported and unsupported sites

The Actor supports independent online stores and brand shops.

Large retailers and marketplaces whose terms forbid automated extraction are refused, and the refusal is free. The list includes:

- Amazon, Walmart, eBay, Etsy, Target, Best Buy
- AliExpress, Alibaba, Temu, Shein
- Costco, Home Depot, Zalando, Wayfair, Flipkart, Mercado Libre, Shopee, Trendyol

Use their official APIs or affiliate feeds instead.

Some stores block datacenter IPs. Those URLs come back as `blocked` and are not charged.

**You are responsible for having the right to collect and use the data from the sites you enter.**

### FAQ

**Which stores work best?**
Any store that publishes schema.org Product data, which most stores do for Google Shopping rich results. Shopify and WooCommerce stores also return full variant lists.

**Does it render JavaScript?**
No. It is HTTP only, which makes it fast and cheap. Pages that only build product data in the browser return `no-product-data` and are free.

**How do I track price changes?**

1. Set `monitor: true` and a `monitorKey`.
2. Create a schedule in Apify Console, for example daily.
3. Each run writes only new and changed products. Turn off `onlyChanges` to get every product.
4. Add an Apify webhook or integration to send changes to Slack, email, Google Sheets or n8n.

**Why is the currency different from what I see?**
Some stores switch currency by visitor location. The Actor reports the price and currency the store served to the Apify server.

**How fast is it?**
Up to 10 stores are fetched in parallel by default (`maxConcurrency`), and each store gets one request about every second.

### Use with AI agents (Apify MCP)

Add the Actor to Claude, Cursor or any MCP client through the [Apify MCP server](https://mcp.apify.com) (`gazidev/product-page-extractor`). An agent can call it with a list of product URLs and get normalised JSON back. Every row has `price`, `currency`, `availability` and `gtin` in the same place, whatever the store platform.

### Related Actors

- [Shopify Products Monitor](https://apify.com/gazidev/shopify-products-monitor) – whole Shopify catalogues with change detection
- [WooCommerce Products Scraper](https://apify.com/gazidev/woocommerce-products-scraper) – whole WooCommerce catalogues via the Store API
- [Shopify Store Analyzer](https://apify.com/gazidev/shopify-store-analyzer) – store-level insights
- [Website Change Monitor](https://apify.com/gazidev/website-change-monitor) – text and price changes on any page
- [URL Metadata & Schema.org Extractor](https://apify.com/gazidev/metadata-schema-extractor) – all metadata of any URL

# Actor input Schema

## `productUrls` (type: `array`):

Product pages from any online store (Shopify, WooCommerce, Magento, BigCommerce, PrestaShop, Shopware, Wix, Squarespace, custom). One URL per line. Big marketplaces whose terms forbid scraping (Amazon, Walmart, eBay, Etsy, Target, AliExpress, Temu, Shein...) are refused for free.

## `sitemapUrls` (type: `array`):

Optional sitemap URLs (e.g. `https://store.com/sitemap_products_1.xml` or `https://store.com/sitemap.xml`). Product-like URLs (matching the pattern below) are taken from them, up to Max products.

## `urlPattern` (type: `string`):

Regular expression that selects product URLs from the sitemaps. Default: `/products?/<slug>`, `/p/`, `/item/`, `/shop/<cat>/<slug>`.

## `datasetId` (type: `string`):

Read product URLs from an Apify dataset (e.g. the output of another scraper).

## `datasetUrlField` (type: `string`):

Field of the dataset items that holds the product URL.

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

List variants (size, colour...) with SKU, GTIN, price and availability. On Shopify and WooCommerce this uses the store's public product JSON (one extra request per product, no extra charge).

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

Add the product description text (up to 5,000 characters).

## `monitor` (type: `boolean`):

Keep a snapshot between runs and add previousPrice, priceChange, priceChangePercent and availabilityChanged. Schedule the Actor (e.g. daily) with the same Monitor key.

## `onlyChanges` (type: `boolean`):

In monitor mode, write only new and changed products to the dataset (every checked product is still charged as a product).

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

Name of the snapshot. Use different keys for different product lists.

## `maxItems` (type: `integer`):

Maximum number of product URLs to process in this run.

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

How many different stores are fetched at the same time. Each store always gets one request at a time.

## `minDelayMillis` (type: `integer`):

Politeness delay per store. A larger robots.txt Crawl-delay is always respected.

## `requestTimeoutSecs` (type: `integer`):

Timeout of one HTTP request.

## `maxRetries` (type: `integer`):

Retries for network errors, HTTP 429 and 5xx.

## `proxyConfiguration` (type: `object`):

Optional. Not needed for most stores. Stores that block automated requests are reported with status `blocked` and not charged.

## Actor input object example

```json
{
  "productUrls": [
    "https://www.allbirds.com/products/mens-tree-runners",
    "https://mercantile.wordpress.org/product/blue-wordpress-flannel-button-down/",
    "https://www.sparkfun.com/sparkfun-redboard-qwiic.html",
    "https://www.adafruit.com/product/4296"
  ],
  "datasetUrlField": "url",
  "includeVariants": true,
  "includeDescription": true,
  "monitor": false,
  "onlyChanges": true,
  "monitorKey": "default",
  "maxItems": 100,
  "maxConcurrency": 10,
  "minDelayMillis": 1000,
  "requestTimeoutSecs": 30,
  "maxRetries": 2,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

## `changes` (type: `string`):

No description

## `results` (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 = {
    "productUrls": [
        "https://www.allbirds.com/products/mens-tree-runners",
        "https://mercantile.wordpress.org/product/blue-wordpress-flannel-button-down/",
        "https://www.sparkfun.com/sparkfun-redboard-qwiic.html",
        "https://www.adafruit.com/product/4296"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("gazidev/product-page-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 = { "productUrls": [
        "https://www.allbirds.com/products/mens-tree-runners",
        "https://mercantile.wordpress.org/product/blue-wordpress-flannel-button-down/",
        "https://www.sparkfun.com/sparkfun-redboard-qwiic.html",
        "https://www.adafruit.com/product/4296",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("gazidev/product-page-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 '{
  "productUrls": [
    "https://www.allbirds.com/products/mens-tree-runners",
    "https://mercantile.wordpress.org/product/blue-wordpress-flannel-button-down/",
    "https://www.sparkfun.com/sparkfun-redboard-qwiic.html",
    "https://www.adafruit.com/product/4296"
  ]
}' |
apify call gazidev/product-page-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,gazidev/product-page-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/W0Fe8hF6keKiR96uK/builds/pGBl4uKfj8hifTp0m/openapi.json
