ResellerRatings Scraper [$2.10/1K💰] | Merchants | Reviews avatar

ResellerRatings Scraper [$2.10/1K💰] | Merchants | Reviews

Pricing

from $1.05 / 1,000 reviews

Go to Apify Store
ResellerRatings Scraper [$2.10/1K💰] | Merchants | 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

Ahmed Jasarevic

Maintained by Community

Actor 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, positivePct and lifetimeRating
  • 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/json
X-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

PurposeEndpoint
Store profile + reviews, page 1GET https://www.resellerratings.com/store/{seoName}
Store profile + reviews, page NGET https://www.resellerratings.com/store/{seoName}/page/{n}
Same, with sortGET https://www.resellerratings.com/store/{seoName}/sort/{sort}/page/{n}
Single review threadGET https://www.resellerratings.com/store/{seoName}/review/{commentId}
Store discovery / rankingGET https://www.resellerratings.com/search?category={cat}&sort={sort}&page={n}
Category listGET 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

FieldTypeRequiredDefaultNotes
startUrlsarrayno["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.
storeSlugsarrayno["Pro_star","JustAnswer"]Store SEO names. Used when startUrls is empty.
categoryUrlsarrayno["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.
categoriesarrayno[]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.
discoverySortstringnoreviewCountWhich stores survive maxStores. See "Why discoverySort defaults to reviewCount" below. site keeps the endpoint order.
minReviewsPerStoreintegerno0Skip discovered stores advertising fewer than this many reviews. 0 = no filter. Use it with a high maxStores to crawl only merchants worth paginating.
maxDiscoveryPagesintegerno5/search result pages read per category before ranking (20 stores per page, max 50). Ignored for categoryUrls, whose landing page is not paginated.
searchSortstringnooverallscore descSort passed to /search when discoverySort is site. Try overallscore desc, reviewcount desc, replyrate desc.
useSitemapbooleannotrueWhen no startUrls / storeSlugs / categories are given, seed store URLs from the seller sitemap index (≈35.5k merchants). Set to false for an empty run.
sortstringno"" (site default = newest first)Review sort: date, rating, overallscore, relevance, updated.
modestringnoallall (store profiles + reviews) / stores (merchant profiles only) / reviews (review archive only).
maxStoresintegerno10Cap on stores crawled per discovery source (max 2000). Applied after discoverySort ranking.
maxReviewsPerStoreintegerno50Stop paginating a store after this many reviews.
maxRequestsPerCrawlintegerno200Hard total HTTP request cap. Each store page holds ~15 reviews, so budget roughly maxRequestsPerCrawl / 4 stores, plus maxDiscoveryPages.
proxyobjectnouseApifyProxy: falseStandard Apify proxy picker.

Seeding precedence

  1. startUrls / storeSlugs → direct store URLs
  2. categoryUrls and /category/ URLs inside startUrls → /category + /search discovery
  3. categories → /search discovery (paginated, honours maxStores)
  4. useSitemap → seller_info sitemap 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:

RankStoreRatingReviews
1Spotted_Horse10.004
2Uflash10.001
3JToutlet10.001

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:

RankStoreRatingReviews
1Betweenthesatinsheets_com9.18572
2PinkCherry_Sex_Toys_Canada8.54467
3EdenFantasys9.98444

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.

OutputDatasetRows
Reviewsdefault datasetone row per review
Storesstores datasetone 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

GroupFields
IdentitystoreId, storeName, seoName, storeUrl, storeThumb
Ratingrating, starRating, lifetimeRating, sixMonthRating, yearlyRating
VolumereviewCount, lifetimeTotal, sixMonthTotal, yearlyTotal
DistributionratingDistribution (1–5 star counts), positivePct, neutralPct, negativePct
Response behaviourpercentReply, hasMerchantReplies
Sub-ratingsinfoRating — pricing / shipping / customer service / return policy / future
Plan flagsisPremium, isElite, currentPlan, isCollecting
ContactmerchantWebsite, merchantDescription, categories, categoryNames, supportReps, supportRepNames, compareUrl

Reviews dataset

GroupFields
IdentityreviewId, surveyId, reviewUrl
Store contextstoreId, storeName, storeSeoName, storeUrl
Authorauthor, authorUsername, authorId, authorAvatar, isMember
VerificationbadgeType, isVerifiedBuyer
Bodyrating, title, text, firstSentence, date, postedDate, wasEdited
Sub-ratingssubRatings — pricing / customer service / shipping
Tagstags
EngagementhelpfulVotes, notHelpfulVotes, sentiment, isFlagged
Geocity / state / country
Merchant repliesmerchantReplies[] — {date, author, body, kind, isMerchant, avatar, sellerId}
Store-level repeatstoreRating, 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; diff reviewCount, rating and sixMonthRating to track reputation drift
  • Monthly — re-crawl a category with discoverySort: reviewCount to catch merchants entering or leaving the top of a niche
  • Alerting — filter on negativePct or isFlagged reviews 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.


  • 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.
  • maxStores is applied after ranking, not before. With the default discoverySort: reviewCount that is what you want; with site you get the site's own score-first order, which returns very few reviews per store.
  • maxRequestsPerCrawl is the real budget. Each store costs roughly 4 requests, so 200 default requests buys about 50 stores, not 200.
  • mode controls which pay-per-event fires — all charges both, stores charges only store, reviews charges only review. Set mode: "stores" for a cheap profile crawl.
  • itemType is on every row in both datasets ("store" or "review"), so you can concatenate the two datasets and still filter correctly.
  • isVerifiedBuyer is derived, not a raw field: it comes from badgeType === "Verified", with isMember as the fallback signal. Check badgeType directly if you need the exact badge.
  • merchantReplies merges two sources — the API's repReply object plus threaded reviewComments — 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.
  • useSitemap defaults to true. With no store or category input you will get an arbitrary crawl of discovered merchants; set it to false for 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.


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