Quick answer
Rebag's shopper-facing catalogue at www.rebag.com/shop is client-rendered and disallowed in robots.txt, which is why most attempts at it end in an empty page or a compliance problem. The Rebag Luxury Resale Scraper reads the public Shopify storefront JSON on shop.rebag.com instead — designer, model, condition, price and availability, one row per variant — at $1.25 per 1,000 rows.
Why the obvious URL is the wrong one 👜
Type "rebag scraper" into a search box and the first instinct is to point a crawler at the shop page you see in a browser. Two things go wrong.
The page is client-rendered. The HTML that arrives contains a shell and a bundle reference; the products appear only after JavaScript runs. A plain HTTP fetch returns a document with no listings in it, which reads like "no results" rather than "wrong surface" — the most expensive kind of failure, because it looks like data.
The bigger problem is that www.rebag.com/shop is disallowed in robots.txt. Whatever your view on the enforceability of that file, building a paid product on a path the site explicitly asks crawlers to avoid is a poor foundation.
Rebag runs on Shopify, and Shopify storefronts expose a public products JSON feed. shop.rebag.com serves it, it is not disallowed, and it returns the same catalogue as structured data — no rendering, no reverse-engineered selectors.
One row per variant, not per product 💰
This is the modelling decision that matters most, and it is easy to get wrong.
A Shopify product is a container. The thing with a price, a size, a condition grade and a stock status is the variant. A single Rebag listing for a handbag can carry several variants that differ in exactly the fields a resale analyst cares about.
Flatten to one row per product and you have to pick a variant to represent it — usually the first — and you silently discard the rest. Your price series then tracks whichever variant happened to be listed first, and your availability column is wrong whenever that variant sells out before the others.
This Actor emits one row per variant, so price and availability are never averaged or dropped. If you want product-level rows, grouping upward is a one-line operation; recovering variants you never collected is not.
What we handle so you don't 🛡️
Rebag is not a heavily defended target, and we are not going to pretend otherwise. The work here is in the transport and the shape of the output.
Browser-grade fingerprinting. curl-cffi impersonates real Chrome, Firefox and Safari TLS handshakes, rotated across requests. Header-only spoofing is what most scrapers do and it is what gets caught first, because the handshake gives you away before a header is read.
Session and exit-IP rotation through Apify Proxy, with a fresh session on every block.
Retries with exponential backoff on 408 / 429 / 5xx, up to five attempts per page, honouring Retry-After.
Product- and variant-level fault isolation. One malformed product does not end the run. It is skipped, logged, and the crawl continues — the single most common reason a scraper returns partial data and reports success.
Typed rows. Pydantic-validated, ISO-8601 timestamps, stable field names.
What it costs
Pay-per-event: a start fee plus $0.0012 per row written to your dataset. A thousand variants is about $1.25. Runs that return nothing cost you nothing beyond the start fee — you are not billed for blocked pages or retries.
Where it fits
Resale pricing intelligence is a real analytical problem: comparable-model price tracking, condition-grade spreads, and how fast inventory turns over at a given price point. Those questions need variant-level rows with honest availability, collected from a surface that is meant to be read by machines.
Top comments (0)