Shopify Intelligence Tracker avatar

Shopify Intelligence Tracker

Pricing

from $1.20 / 1,000 product scrapeds

Go to Apify Store
Shopify Intelligence Tracker

Shopify Intelligence Tracker

Pull structured product data from any Shopify storefront - no API key needed. One row per variant with prices, SKUs, stock status, images, tags and weights, from the public product feed. Built for competitor research, price monitoring and catalog audits. Billed per product, not per variant.

Pricing

from $1.20 / 1,000 product scrapeds

Rating

0.0

(0)

Developer

Molly Vir

Molly Vir

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

14 days ago

Last modified

Categories

Share

Pull clean, structured product data out of any Shopify storefront — no API key, no scraping code.

Give it a storefront URL. It returns one row per product variant with prices, stock status, images, SKUs, tags, weights and options, taken straight from the store's public product feed.

Built for price monitoring, competitor research, catalog audits and catalog-import workflows.

Example input

{
"urls": ["https://www.everlane.com"],
"max_products": 25
}

Example output

One row per variant. Real record from a live Everlane run:

{
"storeDomain": "https://www.everlane.com",
"productName": "Pull-On Maxi Skirt in Cotton Silk | White",
"variantName": "XXS",
"option1": "XXS",
"price": "138.00",
"sku": "F-BTM-VLE-MAXI-SKIRT-WHT-XXS",
"inStock": true,
"productUrl": "https://www.everlane.com/products/womens-pull-on-maxi-skirt-in-cotton-silk-white",
"productId": 7859023741014,
"variantId": 44641683898454,
"handle": "womens-pull-on-maxi-skirt-in-cotton-silk-white",
"vendor": "Everlane",
"productType": "Bottoms",
"tags": ["category: bottoms", "fabric: silk", "Style SKU: F-BTM-VLE-MAXI-SKIRT"],
"imageUrl": "https://cdn.shopify.com/s/files/1/0623/7916/3734/files/2026-09-27_F-BTM-VLE-MAXI-SKIRT-WHT_flat.jpg",
"weight": 1901,
"weightUnit": "g",
"requiresShipping": true,
"taxable": true
}

Pricing

Pay per event. You are charged for what you get, and the price does not depend on how long the run takes or how much bandwidth it uses.

EventPriceWhen it is charged
Product scraped$0.0012Once per product found, including all of its variants
Storefront$0.002Once per storefront URL requested
Actor Start$0.00005Once per run, when the run begins

Example: one storefront, 100 products, any number of variants per product:

Actor Start 1 × $0.00005 = $0.00005
Storefront 1 × $0.002 = $0.00200
Product scraped 100 × $0.0012 = $0.12000
--------
Total $0.12205

A product with twelve variants still costs $0.0012, so you never pay per row. Duplicate products and products with no variant data are not charged. A storefront that fails is still charged, because it still consumed network resources — but a URL that is rejected as invalid before any request is made is not charged.

There is no minimum charge and no separate platform-usage fee. If a run finds nothing, you pay nothing.

Features

  • No API key. Uses the public product feed every Shopify store already exposes.
  • Every variant, not just products. One row per variant with its own price, SKU and stock status.
  • Residential proxy by default. Datacenter IPs are blocked by most Shopify stores, so the default configuration routes through residential proxies that storefronts actually accept.
  • Works with many storefronts per run. Pass as many URLs as you like in a single run.
  • Automatic pagination. Follows the feed page by page until your product cap or the end of the catalog.
  • Deduplicated. Products appearing on multiple pages and repeated records are removed.
  • Retry-aware. Rate limits and transient server errors are retried with exponential backoff.
  • Honest failures. If every storefront fails, the run exits non-zero instead of reporting an empty success, so scheduled runs and monitors can tell the difference.

Input

FieldTypeDefaultDescription
urlsarray of strings—Shopify storefront URLs to scan, for example https://example.com. Maximum 50 per run; split larger batches across runs.
max_productsinteger25Maximum products per storefront. Minimum 1, maximum 100000.
proxyConfigurationobject{"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}Proxy routing. See Proxies; this default matters.

Output

One item per product variant:

FieldTypeDescription
storeDomainstringBase URL of the storefront.
productNamestring | nullProduct name.
variantNamestring | nullVariant name.
option1 / option2 / option3string | nullVariant options, such as size or color.
pricestring | nullCurrent variant price as reported by the storefront.
compareAtPricestring | nullComparison price when supplied by Shopify.
skustring | nullMerchant SKU.
inStockboolean | nullWhether Shopify reports the variant as currently available. Reflects public availability only, not an inventory quantity.
productUrlstring | nullDirect link to the product page.
productIdinteger | nullShopify product identifier.
variantIdinteger | nullShopify variant identifier.
handlestring | nullProduct URL handle.
vendorstring | nullVendor or brand.
productTypestring | nullProduct category or type.
tagsarray<string> | nullProduct tags, normalized into a list.
createdAt / updatedAt / publishedAtstring | nullProduct timestamps.
imageUrlstring | nullVariant image from featured_image, falling back to the product's first image.
barcodestring | nullVariant barcode or UPC. Shopify's public products.json feed does not include barcodes, so this is normally null.
weightnumber | nullVariant weight in grams, as reported by Shopify.
weightUnitstring | nullAlways "g" when a weight is present, otherwise null.
requiresShippingboolean | nullWhether the variant requires shipping.
taxableboolean | nullWhether the variant is taxable.

Prices are reported exactly as Shopify returns them and are not labeled with any currency.

Proxies

This Actor does not work without a proxy. Apify Actors send requests from datacenter IP ranges, and most Shopify storefronts block those outright with HTTP 429. A run without a proxy returns zero items, and fails with a non-zero exit code rather than reporting a misleading success.

The default proxyConfiguration routes requests through Apify's residential proxy group, which storefronts accept. Verified against live stores.

The default Apify proxy group when you only set useApifyProxy: true is datacenter, which Shopify blocks just as hard as a direct request. RESIDENTIAL is specified explicitly for that reason.

This default is applied by the Actor itself, not only by the run form. Runs started through the API, the CLI, a schedule or the Apify MCP server do not get input-schema defaults applied, so without a code-level default those callers would silently fall back to DATACENTER. Passing proxyConfiguration explicitly always overrides it.

SettingBehaviourTypical cost
apifyProxyGroups: ["RESIDENTIAL"] (default)Works against most stores~$8 / GB, absorbed by the Actor price
apifyProxyGroups: ["DATACENTER"]Cheaper, blocked by most storesfrom $0.6 / IP
useApifyProxy: falseDirect request, no proxyFree, but returns nothing

Each storefront is fetched through a single proxy session, so all pages and retries for one store come from the same IP. Rotating mid-crawl makes the request pattern look erratic and defeats backoff.

The one exception is a broken proxy session. When the proxy itself returns an upstream error, retrying on the same session cannot succeed, so the Actor transparently retries that storefront on a fresh session. A store answering 429 or 404 keeps its original IP and is never rotated, since that would defeat backoff. Because every network call happens before any data is pushed or charged, a rotated retry cannot bill the same storefront twice.

How it works

  • Uses the storefront's public products.json feed.
  • Routes each storefront through its own proxy session (see Proxies).
  • Paginates with page-based requests (up to 250 products per page) until max_products is reached or the feed is exhausted.
  • Deduplicates products that appear on multiple pages.
  • Retries rate-limited (HTTP 429) and server errors (HTTP 5xx) with exponential backoff, three attempts per request.
  • Output records are deduplicated by (productId, variantId, productUrl).
  • Exits non-zero if every storefront failed, so scheduled runs and monitoring can distinguish failure from an empty result.

Limitations

Worth knowing before you rely on this:

  • 50 storefronts per run. Larger batches are truncated to the first 50 and the log says how many were dropped. Each URL consumes proxy bandwidth, so the limit keeps a single run's cost bounded.

  • Only Shopify stores. The Actor reads the public products.json feed that Shopify generates. Other platforms have no equivalent, and will fail with a clear error.

  • Public data only. This reads what the storefront publishes to its public feed. Discount codes, customer-specific pricing, inventory counts and sold-out items hidden from the feed are not available. Prices reflect the store's public list price, not what a customer would actually pay at checkout.

  • Some stores rate-limit aggressively. A small number of high-traffic stores return HTTP 429 even through residential proxies. Retry the run, or lower max_products.

  • Some stores block automated clients outright. The Actor identifies itself honestly as ShopifyIntelligenceTracker/1.0 and links to its Apify page, rather than claiming to be a browser. When a store refuses anyway, the Actor retries from a second and third residential IP before giving up, so an IP-level block usually clears. A store that blocks bot traffic on every IP will still fail.

  • No barcodes. Shopify does not publish barcodes in products.json, so barcode is normally null.

  • No currency. Prices are raw strings from the store, without a currency code.

  • inStock is a flag, not a count. It reflects public availability, not inventory quantity.

Troubleshooting

Every storefront failed, run exited non-zero. Most likely the proxy is not working. Check that proxyConfiguration still includes apifyProxyGroups: ["RESIDENTIAL"]. The Actor logs the exact failure per storefront, including HTTP status or network error type.

One storefront returned nothing. Either the URL is not a Shopify store, or that store is blocking the request. The log names the storefront and the reason, including every IP that was tried.

A storefront failed with HTTP 403. The Actor retries from up to three residential IPs before failing that storefront, so an IP-level block usually clears on its own. If it still fails, the store is blocking automated traffic regardless of source IP. Raising an issue is worth it if the store is widely used.

A product is missing a field such as imageUrl or sku. That store does not publish the field. Coverage is very high across stores, but it is never 100% because merchants configure their own data.

barcode is always null. Expected. See Limitations.

Development

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
pip install -r requirements-dev.txt
pytest

Run locally:

apify run

Input security

Storefront URLs are validated before fetching. Private IPs, loopback, link-local, reserved IPs, and localhost targets are rejected to avoid SSRF.

Deploy

apify push