ResellerRatings Scraper [$2.10/1K💰] | Merchants | Reviews
Pricing
from $1.05 / 1,000 reviews
ResellerRatings Scraper [$2.10/1K💰] | Merchants | Reviews
Scrape merchant profiles and full review archives from ResellerRatings - store ratings, sub-ratings, verified-buyer flags, review text, votes, sentiment and merchant replies. Discover 35,500+ sellers from the sitemap. No browser needed.
Pricing
from $1.05 / 1,000 reviews
Rating
0.0
(0)
Developer
Ahmed Jasarevic
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Share
ResellerRatings Scraper — Merchant Profiles and the Full Verified-Review Archive
Scrape merchant/store profiles and the complete review archive from resellerratings.com — store rating, review count, review text, star score, date, author, verified-buyer flag, per-aspect sub-ratings, engagement votes, sentiment, geo and merchant replies. Around 35,500 merchants are discoverable through the seller sitemap.
Built for ecommerce competitor research, brand due diligence, review sentiment analysis and merchant benchmarking. No browser, no Cloudflare challenge, no paid anti-bot API.
Main use cases
- Ecommerce competitor research — pull a category's merchants with their full review archives in one run
- Merchant due diligence — review volume, reply rate, verified-buyer share and sub-ratings per store before you list with them
- Review sentiment and topic analysis — text, scores, per-aspect pricing/shipping/service sub-ratings and helpful-vote counts
- Merchant benchmarking — rank sellers on
percentReply,positivePctandlifetimeRating - Merchant outreach lists — merchant websites and categories for every crawled store
- Fake-review detection research — verified-buyer flags, member flags and rating distributions across merchants
Data source: the site's own internal JSON API (content-negotiation bypass)
resellerratings.com is an Apache/PHP application that server-side-renders a React SPA. The only blob in the served HTML is a config stub (<div id="app" data-config='{...}'>), so the store data itself is not in the HTML. Reverse-engineering store.app.js revealed the SPA's data layer: it requests the same public page paths but with
Accept: application/jsonX-Requested-With: XMLHttpRequest
and the backend then answers with the complete serialized SSR state as JSON instead of an HTML shell (Content-Type: application/json). This is the classic Symfony-style content-negotiation endpoint pattern, exposed here without any auth. One curl with two headers returns roughly 50 KB of clean, structured store and review data.
Endpoints used — all public, all unauthenticated
| Purpose | Endpoint |
|---|---|
| Store profile + reviews, page 1 | GET https://www.resellerratings.com/store/{seoName} |
| Store profile + reviews, page N | GET https://www.resellerratings.com/store/{seoName}/page/{n} |
| Same, with sort | GET https://www.resellerratings.com/store/{seoName}/sort/{sort}/page/{n} |
| Single review thread | GET https://www.resellerratings.com/store/{seoName}/review/{commentId} |
| Store discovery / ranking | GET https://www.resellerratings.com/search?category={cat}&sort={sort}&page={n} |
| Category list | GET https://www.resellerratings.com/endpoint/category?minimum_seller_count=0 |
| Store URL discovery (≈35.5k merchants) | GET https://www.resellerratings.com/sitemap/seller_info_sitemap_index.xml → seller_info_sitemap{1,2}.xml.gz |
Verify it yourself:
curl -s 'https://www.resellerratings.com/store/Pro_star' \-H 'Accept: application/json' \-H 'X-Requested-With: XMLHttpRequest' | jq '.store.storeData.rating'
Why this surface was chosen: it is cheaper than static HTML parsing (nothing to select on), far cheaper and far more reliable than Playwright (no browser units, no rendering), and it dodges every bot-mitigation layer — the origin is plain Apache behind CloudFront with rate limiting only, no Cloudflare Bot Management, no DataDome, no Akamai, no Kasada. Because the JSON is the SSR state, the data is also complete: pagination metadata (paginate.totalPages), rating distribution, sub-ratings, tags and merchant replies all arrive in one request.
robots.txt
Only /store/*/review/*, /viewschema/* and /help/* are disallowed. This Actor crawls /store/{seo} and /store/{seo}/page/{n}, which are allowed. /store/{seo}/review/{id} is never requested.
Input
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
startUrls | array | no | ["https://www.resellerratings.com/store/Pro_star"] | Store profile URLs, or category landing pages like https://www.resellerratings.com/category/adult. Bare slugs ("Pro_star", "adult") also work. Ignored if empty. |
storeSlugs | array | no | ["Pro_star","JustAnswer"] | Store SEO names. Used when startUrls is empty. |
categoryUrls | array | no | ["https://www.resellerratings.com/category/adult"] | Category landing pages whose stores should be scraped. Each URL is read as JSON, the merchants it lists are ranked, and the top maxStores are crawled. Bare slugs work too. |
categories | array | no | [] | Category slugs to expand through /search, e.g. ["adult"], ["Computers & Electronics"]. Unlike categoryUrls, this walks every /search page, so it finds more merchants in the same category. |
discoverySort | string | no | reviewCount | Which stores survive maxStores. See "Why discoverySort defaults to reviewCount" below. site keeps the endpoint order. |
minReviewsPerStore | integer | no | 0 | Skip discovered stores advertising fewer than this many reviews. 0 = no filter. Use it with a high maxStores to crawl only merchants worth paginating. |
maxDiscoveryPages | integer | no | 5 | /search result pages read per category before ranking (20 stores per page, max 50). Ignored for categoryUrls, whose landing page is not paginated. |
searchSort | string | no | overallscore desc | Sort passed to /search when discoverySort is site. Try overallscore desc, reviewcount desc, replyrate desc. |
useSitemap | boolean | no | true | When no startUrls / storeSlugs / categories are given, seed store URLs from the seller sitemap index (≈35.5k merchants). Set to false for an empty run. |
sort | string | no | "" (site default = newest first) | Review sort: date, rating, overallscore, relevance, updated. |
mode | string | no | all | all (store profiles + reviews) / stores (merchant profiles only) / reviews (review archive only). |
maxStores | integer | no | 10 | Cap on stores crawled per discovery source (max 2000). Applied after discoverySort ranking. |
maxReviewsPerStore | integer | no | 50 | Stop paginating a store after this many reviews. |
maxRequestsPerCrawl | integer | no | 200 | Hard total HTTP request cap. Each store page holds ~15 reviews, so budget roughly maxRequestsPerCrawl / 4 stores, plus maxDiscoveryPages. |
proxy | object | no | useApifyProxy: false | Standard Apify proxy picker. |
Seeding precedence
startUrls/storeSlugs→ direct store URLscategoryUrlsand/category/URLs insidestartUrls→/category+/searchdiscoverycategories→/searchdiscovery (paginated, honoursmaxStores)useSitemap→seller_infositemap index (≈35.5k merchants)
Why discoverySort defaults to reviewCount
ResellerRatings' own category order is by score, not by review volume. In the adult category its default overallscore desc listing opens with shops rated 10.00 that have one review each:
| Rank | Store | Rating | Reviews |
|---|---|---|---|
| 1 | Spotted_Horse | 10.00 | 4 |
| 2 | Uflash | 10.00 | 1 |
| 3 | JToutlet | 10.00 | 1 |
Taking the first 10 of those returns 17 reviews in total. Ranking the same category by review count instead picks the merchants that actually have archives:
| Rank | Store | Rating | Reviews |
|---|---|---|---|
| 1 | Betweenthesatinsheets_com | 9.18 | 572 |
| 2 | PinkCherry_Sex_Toys_Canada | 8.54 | 467 |
| 3 | EdenFantasys | 9.98 | 444 |
Same maxStores: 10, same maxReviewsPerStore: 50 — 506 items instead of 27. Every discovery response carries reviewCount per merchant, so the Actor reads every /search page it needs, ranks locally, and only then applies maxStores. Set discoverySort to site if you want the original site order back.
Output
Two separate datasets, so each data type gets its own table and schema in the Output tab. Switch between them with the view selector, or export each from the Storage tab.
| Output | Dataset | Rows |
|---|---|---|
| Reviews | default dataset | one row per review |
| Stores | stores dataset | one row per crawled merchant |
Every row also carries an itemType field ("store" or "review") so you can tell them apart if you merge the datasets yourself.
Stores dataset
| Group | Fields |
|---|---|
| Identity | storeId, storeName, seoName, storeUrl, storeThumb |
| Rating | rating, starRating, lifetimeRating, sixMonthRating, yearlyRating |
| Volume | reviewCount, lifetimeTotal, sixMonthTotal, yearlyTotal |
| Distribution | ratingDistribution (1–5 star counts), positivePct, neutralPct, negativePct |
| Response behaviour | percentReply, hasMerchantReplies |
| Sub-ratings | infoRating — pricing / shipping / customer service / return policy / future |
| Plan flags | isPremium, isElite, currentPlan, isCollecting |
| Contact | merchantWebsite, merchantDescription, categories, categoryNames, supportReps, supportRepNames, compareUrl |
Reviews dataset
| Group | Fields |
|---|---|
| Identity | reviewId, surveyId, reviewUrl |
| Store context | storeId, storeName, storeSeoName, storeUrl |
| Author | author, authorUsername, authorId, authorAvatar, isMember |
| Verification | badgeType, isVerifiedBuyer |
| Body | rating, title, text, firstSentence, date, postedDate, wasEdited |
| Sub-ratings | subRatings — pricing / customer service / shipping |
| Tags | tags |
| Engagement | helpfulVotes, notHelpfulVotes, sentiment, isFlagged |
| Geo | city / state / country |
| Merchant replies | merchantReplies[] — {date, author, body, kind, isMerchant, avatar, sellerId} |
| Store-level repeat | storeRating, storeReviewCount |
merchantReplies combines the API's repReply object with any threaded reviewComments, so you can see how a merchant handled a complaint. isVerifiedBuyer is derived from the API's badgeType === "Verified", with isMember as a fallback signal.
Example input
Direct store plus a category to expand:
{"startUrls": ["https://www.resellerratings.com/store/Pro_star"],"categoryUrls": ["https://www.resellerratings.com/category/adult"],"maxStores": 25,"maxReviewsPerStore": 100}
Full category sweep ranked by review volume (the highest-yield mode):
{"categories": ["Computers & Electronics"],"discoverySort": "reviewCount","minReviewsPerStore": 200,"maxStores": 50,"maxDiscoveryPages": 10,"maxReviewsPerStore": 200,"maxRequestsPerCrawl": 2000}
Merchant profiles only — no review pages fetched, so no review events:
{ "mode": "stores", "categories": ["adult"], "maxStores": 100 }
Example output
Store row:
{"itemType": "store","storeId": "123456","storeName": "Pro Star","seoName": "Pro_star","storeUrl": "https://www.resellerratings.com/store/Pro_star","rating": 4.42,"starRating": 4.4,"lifetimeRating": 4.3,"sixMonthRating": 4.5,"reviewCount": 2871,"lifetimeTotal": 2871,"ratingDistribution": { "1": 96, "2": 41, "3": 63, "4": 210, "5": 2461 },"positivePct": 86.4,"neutralPct": 5.1,"negativePct": 8.5,"percentReply": 92,"hasMerchantReplies": true,"isPremium": true,"isElite": false,"currentPlan": "Business","merchantWebsite": "https://prostar.example","categoryNames": ["Computers & Electronics"],"scrapedAt": "2026-09-29T09:00:00.000Z"}
Review row:
{"itemType": "review","reviewId": "882131","storeId": "123456","storeName": "Pro Star","storeSeoName": "Pro_star","author": "verified_buyer_4471","isMember": true,"badgeType": "Verified","isVerifiedBuyer": true,"rating": 5,"title": "Exactly as described","text": "Arrived two days early and in perfect condition. Would order from this seller again.","firstSentence": "Arrived two days early","date": "2026-08-19","postedDate": "2026-08-19","wasEdited": false,"subRatings": { "pricing": 5, "customerService": 5, "shipping": 5 },"helpfulVotes": 12,"notHelpfulVotes": 1,"sentiment": "positive","city": "Austin","state": "TX","merchantReplies": [{"date": "2026-08-20","author": "Pro Star Support","body": "Thanks so much for the kind words — glad it arrived early!","kind": "repReply","isMerchant": true}],"storeRating": 4.42,"storeReviewCount": 2871,"scrapedAt": "2026-09-29T09:00:02.000Z"}
Monitor merchant reputation and review volume on a schedule
Every Apify Actor is callable over HTTP, so the useful pattern is a recurring crawl of the same merchant set:
- Weekly — same
storeSlugs; diffreviewCount,ratingandsixMonthRatingto track reputation drift - Monthly — re-crawl a category with
discoverySort: reviewCountto catch merchants entering or leaving the top of a niche - Alerting — filter on
negativePctorisFlaggedreviews and push runs to a webhook when a merchant crosses your threshold - Warehouse sync — Apify webhooks, Zapier, Make, Google Sheets and 100+ integrations fire on run completion; both datasets export as JSON, CSV, Excel, XML, HTML or RSS
Set mode per saved input so merchant-only monitoring and full review collection stay on separate schedules.
Related Actors
- G2 Reviews & Products Scraper (
automation-lab/g2-scraper) — 5M+ software reviews with NPS, sentiment and switching data - Trustpilot Scraper (
ahmed_jasarevic/trustpilot-reviews-scraper) — reviews and ratings from the largest independent review platform - Reviews.io Scraper (
ahmed_jasarevic/reviews-scraper) — exact review dates and vote counts - ConsumerAffairs Scraper (
ahmed_jasarevic/consumeraffairs-reviews-scraper) — reviews plus complaint records - Better Scraper (
ahmed_jasarevic/better-scraper) — BBB business profiles, ratings and reviews for US company due diligence
FAQ
Why not scrape the HTML pages directly?
The served HTML contains only a React config stub — no store data at all. The data lives behind the SPA's own data layer, which requests the same paths with Accept: application/json. Going straight there removes the browser entirely: no rendering, no CSS selectors to maintain, a fraction of the compute, and complete payloads including pagination metadata, rating distribution, sub-ratings, tags and merchant replies in a single request.
What are the alternatives to this Actor?
- A Playwright-based scraper — roughly 50× the compute cost per run, and it still has to render a React SPA before any data appears.
- Scraping Google or Trustpilot merchant pages — different, smaller datasets, and you would lose ResellerRatings' verified-buyer badges and merchant-reply threads.
- Buying review data from a reseller — you get a snapshot, not a live archive you can schedule against.
Why does discoverySort default to reviewCount instead of the site's own order?
Because the site's order ranks by score, not volume, and a merchant with one 5-star review outranks one with 500 reviews. Crawling the first 10 of the site's default adult listing returns 17 reviews total; ranking the same category by review count returns 506 items at the same settings. The Actor therefore reads every /search page it needs, ranks locally on reviewCount, and only then applies maxStores.
What is the difference between categoryUrls and categories?
categoryUrls reads one category landing page and ranks the merchants listed on it. categories walks every /search result page for that category (honouring maxDiscoveryPages), which finds far more merchants in the same category — at the cost of more list requests. Use categories when you want breadth within a niche.
How do I get more merchants than the default 10?
Raise maxStores (up to 2000) and maxRequestsPerCrawl together, and raise maxDiscoveryPages if you are using categories. Each store costs roughly 4 requests (profile plus review pages), so budget maxRequestsPerCrawl / 4 stores.
What is useSitemap for?
When you supply no store URLs and no categories, it seeds the run from the seller_info sitemap index — around 35,500 merchants. Set it to false for a deliberate empty run instead of an accidental 10-store crawl of arbitrary merchants.
Do I need a proxy?
No. The origin is Apache behind AWS CloudFront with an rsrsession cookie and ordinary rate limiting. No Cloudflare, Akamai, DataDome or Kasada fingerprinting was observed. Enable Apify Proxy in the run input only if you hit throttling at high volume — no code change needed.
How much does it cost?
Store rows are billed at $0.0021–$0.0025 each (roughly $2.10–$2.50 per 1,000 merchants) and review rows at $0.00105–$0.0012 each (roughly $1.05–$1.20 per 1,000 reviews), as two independently priced events. mode: "stores" charges only store events and mode: "reviews" charges only review events, so a merchant-profile-only run costs the store rate alone. Exactly one event fires per delivered row, and charging happens before the row is written, so nothing unpaid ever reaches a dataset. Runs stop cleanly once your charge limit is reached. Free accounts get a capped 20-item preview.
For AI Agents & LLM Apps
Callable via the Apify MCP server and the Apify API. Returns merchant profiles (second dataset, stores) and the review archive (default dataset), with itemType on every row.
Minimal valid input — two known stores, default limits:
{ "storeSlugs": ["Pro_star", "JustAnswer"] }
Highest-yield category sweep — ranked by review volume so maxStores buys real archives instead of one-review shops:
{"categories": ["Computers & Electronics"],"discoverySort": "reviewCount","minReviewsPerStore": 200,"maxStores": 50,"maxDiscoveryPages": 10,"maxReviewsPerStore": 200}
Merchant profiles only — skips every review page and bills only the store event:
{ "mode": "stores", "categories": ["adult"], "maxStores": 100 }
Output fields — stores: storeId, storeName, seoName, storeUrl, storeThumb, rating, starRating, lifetimeRating, sixMonthRating, yearlyRating, reviewCount, lifetimeTotal, sixMonthTotal, yearlyTotal, ratingDistribution, positivePct, neutralPct, negativePct, percentReply, hasMerchantReplies, infoRating, isPremium, isElite, currentPlan, isCollecting, merchantWebsite, merchantDescription, categories, categoryNames, supportReps, supportRepNames, compareUrl, itemType. Reviews: reviewId, surveyId, reviewUrl, storeId, storeName, storeSeoName, storeUrl, author, authorUsername, authorId, authorAvatar, isMember, badgeType, isVerifiedBuyer, rating, title, text, firstSentence, date, postedDate, wasEdited, subRatings, tags, helpfulVotes, notHelpfulVotes, sentiment, isFlagged, merchantReplies, storeRating, storeReviewCount, itemType.
Behaviors an agent should know
- Seeding is strictly ordered:
startUrls/storeSlugs→categoryUrls→categories→useSitemap. Later sources are ignored if an earlier one produced input. Defaults mean all four can fire, so be explicit about what you want. maxStoresis applied after ranking, not before. With the defaultdiscoverySort: reviewCountthat is what you want; withsiteyou get the site's own score-first order, which returns very few reviews per store.maxRequestsPerCrawlis the real budget. Each store costs roughly 4 requests, so 200 default requests buys about 50 stores, not 200.modecontrols which pay-per-event fires —allcharges both,storescharges onlystore,reviewscharges onlyreview. Setmode: "stores"for a cheap profile crawl.itemTypeis on every row in both datasets ("store"or"review"), so you can concatenate the two datasets and still filter correctly.isVerifiedBuyeris derived, not a raw field: it comes frombadgeType === "Verified", withisMemberas the fallback signal. CheckbadgeTypedirectly if you need the exact badge.merchantRepliesmerges two sources — the API'srepReplyobject plus threadedreviewComments— so it is an array that may be empty.- Category slugs are free text and market-specific, e.g.
"adult"or"Computers & Electronics". An unrecognised slug returns no merchants rather than an error. useSitemapdefaults totrue. With no store or category input you will get an arbitrary crawl of discovered merchants; set it tofalsefor a clean empty run.
Billing model — pay per event with two independently priced events: store ($0.0021–$0.0025 per merchant row) and review ($0.00105–$0.0012 per review row), plus a per-run Actor Start event scaled by memory. The run stops cleanly when the caller's charge limit is reached.
Legal & Compliance Disclaimer
This Actor is an independent third-party tool. It is not affiliated with, endorsed by, sponsored by, or connected to ResellerRatings or ShopperStream, Inc.
It reads only publicly accessible JSON responses from www.resellerratings.com public page paths. It does not log in, does not bypass authentication, does not solve CAPTCHAs, does not use proxies by default, and respects the site's robots.txt — only /store/{seo} and /store/{seo}/page/{n} are crawled; the disallowed /store/*/review/*, /viewschema/* and /help/* paths are never requested.
Output includes reviewer usernames, avatars, geo fields and review text, and store rows include merchant website and support-representative names. That is personal data. ResellerRatings publishes it publicly, but you are responsible for your own lawful basis for processing it, and for complying with the site's Terms of Service and any applicable data-protection law including GDPR, UK GDPR and CCPA. Do not use reviewer data for unsolicited commercial outreach, which can violate applicable law including CAN-SPAM and TCPA.
Please note that several merchants and consumer advocates have publicly disputed ResellerRatings' moderation practices and the authenticity of some listed reviews. If review authenticity matters to your use case, treat isVerifiedBuyer and isFlagged as signals to filter on, not as proof.
This Actor is a data-collection tool; it does not provide legal advice and makes no claim that any particular use is permitted.
SEO Keywords
resellerratings scraper, reseller ratings data, merchant review data, verified buyer reviews, ecommerce review scraper, merchant profile scraper, product review api, review sentiment analysis, store rating data, customer review archive, review scraping api, competitor review analysis, brand due diligence ecommerce, merchant benchmarking, ecommerce competitor research, review sub ratings, merchant reply data, review data for ai training, trustpilot alternative data, review api alternative, ecommerce reputation monitoring, helpful votes review data, seller review dataset