How to Scrape Wayfair Listings for an Assortment Comparison
A sofa card can advertise a large discount and several color options without showing which configuration the price represents. For an assortment comparison, those qualifications matter as much as the number.
The Wayfair Listings Scraper collects cards from Wayfair category, subcategory, and keyword-search URLs. I maintain this Actor on Apify. It returns SKU, name, current and reference prices, ratings, image, variant-count text, badges, and delivery text. It does not document full product-detail or per-variant extraction.

Choose a category with comparable products
For a sofa study, start with the sofa category rather than all furniture. If you need a particular material or size, use Wayfair's available filters and confirm the copied URL retains them. The scraper accepts listing URLs in startUrls; it does not take a bare keyword field.
A supported keyword URL has the form https://www.wayfair.com/keyword.php?keyword=standing+desk. The documented examples use wayfair.com. Do not assume another regional domain has the same support or output currency without checking it separately.
On Apify, open Input, select JSON, and enter:
{
"startUrls": [
{"url": "https://www.wayfair.com/furniture/sb0/sofas-c413892.html"}
],
"maxResults": 20
}
Click Start, then inspect the dataset and log after completion. The current schema defaults maxResults to fifty, although an older README table says 500. The example sets twenty explicitly.
The limit applies per start URL. Adding three URLs allows up to sixty results at this setting, not twenty for the entire run. Zero removes the limit. Pagination follows listing pages until the cap or available results stop collection; it does not make the sample a census of all Wayfair products.
No cookie or proxy configuration is exposed in this Actor's input. If a run fails, inspect the log and source URL rather than adding unsupported proxy keys to the JSON.
Read the card as an advertised offer
An abbreviated historical sample from the documentation shows:
{
"sku": "W011378024",
"name": "Shavera Velvet Upholstered Modular Sectional Sofa",
"price": 1080,
"previousPrice": 2014.72,
"currency": "USD",
"discountPercent": 46,
"rating": 4.6,
"reviewCount": 118,
"variantCountText": "4 Colors",
"flag": "Bundle & Save"
}
These values illustrate the fields, not today's availability or price. previousPrice is the reference price displayed on the card. It does not independently establish a historical selling price or a realized saving.
variantCountText tells you that alternatives are advertised. It does not list the price of every color or configuration. A modular sectional can also differ from a standard sofa in components and seating capacity, so a shared category does not make them comparable.
Other fields include url, leadImage, speedBadge, estimatedArrival, isBestValue, categoryBreadcrumbs, sourceUrl, and scrapedAt. Treat badges as retailer labels. A null delivery estimate means that field was not available in the record, not that the product cannot be delivered.

Make an assortment worksheet
Export CSV with SKU, URL, name, price, currency, reference price, discount percentage, rating, review count, variant text, flags, delivery text, and collection time. Use JSON if you want to retain category breadcrumbs as an array.
Deduplicate matching SKUs when search URLs overlap, but keep their source URLs if category placement matters. Add reviewed columns for sofa type, seating configuration, material, dimensions, and selected variant. These facts need product-page inspection because the listing output does not document detailed dimensions or a full variant matrix.
Group the reviewed rows into comparable products before summarizing price. Keep loveseats, standard sofas, sectionals, and modular bundles separate. For a particular buying brief, mark which dimensions and configuration actually fit; leave uncertain rows for review.
If you compare advertised discounts, calculate the percentage only when a positive reference price exists and retain the source's discountPercent beside your calculation. Rounding can explain small differences. Do not present that discount as a measured price drop unless you have your own earlier observation of the same SKU and variant.
For delivery-sensitive choices, open the source with the intended destination and confirm the current estimate. The scraped estimatedArrival is a text observation, not a delivery promise to every address. Keep it out of a purchasing commitment until checked.
Build a defensible price history
Save the successful input as an Apify task and keep dated exports. Match records by SKU on later runs, then review large changes against the product page. A default variant, bundle, or promotion can change the headline price without representing a like-for-like reduction.
Store current price and collection time for each observation instead of overwriting the previous record. That gives you an actual observed history. A product missing from the next twenty-row category sample is simply not observed within that scope; it is not necessarily discontinued.
If the run returns fewer rows than expected, check the cap per URL, source filters, and log. A narrower category can legitimately have fewer results, while access or parsing failures need a different response. Adding more categories can conceal that distinction.
Cost and the next export
Pricing as of September 6, 2026 is $0.0015 per product result. Twenty results cost $0.03 in product events; three sources producing twenty each correspond to $0.09 before the start event. The start event is $0.00005 per GB of allocated memory, minimum one event. Check live pricing and separately billed account usage before scaling.
The Wayfair Node.js example can help automate the export once the review columns are settled. If you broaden the assortment study to Amazon, Walmart, or AliExpress, match the actual product and configuration before comparing prices across stores.
Frequently asked questions
Is maxResults a global limit?
No. maxResults applies to each start URL. Three URLs with a cap of twenty allow up to sixty product results before considering overlap or unavailable results.
Does variantCountText contain every variant’s price?
No. It is listing-card text such as “4 Colors.” The documented output does not enumerate full variant configurations or their individual prices.
Is previousPrice a historical price observation?
It is the reference price shown in the collected listing. It does not independently prove what the product sold for on a previous date.
