Shopify Products Scraper: Media, Currency & Related Products
Pricing
from $5.99 / 1,000 results
Shopify Products Scraper: Media, Currency & Related Products
Shopify Products Scraper — Scrape Shopify products with titles, prices, currency, images, videos, product media, variants, descriptions, and related products. Extract structured ecommerce data for product research, competitor analysis, catalog monitoring, and market insights.
Pricing
from $5.99 / 1,000 results
Rating
0.0
(0)
Developer
Scrapier
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Shopify Products Scraper: Media, Currency & Related Products
A Shopify products scraper that reads any storefront's public catalogue and returns typed JSON for every product — full pricing range, a verified currency, a typed media inventory (images, hosted video, external video and 3D models), and the store's own related-product graph. Every row is structured JSON, ready to pass straight into an LLM prompt, a spreadsheet, or a price-monitoring pipeline. No Shopify account, API key or app installation is required — just the storefront's own URL.
What is Shopify Products Scraper: Media, Currency & Related Products?
This Actor queries one or more Shopify storefronts — a full catalogue URL (https://rothys.com) or a single product URL (https://rothys.com/products/some-handle) — and returns a normalized JSON row per product, plus a child row per related product the store recommends. It reads the same public endpoints a browser already loads (/products.json, /products/<handle>.js, /products/<handle>.json), so no Shopify login, Storefront access token or Admin API app is needed for any store you point it at.
What sets this Actor apart from a plain product-list scrape:
- 💱 Verified currency — reads the storefront's declared currency and cross-checks it against the currency each price is actually quoted in
- ✅ Verified price units — recomputes every variant price from a second storefront source and flags disagreement instead of trusting one surface
- 📊 Purchasable-only price range —
priceMin/priceMaxare built only from variants a buyer can actually check out with - 🖼️ Typed media inventory — images, hosted video, external (YouTube/Vimeo) video and 3D models, normalized into one array with real dimensions and durations
- 🔀 Related-product graph — the store's own product recommendations, collected as child rows with rank
- 🌐 Optional proxy routing — direct by default, escalating through Apify Proxy groups only when a storefront starts refusing requests
What data can you get with Shopify Products Scraper: Media, Currency & Related Products?
The Actor returns three row types in one dataset — product rows, related-product rows, and store-status rows for stores it could not read — plus a nested media object inside every product row.
| Result type | Extracted fields | Primary use case |
|---|---|---|
| Product | title, handle, product_id, vendor, product_type, price, priceMin/priceMax, currency, storeCurrency, mediaCount, variantCount, tags, full_data (full raw record) | Catalogue extraction, pricing feeds, product enrichment |
Media asset (nested in media[]) | position, mediaType, url, alt, width, height, durationMs, previewImageUrl, variantIds | Image/video pipelines, PIM ingestion, visual search indexes |
Related product (child row, type: "related") | parentProductId, relatedProductId, relatedTitle, relatedPrice, relatedAvailable, rank | Merchandising analysis, cross-sell mapping, recommendation audits |
| Store status | storeStatus, catalogueComplete, catalogueStopReason, productsDiscovered | Monitoring which storefronts were reachable in a run |
💱 Verified price, currency and typed media
Every product row carries pricing and media as verified facts, not raw pass-through. priceMin/priceMax are computed only from variants that are actually purchasable, so a sold-out placeholder variant can't drag the minimum to zero. priceUnitVerified is true only when an independently recomputed price matches the storefront's own published minor-unit price for the same variant. currencyMatchesStore is false — not hidden — when a storefront quotes a different currency than the one it declares. The media array carries every asset type Shopify supports, not just images:
{"priceMin": "48.00","priceMax": "58.00","priceVaries": true,"compareAtPriceMax": "68.00","discountPercent": 15,"isOnSale": true,"priceUnitVerified": true,"priceUnitCheckedVariants": 4,"currency": "USD","storeCurrency": "USD","currencyMatchesStore": true,"mediaCount": 6,"imageCount": 4,"videoCount": 1,"has3dModel": true,"hasVideo": true}
🔀 Related-product graph
When includeRelatedProducts is on, the Actor calls the store's own recommendations endpoint for every product and emits each result as a separate type: "related" child row, ranked the way the storefront ranks them:
{"type": "related","isChild": true,"parentProductId": 7891234567,"relatedProductId": 7891298765,"relatedTitle": "The Original Flat","relatedPrice": "48.00","relatedAvailable": true,"rank": 1}
How does Shopify Products Scraper: Media, Currency & Related Products differ from the official Shopify API?
Shopify's own Storefront and Admin APIs return the same underlying product data, but only for a store you or the merchant control — this Actor reads the same public storefront JSON any visitor's browser loads, across any number of independent stores in one run.
| Feature | Shopify Storefront / Admin API | Shopify Products Scraper |
|---|---|---|
| Access requirement | A per-store Storefront access token or an installed Admin API app, generated by the store owner (shopify.dev, checked 2026‑08‑15) | None — no token, app install, or store-owner permission needed |
| Cross-store queries | Scoped to one store per token | One run accepts any number of independent storefront URLs |
| Media types in one call | Requires querying the GraphQL media union per type | Images, hosted video, external video and 3D models normalized into one typed array automatically |
| Currency cross-check | Not provided by either API | storeCurrency vs. quoted currency compared on every row |
| Price-unit verification | Not provided | Every variant price independently recomputed and cross-checked |
| Related-product graph | Requires a separate productRecommendations query per product with the token | Collected automatically per product, emitted as ranked child rows |
| Setup time | Register a custom app, request scopes, store a secret token per shop | Enter a URL and start the run |
Use the official API when you own the store and need write access, orders, customers or inventory levels — none of which this Actor touches. Use this Actor when you need read-only catalogue, pricing, media and related-product data across stores you don't administer.
How to scrape Shopify with Shopify Products Scraper: Media, Currency & Related Products?
- Open the Actor on its Apify Store page and click Try for free (or Start, if you already have it).
- Add one or more storefront or product URLs to
targets— for example["https://rothys.com", "https://www.deathwishcoffee.com"]. - Set the query controls that matter for your job:
maxProductsper store,mediaTypesto keep,maxRelatedPerProduct, and whether to verify currency and price units. - Click Start to run the Actor.
- Download results as JSON, CSV, Excel or the other formats Apify's dataset export offers, or stream them via the API.
How to run multiple queries in one job
targets is a list — add every storefront or product URL you want in a single run, and the Actor works through them in order, applying maxProducts per store URL independently. For input files built for the original actor, startUrls and maxItems are kept as aliases: anything in startUrls is merged into targets, and maxItems is used only when maxProducts is left empty.
⬇️ Input
The Actor takes storefront or product URLs plus a set of toggles for how much detail to compute per product. Nothing is required — leaving everything blank runs the one demo store prefilled in targets.
| Parameter | Required | Type | Constraints | Description |
|---|---|---|---|---|
targets | No | array | editor: stringList | One or more Shopify storefront URLs. A store URL (https://rothys.com) scrapes its catalogue; a single product URL (https://rothys.com/products/some-handle) scrapes just that product. Example: ["https://rothys.com", "https://www.deathwishcoffee.com"]. Default is one demo store. |
startUrls | No | array | editor: stringList | Kept so input files written for the original actor keep working. Anything listed here is merged with targets. Leave empty if you filled in targets. |
resolveStoreCurrency | No | boolean | default true | Reads the storefront's own declared currency and reports it as storeCurrency, then compares it to the currency the prices were actually quoted in. Sets currencyMatchesStore so a storefront that quotes a different currency than it declares is visible instead of silent. |
includePriceRange | No | boolean | default true | Adds priceMin, priceMax, priceVaries, compareAtPriceMax, compareAtPriceVaries, discountPercent and isOnSale. The range is built from purchasable variants only, so sold-out and placeholder variants cannot drag the minimum to zero. |
verifyPriceUnits | No | boolean | default true | Independently recomputes every variant price from a second storefront source and checks the two agree exactly, then reports the result as priceUnitVerified plus priceUnitCheckedVariants. Guards against a hundred-fold unit error that would otherwise look like ordinary data. |
treatZeroCompareAtAsNull | No | boolean | default true | Shopify themes often store a strike-through price as an empty string or 0 when there is no sale. With this on, those become null so no row implies a 100% discount. Turn it off to receive the raw value exactly as published. |
includeMediaInventory | No | boolean | default true | Adds mediaCount and a media array holding each asset's position, type, URL, alt text, dimensions and (for video) duration and preview frame, plus imageCount, videoCount, hasVideo, has3dModel and featuredImageUrl. URLs and metadata only — no files are ever fetched, stored or bundled. |
mediaTypes | No | array | default ["image", "video", "external_video", "model"]; editor: select | Keep only these asset types in the media array and in the per-type counts. Example: choose Image + Video to drop 3D models. |
includeRelatedProducts | No | boolean | default true | Collects the products the storefront itself recommends alongside each product and emits them as separate child rows (type = "related", isChild = true) carrying parentProductId, relatedProductId, relatedTitle, relatedPrice, relatedAvailable and rank. Also mirrored to a dedicated dataset for this run. |
maxRelatedPerProduct | No | integer | default 5; min 0; max 10 | How many related products to keep for each product, ranked as the storefront ranks them. Example: 5 on a 30-product run yields up to 150 related rows. Set 0 to turn the graph off. |
maxProducts | No | integer | min 0; prefill 30 | Upper bound on how many products are returned for each store URL. Example: maxProducts=30 with 3 stores returns up to 90 product rows. Set 0 for the whole catalogue. |
maxItems | No | integer | min 0 | Kept so input files written for the original actor keep working. Used only when maxProducts is left empty. |
proxyConfiguration | No | object | editor: proxy; prefill {"useApifyProxy": false} | Choose the connection route used to reach the storefronts. Leave off to connect directly. Large catalogues and stores that limit how fast they answer are more reliable with a proxy selected. |
Example input:
{"targets": ["https://rothys.com","https://www.deathwishcoffee.com/products/nitro-cold-brew-coffee"],"maxProducts": 50,"mediaTypes": ["image", "video"],"includeRelatedProducts": true,"maxRelatedPerProduct": 5,"resolveStoreCurrency": true,"verifyPriceUnits": true,"proxyConfiguration": { "useApifyProxy": true }}
Common pitfall: mixing a bare domain with www. and without it in the same run (rothys.com and www.rothys.com) is treated as two separate targets, since the Actor does not assume they resolve to the same catalogue — use whichever form the store actually redirects to, or list only one.
⬆️ Output
Results are typed, normalized JSON, one row per product plus a child row per related product and a status row for any store that couldn't be read. Export as JSON, CSV, Excel, XML, HTML table or RSS directly from the dataset, or pull it with the Apify API / apify-client.
⚠️ Every pushed row charges the row_result event — including a store_status row for a store that was locked, unreachable, or had no readable catalogue. If you're counting billable rows against expected product counts, filter on type == "product" (or != "store_status") rather than assuming only successful product rows are charged.
A few fields are deliberately null instead of 0 or false when the Actor genuinely could not determine the value — that's not the same as a confirmed negative:
mediaCount,imageCount,videoCount,hasVideo,has3dModelandmediaTypesPresentarenull(not0/false) when the per-product script record couldn't be read, orincludeMediaInventoryis off —0always means media was checked and confirmed absent.relatedCountandrelatedProductIdsarenullwhen the recommendations lookup itself failed to answer, versus an empty list when the store genuinely recommends nothing.availableVariantCountisnullwhen no surface published availability for any variant on that product.
Scraped results
[{"type": "product","isChild": false,"scrapedAt": "2026-08-15T09:12:41Z","store_url": "https://rothys.com","product_url": "https://rothys.com/products/the-flat","product_id": 7891234567,"title": "The Flat","vendor": "Rothy's","product_type": "Flats","price": "48.00","compare_at_price": "68.00","tags": ["bestseller", "washable"],"total_found": 214,"successful": 1,"full_data": { "product": { "id": 7891234567, "...": "full raw Shopify product record" } },"handle": "the-flat","storeDomain": "rothys.com","canonicalProductUrl": "https://rothys.com/products/the-flat","canonicalUrlSource": "storefront_product_record","productsDiscovered": 214,"catalogueComplete": true,"catalogueStopReason": "catalogue_exhausted","storeStatus": "ok","currency": "USD","currencySource": "product_price_currency","storeCurrency": "USD","currencyMatchesStore": true,"priceUnitVerified": true,"priceUnitCheckedVariants": 4,"priceUnitMismatch": null,"variantCount": 4,"availableVariantCount": 3,"productAvailable": true,"publishedAt": "2023-02-01T10:00:00-05:00","updatedAt": "2026-08-10T14:22:03-04:00","createdAt": "2022-11-05T08:00:00-05:00","priceMin": "48.00","priceMax": "58.00","priceMinMinor": 4800,"priceMaxMinor": 5800,"priceVaries": true,"compareAtPriceMax": "68.00","compareAtPriceMaxMinor": 6800,"compareAtPriceVaries": false,"discountPercent": 15,"isOnSale": true,"priceRangeVariants": 3,"priceRangeExcludedUnavailable": 1,"priceRangeUnknownAvailability": 0,"priceOutlierFlagged": false,"priceOutlierNote": null,"mediaCount": 6,"imageCount": 4,"videoCount": 1,"externalVideoCount": 0,"model3dCount": 1,"hasVideo": true,"has3dModel": true,"mediaTypesPresent": ["image", "model", "video"],"media": [{"position": 1,"mediaType": "image","url": "https://cdn.shopify.com/s/files/1/0000/0001/products/the-flat-1.jpg","alt": "The Flat in Black","width": 2048,"height": 2048,"aspectRatio": 1.0,"durationMs": null,"previewImageUrl": null,"externalVideoHost": null,"externalVideoId": null,"variantIds": [40012345, 40012346]}],"featuredImageUrl": "https://cdn.shopify.com/s/files/1/0000/0001/products/the-flat-1.jpg","relatedCount": 2,"relatedProductIds": [7891298765, 7891298766]},{"type": "related","isChild": true,"scrapedAt": "2026-08-15T09:12:44Z","store_url": "https://rothys.com","parentProductId": 7891234567,"parentHandle": "the-flat","relatedProductId": 7891298765,"relatedHandle": "the-original-flat","relatedTitle": "The Original Flat","relatedPrice": "48.00","relatedPriceMinor": 4800,"relatedCompareAtPrice": null,"relatedAvailable": true,"relatedVendor": "Rothy's","relatedProductType": "Flats","relatedProductUrl": "https://rothys.com/products/the-original-flat","rank": 1,"product_id": 7891298765,"handle": "the-original-flat","title": "The Original Flat","vendor": "Rothy's","product_type": "Flats","price": "48.00","product_url": "https://rothys.com/products/the-original-flat","currency": "USD","storeCurrency": "USD"},{"type": "store_status","isChild": false,"scrapedAt": "2026-08-15T09:13:02Z","store_url": "https://example-locked-store.myshopify.com","storeDomain": "example-locked-store.myshopify.com","storeStatus": "storefront_locked","catalogueComplete": false,"catalogueStopReason": "listing_incomplete","productsDiscovered": null,"total_found": null,"storeCurrency": null}]
How can I use the data extracted with Shopify Products Scraper: Media, Currency & Related Products?
- 📊 Ecommerce and pricing analysts: track
priceMin,priceMax,discountPercentandisOnSaleacross a set of competitor storefronts to build a pricing feed that flags undercuts and sale starts. - 🤖 AI engineers and LLM developers: feed the structured
productandmediaJSON directly into a retrieval-augmented catalogue agent or a shopping assistant, withfull_dataavailable for anything the normalized fields don't cover. - 🔬 Market researchers: compare
relatedProductIdsandrelatedCountacross stores to map how merchants cross-sell within a category. - 🛍️ Merchandising and product teams: audit
mediaTypesPresentandvariantCountacross your own or a partner's catalogue to spot listings missing video or 3D assets.
How do you monitor Shopify pricing and catalogue changes over time?
Repeated-run monitoring turns a single snapshot into a change feed. Run the same targets on a schedule, keep each run's dataset, and diff the fields that actually move: priceMin/priceMax for price changes, isOnSale/discountPercent for markdown events, productAvailable/availableVariantCount for stock changes, and relatedProductIds/mediaCount for catalogue and merchandising changes. Because priceUnitVerified and currencyMatchesStore are recomputed every run, a store that silently starts publishing a mismatched currency or an unverifiable price shows up as a flag flip rather than a value you'd have to notice by eye.
A practical loop: schedule a run across your keyword set of storefronts, store each run's dataset by date, then compare the current priceMin/isOnSale/mediaCount against the previous run and alert on the deltas that matter to you — a new sale, a restock, or a currency mismatch appearing. This Actor has no built-in scheduler; use an Apify Schedule on the Actor to trigger runs automatically, and read consecutive datasets through the API to compute the diff.
Integrate Shopify Products Scraper: Media, Currency & Related Products and automate your workflow
Shopify Products Scraper: Media, Currency & Related Products works with any language or tool that can send an HTTP request.
REST API with Python
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_API_TOKEN>")run = client.actor("<store-owner>/shopify-products-scraper-media-currency-related-products").call(run_input={"targets": ["https://rothys.com"],"maxProducts": 50,"includeRelatedProducts": True,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():if item.get("type") == "product":print(item["title"], item.get("priceMin"), item.get("currency"))
Scheduled monitoring and delivery
The Actor has no built-in webhook delivery. Use an Apify Schedule to trigger repeated runs and an Apify webhook on the run-succeeded event to push each dataset to your own endpoint, or poll the dataset via the API on your own interval.
⚖️ Is it legal to scrape Shopify product data?
Scraping publicly listed product data is generally lawful — this Actor reads only what any storefront visitor's browser already loads, no login or account required. In hiQ Labs v. LinkedIn (9th U.S. Circuit Court of Appeals, 2019, reaffirmed on remand April 2022), the court held that accessing data on a public website without authentication does not violate the U.S. Computer Fraud and Abuse Act. Shopify product listings, prices and media are business and catalogue data, not personal data, so GDPR and CCPA — which govern personal data about individuals — do not attach to what this Actor returns; the relevant framework instead is each storefront's own terms of service and, in some jurisdictions, database-rights law protecting the compiled catalogue itself. Scraping for AI training and scraping for operational price monitoring carry different risk profiles under a store's terms. Consult your legal team for commercial use cases involving bulk data storage.
❓ Frequently asked questions
How many products does Shopify Products Scraper: Media, Currency & Related Products return per store?
By default, up to 30 products per store URL (maxProducts prefill). Set maxProducts to 0 for the whole catalogue, or any other number as your own cap. Internally, catalogue paging reads 250 products per page for up to 200 pages before stopping regardless of maxProducts — a ceiling from the source code that only matters on catalogues larger than 50,000 products.
Does this Actor need a Shopify account, Storefront token or app installation?
No. It reads the same public JSON endpoints (/products.json, /products/<handle>.js, /products/<handle>.json) a storefront visitor's browser already loads. No login, Storefront access token or Admin API app is required for any store you point it at.
Does Shopify Products Scraper: Media, Currency & Related Products extract related products?
Yes — when includeRelatedProducts is on (default), it calls the store's own recommendations endpoint per product and emits each result as a type: "related" child row with parentProductId, relatedProductId, relatedTitle, relatedPrice, relatedAvailable and rank. If the recommendations lookup itself doesn't answer, relatedCount is null rather than 0, so "we don't know" is never reported as "there are none."
How does the Actor verify price and currency data?
verifyPriceUnits independently recomputes each variant's price from a second storefront surface and reports agreement as priceUnitVerified plus priceUnitCheckedVariants — this guards against the hundred-fold unit mix-up that occurs when a decimal price ("19.99") and a minor-unit price (1999) are confused. resolveStoreCurrency separately reads the store's declared currency and compares it to what each price is actually quoted in, exposing a mismatch through currencyMatchesStore instead of silently trusting one value.
What media types does the Actor extract?
Images, hosted video, external video (YouTube/Vimeo) and 3D models — controlled by the mediaTypes input, which defaults to all four. Each asset in the media array carries its position, type, absolute URL, alt text, dimensions, and for video, duration and a preview frame. No files are downloaded, stored or bundled — URLs and metadata only.
How does the Actor handle a locked or unreachable storefront?
A storefront redirecting to its own /password lock page is reported as storeStatus: "storefront_locked"; one that fails to answer at all is reported as store_unreachable. Either way, the Actor pushes a single store_status row for that store instead of guessing at product data, and that row still charges the row_result event.
How does the Actor handle rate limiting and anti-bot responses?
Requests are politely paced and retried up to 4 times per address with exponential backoff (capped at 8 seconds) plus jitter. On a soft refusal (HTTP 403, 406, 429, 451 or 503), the connection escalates from a direct connection to an Apify Proxy group for the rest of the run rather than retrying the same route indefinitely. A 404 or 410 is treated as permanently dead and is not retried.
How do I use this Actor to monitor a storefront's pricing and catalogue over time?
Schedule repeated runs over the same targets using an Apify Schedule, store each run's dataset, and diff priceMin, discountPercent, isOnSale, productAvailable and mediaCount against the previous run to catch price changes, sale starts, restocks or new media. See "How do you monitor Shopify pricing and catalogue changes over time?" above.
Does Shopify Products Scraper: Media, Currency & Related Products work with Claude, ChatGPT and AI agent frameworks?
It is callable as an HTTP endpoint through the Apify API by any agent framework that can make a request, so an agent can trigger a run and receive structured product JSON to ground its answers — a scoped tool call rather than a general web search.
Can I use this Actor without managing proxies or Shopify credentials?
Yes. No Shopify login, token or app is needed for any store, and proxyConfiguration is entirely optional — the Actor connects directly by default and only routes through Apify Proxy groups when a storefront starts refusing requests, or when you turn a proxy on yourself for a large or slow catalogue.
💬 Your feedback
Found a bug or missing a field? Let us know through the Actor's Issues tab on Apify or the Scrapier support channel — reports of a wrong field or an edge case a storefront exposes help keep this Actor accurate.