E-commerce Platform Detector: Identify & Extract Any Store
Pricing
from $0.74 / 1,000 record scrapeds
E-commerce Platform Detector: Identify & Extract Any Store
Point it at any online store and it identifies the platform (Shopify, WooCommerce, BigCommerce, Squarespace or Magento) then extracts the catalogue using that platform's public API.
Pricing
from $0.74 / 1,000 record scrapeds
Rating
0.0
(0)
Developer
Arman Hossain
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
21 days ago
Last modified
Categories
Share

E-commerce Platform Detector takes a storefront URL, works out which platform it runs on, Shopify, WooCommerce, BigCommerce, Squarespace or Magento, and then pulls the catalogue through that platform's own public endpoint. One input, one output shape, whatever the store is built on.
Every record carries the platform, a confidence score and the exact evidence behind it, so you can audit the detection instead of trusting it.
Agent skill: SKILL.md
https://api.apify.com/v2/key-value-stores/t7YoTxpZEJOWvw4Ug/records/ecommerce-platform-detector.md
How detection works
Two stages, both cheap:
- Passive fingerprinting, the store's home page is fetched once and scored against response headers (
powered-by: Shopify,server: Squarespace,x-magento-*),Set-Cookienames (_shopify_essential,woocommerce_*,Shopper-Pref), and markup markers (cdn11.bigcommerce.com,/wp-content/plugins/woocommerce,Static.SQUARESPACE_CONTEXT,/static/version*/frontend/). - Active confirmation, the candidate platform's catalogue endpoint is probed directly. A hit both proves the platform and proves the catalogue is reachable, which is why probes outweigh any single passive marker.
Stage 2 matters more than it sounds. A headless storefront can serve markup with zero platform markers in it, bulk.com renders a custom front end whose HTML mentions Magento nowhere, and is still identified with confidence 70 because /graphql and /rest/V1/directory/currency both answer.
Scores are additive and capped at 100. Below 30 the store is reported as platform: "unknown" with whatever evidence was found, never as an error.
What you get
| Output field | Meaning |
|---|---|
store, storeUrl | Hostname and canonical origin after redirects |
detectedPlatform | shopify, woocommerce, bigcommerce, squarespace, magento or unknown |
confidence | 0-100. Anything at 30 or above named a platform |
detectionSignals | The individual markers that produced the score, each tagged header:, cookie:, html: or probe: |
extractionMethod | Which route the products came from, see the table below |
productId, sku, handle | Platform-native identifiers |
title, vendor, productType | Product name, brand and category, where the platform exposes them |
price, compareAtPrice, currency | Lowest current price, the struck-through price if on sale, and the ISO currency code |
available | Whether any variant is purchasable |
variantCount | Number of variants |
images | Up to 10 image URLs |
url | Direct link to the product page |
scrapedAt | Run timestamp |
In detectOnly mode each record instead carries platformScores (every platform's score, not just the winner), httpStatus and finalUrl.
A RUN_SUMMARY record in the key-value store holds a per-store breakdown, a platform histogram, the filters used and any store that failed.
Extraction routes
| Platform | Method | Endpoint |
|---|---|---|
| Shopify | shopify-products-json | /products.json?limit=250&page=N, currency from /meta.json |
| WooCommerce | woocommerce-store-api | /wp-json/wc/store/v1/products (falls back to the pre-v1 path) |
| Squarespace | squarespace-format-json | Store collections discovered from the sitemap, read via ?format=json |
| Magento | magento-graphql | POST /graphql with a paged products(filter: {}) query |
| BigCommerce, unknown, or any closed API | jsonld-sitemap | Product URLs from robots.txt / sitemap.xml / xmlsitemap.php, then schema.org Product JSON-LD from each page |
Extraction degrades. It does not fail. If a store is confidently Shopify but has /products.json switched off, the Actor logs that and falls back to sitemap + JSON-LD rather than returning nothing. BigCommerce has no anonymous catalogue API at all, so it always takes the JSON-LD route, and still returns structured products.
Common use cases
Audit a competitor set on mixed platforms. One input, one output schema, regardless of what each competitor is built on.
{"storeUrls": ["https://www.allbirds.com","https://barefootbuttons.com","https://www.berlinpackaging.com","https://www.aaksonline.com"],"maxProductsPerStore": 250}
Qualify e-commerce leads by platform. Detection only, one cheap record per domain, no catalogue.
{"storeUrls": ["allbirds.com", "gymshark.com", "bulk.com", "aaksonline.com"],"detectOnly": true}
Build a universal price monitor. Restrict to the platforms whose APIs give you exact prices, and run it on a schedule.
{"storeUrls": ["https://www.allbirds.com", "https://barefootbuttons.com"],"platforms": ["shopify", "woocommerce"],"maxProductsPerStore": 1000}
Quick start
One store, first 100 products:
{"storeUrls": ["https://www.allbirds.com"]}
Just tell me what it runs on:
{"storeUrls": ["allbirds.com"],"detectOnly": true}
Input
| Field | Type | Default | Notes |
|---|---|---|---|
storeUrls | array | - | Required. Store home pages. Bare domains work; redirects are followed. |
detectOnly | boolean | false | Emit one detection record per store and skip extraction. |
maxProductsPerStore | integer | 100 | Cap per store. 0 = no limit. |
platforms | array | [] | Restrict extraction to these platforms. Empty = all. Add unknown to keep unidentified stores. |
Combinations that make sense together:
detectOnly: true+ a longstoreUrlslist: the lead-qualification mode. One record and roughly two to four requests per domain.platforms+ a long list: everything is still detected (and reported inRUN_SUMMARY.stores), but only matching stores are extracted. You get the tech-stack census for free while paying for products from just the platforms you care about.- A locale sub-path in
storeUrls. Passikea.com/us/en/rather thanikea.com. Detection normalises to the origin, but URLs under the sub-path you gave are preferred during sitemap extraction and used when building Magento product links. maxProductsPerStore: 0on a big Shopify store: expect tens of thousands of products; raise the run timeout to match.
Output example
{"store": "www.allbirds.com","storeUrl": "https://www.allbirds.com","detectedPlatform": "shopify","confidence": 100,"detectionSignals": ["header: powered-by: Shopify response header","cookie: _shopify_* session cookie","html: cdn.shopify.com asset host","probe: /products.json returns a Shopify product array","probe: /meta.json exposes a myshopify_domain"],"extractionMethod": "shopify-products-json","productId": 7292464955472,"title": "Men's Cruiser - Shadow Blue (Natural White Sole)","handle": "mens-cruiser-shadow-blue-natural-white-sole","vendor": "Allbirds","productType": "Shoes","price": 105,"compareAtPrice": null,"currency": "USD","available": true,"sku": "A12856M080","variantCount": 13,"images": ["https://cdn.shopify.com/s/files/1/1104/4168/files/All-birds_0010.png?v=1783535519"],"url": "https://www.allbirds.com/products/mens-cruiser-shadow-blue-natural-white-sole","scrapedAt": "2026-08-06T11:49:23.335Z"}
A detectOnly record:
{"store": "www.bulk.com","storeUrl": "https://www.bulk.com","detectedPlatform": "magento","confidence": 70,"detectionSignals": ["probe: Magento GraphQL products query succeeds at /graphql","probe: Magento REST answers at /rest/V1/directory/currency"],"platformScores": { "magento": 70 },"extractionMethod": "magento-graphql","httpStatus": 200,"finalUrl": "https://www.bulk.com/uk/","scrapedAt": "2026-08-06T11:52:04.118Z"}
RUN_SUMMARY looks like this:
{"storesRequested": 5,"storesFailed": 0,"failures": [],"stores": [{ "store": "www.allbirds.com", "detectedPlatform": "shopify", "confidence": 100, "detectionSignals": ["."], "extractionMethod": "shopify-products-json", "products": 291 },{ "store": "barefootbuttons.com", "detectedPlatform": "woocommerce", "confidence": 100, "detectionSignals": ["."], "extractionMethod": "woocommerce-store-api", "products": 61 },{ "store": "www.berlinpackaging.com", "detectedPlatform": "bigcommerce", "confidence": 100, "detectionSignals": ["."], "extractionMethod": "jsonld-sitemap", "products": 60 }],"platformBreakdown": { "shopify": 1, "woocommerce": 1, "bigcommerce": 1 },"itemsSaved": 412,"filters": { "detectOnly": false, "maxProductsPerStore": 0, "platforms": [] },"finishedAt": "2026-08-06T11:53:41.902Z"}
Limits and behaviour
- An unknown platform is a result, not an error. Stores below the confidence threshold are reported as
platform: "unknown"with their evidence, and still go through sitemap + JSON-LD extraction. In testing,ikea.com, which matches none of the five fingerprints, returned fully structured products this way. - Confidence is additive and capped at 100. Two independent probes plus a header marker will hit the cap; a single weak HTML marker will not clear the threshold of 30 on its own.
- WordPress is not WooCommerce. Generic WordPress markers score low on purpose; the decisive signal is the Store API answering at
/wp-json/wc/store/v1/products. - Prices are normalised. WooCommerce's Store API returns money in minor units (
"195"withcurrency_minor_unit: 2); this Actor divides it out, so you get1.95. Squarespace variant prices come frompriceMoney, not the frequently-zero product-level field. priceis the lowest current variant price, not the price of a specific variant.compareAtPriceis the struck-through original where the platform reports one.- Magento product URLs are the Magento-canonical path. For a standard install that is the live URL. Heavily customised or headless storefronts sometimes route products elsewhere, in which case the link points at the canonical path rather than the custom one, the price, SKU and stock status are still exact.
- JSON-LD extraction is only as good as the store's markup. Products without a schema.org
Productblock are skipped rather than guessed at, and the Actor reports how many sitemap URLs it scanned in the log and in the failure note. - Sitemap crawling is bounded. At most 12 sitemap files and 6 child sitemaps from an index, with product-shaped URLs prioritised.
- Bare domains are recovered. Plenty of stores serve a valid certificate on
www.and a broken chain on the apex,berlinpackaging.comis one. If the host you gave fails outright, the other variant is tried once before the store is written off. - One store failing never aborts the run. Detection and extraction failures are recorded in
RUN_SUMMARY.failuresand the run continues. - Transient errors are retried. 429 and 5xx get up to three attempts with linear backoff. A 4xx from a probe is treated as a signal (that platform is absent), not a failure.
- Public catalogue data only. No authentication, no personal data, no access-control bypass, every endpoint used is one the platform publishes for front-end code to read.
Verified against real stores
Detection and extraction were run against five live storefronts on five different platforms, plus one store matching none of the fingerprints:
| Store | Detected | Confidence | Route | Result |
|---|---|---|---|---|
allbirds.com | shopify | 100 | shopify-products-json | 291 products, powered-by header + _shopify_* cookies + both probes |
barefootbuttons.com | woocommerce | 100 | woocommerce-store-api | 61 products, plugin asset path + Store API probe |
berlinpackaging.com | bigcommerce | 100 | jsonld-sitemap | 60/60 requested products, all with price, SKU and images; no anonymous API, so JSON-LD was used |
aaksonline.com | squarespace | 100 | squarespace-format-json | 41 products, server: Squarespace + ?format=json probe |
bulk.com/uk/ | magento | 70 | magento-graphql | Zero HTML markers, headless front end; identified entirely by the /graphql and /rest/V1 probes |
ikea.com/us/en/ | unknown | 0 | jsonld-sitemap | No fingerprint matched; products still extracted from schema.org markup, in USD from the /us/en/ catalogue |
API example
curl -X POST "https://api.apify.com/v2/acts/arman-bd~ecommerce-platform-detector/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H "Content-Type: application/json" \-d '{"storeUrls": ["https://www.allbirds.com", "https://barefootbuttons.com"],"maxProductsPerStore": 50}'
JavaScript example
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_TOKEN' });const run = await client.actor('arman-bd/ecommerce-platform-detector').call({storeUrls: ['allbirds.com', 'barefootbuttons.com', 'bulk.com'],detectOnly: true,});const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const s of items) console.log(`${s.store} → ${s.detectedPlatform} (${s.confidence})`);
Defaults: 2 GB memory, 30 min timeout.
FAQ
Do I need a proxy? No. Proxy configuration is not required to run this Actor.
Do I need an account on the source? No, on any of the five platforms.
What happens if a store is unavailable? It is recorded in RUN_SUMMARY.failures and the run continues with the rest. The Actor only throws if no store could be processed at all.
Why did a store come back as unknown? Either it runs on a platform outside the five fingerprinted here (Salesforce Commerce Cloud, Wix, Ecwid, custom builds), or it is a headless front end whose APIs are not at the standard paths. Check platformScores in detectOnly mode to see whether anything scored at all, products may still have been extracted from JSON-LD.
Why does a BigCommerce store use jsonld-sitemap? BigCommerce's storefront GraphQL API requires a bearer token that stores do not publish, so there is no anonymous catalogue endpoint. Sitemap plus schema.org markup is the honest route, and it works.
Can I get variant-level prices? Not as separate records, price is the lowest live variant price and variantCount tells you how many there are. This keeps one row per product across all five platforms.
Why is currency sometimes null? Not every store declares one in a machine-readable place. Shopify reads it from /meta.json, WooCommerce and Squarespace return it per product, and JSON-LD supplies priceCurrency when the store publishes it.
Can I schedule it? Yes, it is designed for scheduled runs. Diff on productId plus price for price monitoring, or on detectedPlatform to catch re-platforming.
Can I integrate it with something else? Yes, Apify API, client libraries, webhooks, scheduled runs, dataset exports (JSON/CSV/Excel) or MCP. Output is structured JSON.