E-commerce Product Scraper & JSON-LD Extractor avatar

E-commerce Product Scraper & JSON-LD Extractor

Pricing

Pay per usage

Go to Apify Store
E-commerce Product Scraper & JSON-LD Extractor

E-commerce Product Scraper & JSON-LD Extractor

Extract product prices, availability, images, identifiers and variants from public product pages. Discover URLs from store sitemaps, filter by data completeness, and export JSON or CSV. Free-plan sample: up to 25 pages per run.

Pricing

Pay per usage

Rating

0.0

(0)

Developer

Scopras Data Labs

Scopras Data Labs

Maintained by Community

Actor stats

0

Bookmarked

18

Total users

8

Monthly active users

16 days ago

Last modified

Share

Turns product pages into one clean row each — parsed prices, normalised stock status, variants, absolute image URLs — from any storefront, not just Shopify.

Give it product URLs, or give it a store's homepage and let it find them.

{
"startUrls": [{ "url": "https://www.gymshark.com" }],
"discoverProducts": true,
"maxProducts": 10,
"minCompleteness": 50
}

Illustrative output shape (not a live product quote). Every field is flat — no nested objects or arrays — so the Console's CSV/Excel export button renders a clean table without opening a single item:

{
"name": "Legacy Fitted T-Shirt",
"brand": "Gymshark",
"sku": "GSTS-4471",
"price": 32,
"priceCurrency": "USD",
"availability": "InStock",
"inStock": true,
"imageCount": 1,
"primaryImage": "https://cdn.shopify.com/s/files/…/legacy-tee.jpg",
"imagesJson": "[\"https://cdn.shopify.com/s/files/…/legacy-tee.jpg\"]",
"variantCount": 2,
"variantsJson": "[{\"name\":\"Legacy Tee — S\",\"sku\":\"GSTS-4471-S\",\"price\":32,\"availability\":\"InStock\"},{\"name\":\"Legacy Tee — M\",\"sku\":\"GSTS-4471-M\",\"price\":32,\"availability\":\"OutOfStock\"}]",
"source": "jsonld",
"completeness": 1,
"missingFields": [],
"ok": true
}
  • price / priceCurrency — the price is always a clean number with the currency symbol and thousands/decimal formatting resolved, in a column separate from its ISO currency code (see "What the extractor handles" below for the locale-parsing rule).
  • inStock — a plain boolean derived from availability (null when the page gave no availability signal at all), for price monitors and feeds that just need yes/no rather than nine schema.org spellings.
  • imageCount / primaryImage / imagesJson and variantCount / variantsJson — the genuinely nested parts of a product (multiple images, per-variant price/sku/stock) are summarised into flat columns (imageCount, variantCount, primaryImage) and the full detail is kept as a JSON string you can JSON.parse() back into an array on re-import, instead of a raw array that CSV/Excel would render unreadably.

Pricing and free-plan sample

The Pricing tab shows the current price. Unreachable pages and rows below your completeness filter are never charged.

Apify Free plans: up to 25 product pages per run. Paid plans can process larger batches within your configured limit and run budget. This is a per-run sample limit. The prefilled input now discovers 10 products from a store sitemap with a 50% completeness filter; replace the example store with your target.

To scrape individual product URLs, turn discovery off. To process a whole store, turn it on. Set a maximum total charge before starting a larger job.

What the extractor handles

Prices come out as numbers, in the right magnitude. "1.299,90" and "1,299.90" are the same amount written by two halves of the world. Returning the string hands you a problem you discover in row 40,000; guessing wrong makes it a thousandfold error. Both are parsed, and anything genuinely unreadable — "call for pricing" — comes back absent rather than as 0.

Variants are not lost. A ProductGroup keeps name and brand on the parent and SKU, price and stock on each child. Read either node alone and you get half a product. Both are read, and every variant is returned with its own row of fields.

Non-English stores stay legible. Pages served as windows-1254 or ISO-8859-9 are decoded in the encoding the server declared, and HTML entities are resolved with case respected — Ç is Ç, ç is ç. No mojibake, no ü in your spreadsheet.

It works past the Shopify convention. Product URLs are found from the store's own sitemap filing rather than guessed from the path, so flat-URL stores work too — hisar.com.tr/hisar-16-parca-granit-ceyiz-seti has no /products/ segment anywhere and is found regardless.

Three sources, in the right order. JSON-LD first, then microdata, then OpenGraph — and a fallback only ever fills a gap, never overwrites. Each row tells you which sources it needed (source: "jsonld" | "mixed" | …).

Every row grades itself. completeness is the share of the seven fields that matter — name, brand, identifier, price, currency, availability, image — and missingFields names the ones that were absent. Set Minimum completeness to drop thin rows, and you are never charged for them.

A name that is really a SKU gets fixed. Some stores publish "name": "PCDP253G13IY". Where the page offers something better, you get the real title.

Input

FieldWhat it does
startUrlsProduct URLs, or store homepages when discovery is on
discoverProductsFind product pages from robots.txt and the sitemaps it declares
maxProductsHard cap for the run
minCompletenessDrop rows below this percentage. Dropped rows are never charged
includeVariantsKeep the per-variant array, or flatten to one row per product
crawlerIdentityYour own User-Agent. Whoever runs the scrape answers for the traffic

Output

Two kinds of row, so a run is always auditable:

  • Products — ok: true, plus everything above.
  • Unreachable pages — ok: false with url, httpStatus and error. Recorded so you can see them; never charged.

Politeness

Requests to one host are spaced out, bodies are capped, timeouts are hard, and a 429 is honoured with a single backed-off retry. These are not configurable. A scrape that gets your IP banned was not a bargain, and the stores being read did not ask to be.

Limits, stated plainly

  • Public pages only. URLs that point at localhost, private networks or non-http(s) schemes are refused.
  • No JavaScript rendering. Products whose data is drawn client-side and published in no markup at all will come back thin. completeness will say so rather than pretending otherwise.
  • Compressed sitemaps (.xml.gz) are read like plain ones, with the same size cap after decompression.
  • Discovery depends on the store publishing a sitemap. Without one, only the homepage's own product links are found — the run says so explicitly when that happens, because 40 rows against a catalogue of 4,000 is a number you need to know the provenance of.
  • At most 15 sitemap documents are read per store, and no more than 25 are requested. A store whose index lists hundreds of dead children will not spend your run collecting 404s.
  • A run that reaches your maximum total charge stops there and says so in the log and the run's status. It does not keep fetching pages it cannot deliver — raise the budget and run it again for the rest.

Built on the engine behind Scopras, an audit tool that grades a store's product markup against what AI shopping agents need. Same extraction rules: this actor gives you the data, Scopras tells you what is wrong with it.

Build a recurring ecommerce workflow

Use XML Sitemap Scraper to inventory URLs, extract the product records here, then compare recurring datasets with Product Catalog Change Monitor. For public Shopify catalogs and variant snapshots, use Shopify Price Monitor.

You can save inputs as an Apify task and schedule recurring collection. Export the Output dataset as JSON, CSV or Excel, or connect it to your existing workflow through the API and integrations.

For support, open an issue with a run ID and public product URL. Do not post tokens or private customer information.

FAQ

Which stores does this product scraper work on? Any storefront that publishes product markup (JSON-LD, microdata or OpenGraph) in its HTML — Shopify, WooCommerce, Magento, BigCommerce and custom stores. Pages that draw products only with JavaScript come back thin, and the completeness score says so.

Can it find every product in a store? With discovery on, it reads the store's robots.txt and sitemaps to list product URLs, then extracts each one. Cap the run with Max products.

How much does it cost? See the Pricing tab. Unreachable pages and rows below your completeness filter are never charged.

How do I track price changes? Run it on a schedule and compare datasets with Product Catalog Change Monitor.

Is it legal? It reads publicly available pages only, with no login. You are responsible for respecting each site's terms and the privacy rules that apply to your use of the data.

Can I run it through the API or on a schedule? Yes. Save your input as a task, schedule it in Apify Console, or call it from the Apify API. Results export as JSON, CSV or Excel and connect to Google Sheets, Slack, Make, Zapier or a webhook.