Shopify Products Scraper — Any Store, No Auth | $0.9/1K avatar

Shopify Products Scraper — Any Store, No Auth | $0.9/1K

Pricing

from $0.87 / 1,000 products

Go to Apify Store
Shopify Products Scraper — Any Store, No Auth | $0.9/1K

Shopify Products Scraper — Any Store, No Auth | $0.9/1K

Collect public Shopify product or variant records from a store's /products.json catalog. Get title, price, SKU, availability, and images. Run with store URLs and no Shopify login or API key. Pricing: $0.90 per 1,000 results on Free, plus Actor Start.

Pricing

from $0.87 / 1,000 products

Rating

0.0

(0)

Developer

Vitalii Bondarev

Vitalii Bondarev

Maintained by Community

Actor stats

0

Bookmarked

8

Total users

2

Monthly active users

17 hours ago

Last modified

Categories

Features

Limited permissions

Share

Shopify Products Scraper for Any Store

Scrape Shopify product catalogs from the public /products.json endpoint on a myshopify.com host or a custom domain. Each row is a product or one variant, and the run does not need a Shopify login or API key.

  • Check competitor listing prices and the in-stock flag.
  • Index vendors, product types, tags, and product URLs.
  • Pull in-stock variant SKUs for a dropshipping supplier.
  • Switch between one row per variant and one row per product.

What you get

The Actor reads public GET /products.json?limit=250&page=N and writes flat rows until a page returns an empty products array or maxProducts is reached for that store.

Default output is one row per variant. There is no currency field and no inventory-quantity field; stock is the boolean available.

FamilyFieldsTypeNotes
Store and productstore_domain, product_id, title, handle, vendor, product_type, tagsstring, integer, string, string, string, string, list of stringsRequested host, Shopify product id, title, slug, vendor, store type, and tags normalized to a list.
Variant columnsvariant_id, variant_title, price, compare_at_price, sku, availableinteger or null, string or null, number or null, number or null, string or null, boolean or nullCurrent variant when one row per variant is on. Null in per-product mode, and null when the product has no variants. Prices are numbers parsed from the store price strings.
Nested catalogoptions, variants, imageslist, list, list of stringsOn every row. Options are name plus values. Each variant object has variant_id, title, option1, option2, option3, sku, price, compare_at_price, available, grams, requires_shipping, and featured_image. Images are CDN URLs in position order.
Price spanprice_min, price_max, compare_at_price_min, compare_at_price_maxnumber or nullLowest and highest across that product's variants. Still set when the flat price column is null.
Linksimage_url, product_urlstring or nullFirst image, and https://<host>/products/<handle>.
Descriptionbody_htmlstring or nullRaw HTML when description HTML is on. Otherwise null.
Timestampscreated_at, updated_at, published_atstring or nullStore ISO 8601 values, passed through.
Qualityparse_confidence, warningsnumber, list of stringsCompleteness score and warning codes.

Quality score

A complete row scores 1. These codes reduce the score:

WarningWhat changes
product_id_missingSubtract 0.50
title_missingSubtract 0.25
handle_missingSubtract 0.10
created_at_missingSubtract 0.05
no_variantsSubtract 0.20 more, only in per-variant mode when the product has no variants. The score is rounded to 3 decimals and does not go below 0.

Sample output

One row from a successful run. The sample is shortened by omitting tags, options, variants, images, compare_at_price_min, compare_at_price_max, price_min, price_max, body_html, created_at, and updated_at. Values that remain are unchanged.

{
"store_domain": "gymshark.myshopify.com",
"product_id": 6715692744907,
"title": "Gymshark Power Washed Track Pants Short - Pitch Grey/Wash",
"handle": "gymshark-power-washed-track-pants-short-pants-grey-aw26",
"vendor": "Gymshark | Be a visionary.",
"product_type": "Womens>Apparel>Pants>wide_leg",
"variant_id": 39662273626315,
"variant_title": "Large",
"price": 48,
"compare_at_price": null,
"sku": "B7B7S-GFPV-L",
"available": true,
"image_url": "https://cdn.shopify.com/s/files/1/0098/8822/files/Power_Washed_Track_Pant_Short_GS_Pitch_Grey_WASH_B7B7S_GFPV_1.jpg?v=1789654609",
"product_url": "https://gymshark.myshopify.com/products/gymshark-power-washed-track-pants-short-pants-grey-aw26",
"published_at": "2026-10-29T19:00:00+00:00",
"parse_confidence": 1,
"warnings": []
}

Pricing

Billing is pay per event. Per-variant and per-product runs use the same Product price. A Product event is one saved dataset row. Filtered-out products and stores that save no rows do not add Product events. Actor Start is charged when the run starts, including a run that saves no rows. Its count is one event per GB of memory, with a minimum of one event.

product-item and variant-item have no price, so you are not charged for them.

PlanActor Start (per event)Product (per result)1,000 Product results
Free$0.00005$0.0009$0.90
Bronze$0.0000495$0.000891$0.891
Silver$0.000049$0.000882$0.882
Gold$0.0000485$0.000873$0.873
Platinum$0.000048$0.000864$0.864
Diamond$0.0000475$0.000855$0.855

1,000 results = $0.90 on Free, plus one Actor Start event at $0.00005 on Free when memory is 1 GB or the one-event minimum. 10,000 results = $9 on Free.

The Apify Free plan includes $5 of monthly platform usage credit. After one Actor Start event, that credit covers 5555 Product results on Free.

On this pay-per-event Actor, platform usage (compute, Apify Proxy traffic including residential, and storage) is included in the event prices and paid by the Actor developer. This Actor does not use pay-per-event plus usage, so you do not pay those platform usage charges on top.

How to use

  1. Add one host or URL per Store URLs entry (myshopify.com or a custom domain, with or without https://). A path is dropped, the host is lowercased, and stores run in sequence.
  2. Set Max products per store (default 100; 0 pages until a page returns no products).
  3. Leave One row per variant on for a row per SKU, or clear it for one row per product.
  4. Optionally add a case-insensitive handle or vendor substring. Leave description HTML on to keep body_html.
  5. Repeat with Apify Schedules. Daily is a reasonable starting point for price and availability checks; treat that cadence as a starting point only.
{
"storeUrls": ["gymshark.myshopify.com"],
"maxProducts": 10,
"rowPerVariant": true,
"includeBodyHtml": true,
"proxyConfiguration": {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]},
"disableUsageStats": false
}

Export the dataset as JSON or CSV, or read it through the Apify dataset API.

Input parameters

ParameterWhat it doesDefault
storeUrlsHosts or URLs, scraped in order. Each becomes that host's products.json URL. A blank entry is skipped.Empty. Form prefill: gymshark.myshopify.com and www.allbirds.com.
maxProductsStops after this many products per store, before variant rows are built. 0 pages through every non-empty page of 250. Minimum 0.100
rowPerVariantTrue writes one row per variant. False writes one row per product and leaves the six variant columns null.true
includeBodyHtmlTrue copies the store's body_html onto each row. False sets body_html to null. It does not change the row count.true
productHandleFilterKeeps products whose handle contains this substring, case-insensitive. Blank keeps all. Applied after fetch, so it does not pull extra pages to fill the cap.blank
vendorFilterKeeps products whose vendor contains this substring, case-insensitive. Blank keeps all. Same paging behavior as the handle filter.blank
proxyConfigurationWhen set, requests use that Apify Proxy configuration. If proxy setup fails, the run logs a warning and continues without a proxy.Omitted means no proxy. Form prefill: Apify Proxy, group RESIDENTIAL.
disableUsageStatsTrue skips the usage-statistics record described under Usage statistics.false

Limits and edge cases

Note: maxProducts counts products fetched per store, not dataset rows. Several variants on one product produce several rows when one row per variant is on.

Each products request uses a 30-second timeout. Pages are sequential, with no delay or concurrency input. A later-page failure saves nothing for that store and the run moves on; rows from stores that already finished stay. OUTPUT holds totalRows, rowPerVariant, scrapedAt (UTC), and stores (products_fetched and rows_pushed, or error and products 0).

ConditionWhat you seeWhat to do
storeUrls is missing or emptyLog warning. OUTPUT.error is no_store_urls. No dataset rows.Add at least one host or URL.
Blank line in the URL listThat entry is ignored. Other stores still run.Remove the blank line.
First page is an empty product listStore finishes with products_fetched 0 and rows_pushed 0. No error key.Confirm the host is the public storefront.
HTTP 404Log says the store was not found. OUTPUT error is store_not_found. No rows from that store.Check the host, or that /products.json is public on it.
Any other fetch or transport errorWarning in the log. OUTPUT error is the message trimmed to 300 characters. Later stores still run.Fix the host and run again. Earlier stores' rows remain.
Handle or vendor filter matches nothingProducts may be fetched while rows_pushed is 0.Clear the filter or use a shorter substring.
Proxy setup throwsWarning that the run is proceeding without a proxy.Continue, or set a valid Apify Proxy configuration.
Per-product modeFlat variant columns are null. Use price_min, price_max, or variants for prices.Turn one row per variant on when you need SKU rows.
Product has no variants in variant modeOne row, variant columns null, warning no_variants, confidence reduced by 0.20.Treat that row as product-level only.

FAQ

How much does it cost to scrape Shopify products?

See Pricing. A saved row is one Product event at that plan's price, the same in both row modes, plus Actor Start. Filtered-out products are not charged.

What if the dataset is empty?

Check OUTPUT for no_store_urls, products_fetched 0, rows_pushed 0, store_not_found, or error. Export rows already saved.

Why did one store fail while others succeeded?

Stores run in sequence. A timeout, a bad later page, or HTTP 404 drops that store only. If proxy setup fails, requests continue without a proxy.

Is reading this public Shopify data allowed under store ToS?

The Actor reads public /products.json and does not log in. Whether that use is allowed depends on the store's terms and the law that applies to your use case. This page does not say that your use is legal.

Note: This Actor is not affiliated with Shopify Inc.

Usage statistics

This Actor creates a small, content-free summary at the end of each run, used only to monitor reliability and improve this Actor. No input values, credentials or scraped data are sent.

A copy of the exact record for your run is saved as USAGE_STATS in your own Apify key-value store.

To opt out, set disableUsageStats to true in the input. Nothing is sent then.

Full list of collected fields