1. Scraping category pages
Wayfair category pages list products with prices, ratings, and brand info. Use SnapRender with Cloudflare bypass to extract the data:
#E8A0BF">import requests
#E8A0BF">import json
API_KEY = #A8D4A0">"sr_live_YOUR_KEY"
#E8A0BF">def scrape_wayfair_category(category_slug, page=1):
#A8D4A0">""#A8D4A0">"Scrape Wayfair category page #E8A0BF">for product listings"#A8D4A0">""
url = f#A8D4A0">"https://www.wayfair.com/keyword.html?keyword={category_slug}&curpage={page}"
resp = requests.post(
#A8D4A0">"https://api.snaprender.dev/v1/extract",
headers={
#A8D4A0">"x-api-key": API_KEY,
#A8D4A0">"Content-Type": #A8D4A0">"application/json"
},
json={
#A8D4A0">"url": url,
#A8D4A0">"selectors": {
#A8D4A0">"names": #A8D4A0">"[data-testid=#A8D4A0">'product-card'] a[data-testid=#A8D4A0">'product-name']",
#A8D4A0">"prices": #A8D4A0">"[data-testid=#A8D4A0">'product-card'] [data-testid=#A8D4A0">'primary-price']",
#A8D4A0">"sale_prices": #A8D4A0">"[data-testid=#A8D4A0">'product-card'] [data-testid=#A8D4A0">'sale-price']",
#A8D4A0">"ratings": #A8D4A0">"[data-testid=#A8D4A0">'product-card'] [data-testid=#A8D4A0">'rating-value']",
#A8D4A0">"review_counts": #A8D4A0">"[data-testid=#A8D4A0">'product-card'] [data-testid=#A8D4A0">'review-count']",
#A8D4A0">"brands": #A8D4A0">"[data-testid=#A8D4A0">'product-card'] [data-testid=#A8D4A0">'brand-name']",
#A8D4A0">"links": #A8D4A0">"[data-testid=#A8D4A0">'product-card'] a[data-testid=#A8D4A0">'product-name']::attr(href)"
},
#A8D4A0">"use_flaresolverr": true
}
)
#E8A0BF">return resp.json()[#A8D4A0">"data"]
# Scrape standing desks
data = scrape_wayfair_category(#A8D4A0">"standing+desk")
#E8A0BF">print(f#A8D4A0">"Found {len(data.get(#A8D4A0">'names', []))} products")
#E8A0BF">for i #E8A0BF">in range(min(5, len(data.get(#A8D4A0">"names", [])))):
#E8A0BF">print(f#A8D4A0">"{data[#A8D4A0">'names'][i]}: {data[#A8D4A0">'prices'][i]}")2. Product detail extraction
Individual product pages contain detailed specs, descriptions, and availability:
#E8A0BF">def scrape_wayfair_product(product_url):
#A8D4A0">""#A8D4A0">"Scrape detailed data #E8A0BF">from a Wayfair product page"#A8D4A0">""
resp = requests.post(
#A8D4A0">"https://api.snaprender.dev/v1/extract",
headers={
#A8D4A0">"x-api-key": API_KEY,
#A8D4A0">"Content-Type": #A8D4A0">"application/json"
},
json={
#A8D4A0">"url": product_url,
#A8D4A0">"selectors": {
#A8D4A0">"name": #A8D4A0">"h1[data-testid=#A8D4A0">'product-title']",
#A8D4A0">"brand": #A8D4A0">"[data-testid=#A8D4A0">'brand-link']",
#A8D4A0">"price": #A8D4A0">"[data-testid=#A8D4A0">'primary-price']",
#A8D4A0">"original_price": #A8D4A0">"[data-testid=#A8D4A0">'comparison-price']",
#A8D4A0">"rating": #A8D4A0">"[data-testid=#A8D4A0">'rating-value']",
#A8D4A0">"review_count": #A8D4A0">"[data-testid=#A8D4A0">'review-count']",
#A8D4A0">"description": #A8D4A0">"[data-testid=#A8D4A0">'product-description']",
#A8D4A0">"dimensions": #A8D4A0">"[data-testid=#A8D4A0">'product-dimensions']",
#A8D4A0">"material": #A8D4A0">"[data-testid=#A8D4A0">'material']",
#A8D4A0">"color": #A8D4A0">"[data-testid=#A8D4A0">'selected-color']",
#A8D4A0">"shipping": #A8D4A0">"[data-testid=#A8D4A0">'shipping-info']",
#A8D4A0">"in_stock": #A8D4A0">"[data-testid=#A8D4A0">'availability']"
},
#A8D4A0">"use_flaresolverr": true
}
)
#E8A0BF">return resp.json()[#A8D4A0">"data"]
product = scrape_wayfair_product(
#A8D4A0">"https://www.wayfair.com/furniture/pdp/example-product-123.html"
)
#E8A0BF">print(json.dumps(product, indent=2))3. Price tracking
Monitor price changes over time by running a tracker on a daily schedule:
#E8A0BF">import pandas #E8A0BF">as pd
#E8A0BF">import time
#E8A0BF">from datetime #E8A0BF">import datetime
#E8A0BF">def track_prices(product_urls, output_file=#A8D4A0">"wayfair_prices.csv"):
#A8D4A0">""#A8D4A0">"Track prices #E8A0BF">for a list of products"#A8D4A0">""
results = []
timestamp = datetime.now().isoformat()
#E8A0BF">for url #E8A0BF">in product_urls:
#E8A0BF">try:
data = scrape_wayfair_product(url)
results.append({
#A8D4A0">"timestamp": timestamp,
#A8D4A0">"url": url,
#A8D4A0">"name": data.get(#A8D4A0">"name", #A8D4A0">""),
#A8D4A0">"price": data.get(#A8D4A0">"price", #A8D4A0">""),
#A8D4A0">"original_price": data.get(#A8D4A0">"original_price", #A8D4A0">""),
#A8D4A0">"in_stock": data.get(#A8D4A0">"in_stock", #A8D4A0">""),
})
#E8A0BF">print(f#A8D4A0">"Tracked: {data.get(#A8D4A0">'name', #A8D4A0">'Unknown')}")
time.sleep(2)
#E8A0BF">except Exception #E8A0BF">as e:
#E8A0BF">print(f#A8D4A0">"Error on {url}: {e}")
# Append to CSV (creates #E8A0BF">if #E8A0BF">not exists)
df = pd.DataFrame(results)
df.to_csv(
output_file,
mode=#A8D4A0">"a",
header=#E8A0BF">not pd.io.common.file_exists(output_file),
index=#E8A0BF">False
)
#E8A0BF">print(f#A8D4A0">"Tracked {len(results)} products at {timestamp}")
#E8A0BF">return df
# Run daily via cron: python track_wayfair.py
products_to_track = [
#A8D4A0">"https://www.wayfair.com/furniture/pdp/desk-1.html",
#A8D4A0">"https://www.wayfair.com/furniture/pdp/desk-2.html",
#A8D4A0">"https://www.wayfair.com/furniture/pdp/desk-3.html",
]
track_prices(products_to_track)4. Competitive analysis
Analyze the competitive landscape within a product category:
#E8A0BF">import pandas #E8A0BF">as pd
# Load scraped data
df = pd.DataFrame(all_products)
# Clean prices
df[#A8D4A0">"price_num"] = (
df[#A8D4A0">"price"]
.str.replace(#A8D4A0">"$", #A8D4A0">"", regex=#E8A0BF">False)
.str.replace(#A8D4A0">",", #A8D4A0">"", regex=#E8A0BF">False)
.astype(float)
)
# Category analysis
#E8A0BF">print(#A8D4A0">"=== Standing Desk Market on Wayfair ===")
#E8A0BF">print(f#A8D4A0">"Total products: {len(df)}")
#E8A0BF">print(f#A8D4A0">"Price range: $" + f#A8D4A0">"{df[#A8D4A0">'price_num'].min():.0f} - $" + f#A8D4A0">"{df[#A8D4A0">'price_num'].max():.0f}")
#E8A0BF">print(f#A8D4A0">"Median price: $" + f#A8D4A0">"{df[#A8D4A0">'price_num'].median():.0f}")
#E8A0BF">print(f#A8D4A0">"Mean rating: {df[#A8D4A0">'rating_num'].mean():.1f}")
# Brand breakdown
brand_stats = df.groupby(#A8D4A0">"brand").agg(
products=(#A8D4A0">"name", #A8D4A0">"count"),
avg_price=(#A8D4A0">"price_num", #A8D4A0">"mean"),
avg_rating=(#A8D4A0">"rating_num", #A8D4A0">"mean")
).sort_values(#A8D4A0">"products", ascending=#E8A0BF">False)
#E8A0BF">print(#A8D4A0">"\n=== Top Brands ===")
#E8A0BF">print(brand_stats.head(10))
# Price sweet spot (most products)
price_bins = pd.cut(
df[#A8D4A0">"price_num"],
bins=[0, 100, 200, 300, 500, 1000, float(#A8D4A0">"inf")],
labels=[#A8D4A0">"<$100", #A8D4A0">"$100-200", #A8D4A0">"$200-300", #A8D4A0">"$300-500", #A8D4A0">"$500-1K", #A8D4A0">"$1K+"]
)
#E8A0BF">print(#A8D4A0">"\n=== Price Distribution ===")
#E8A0BF">print(price_bins.value_counts().sort_index())Scrape Wayfair without getting blocked
SnapRender handles Cloudflare bypass, JavaScript rendering, and structured data extraction. Get product data from Wayfair with a single API call.
Get Your API Key — FreeFrequently asked questions
Wayfair's Terms of Service prohibit automated scraping. Publicly displayed pricing data is generally accessible, but use scraped data for personal research, competitive analysis, or market intelligence only. Do not republish or resell the data. Consult a lawyer for commercial use cases.
Wayfair uses Cloudflare, fingerprinting, and bot detection. Standard HTTP requests with Python's requests library are blocked immediately. You need either a headless browser with stealth plugins or an API like SnapRender that handles anti-bot bypass automatically.
Product name, price, sale price, rating, review count, brand, material, dimensions, color options, shipping info, images, and product description. Category pages also show filters like price range, style, and material which are useful for market analysis.
Wayfair is known for dynamic pricing. Prices can change multiple times per day, especially during sales events. For pricing intelligence, daily scraping is recommended. Set up alerts when prices drop below a threshold for products you are monitoring.
Yes. Review data (rating, text, date, verified purchase status) is available on product pages. Reviews load dynamically via JavaScript, so you need JS rendering. SnapRender can extract review content along with product data in a single API call.