1. Scraping product listings
Houzz Shop has millions of home improvement products across categories like bathroom vanities, lighting, furniture, and outdoor living. Scrape product cards with prices and seller info:
#E8A0BF">import requests
#E8A0BF">import json
API_KEY = #A8D4A0">"sr_live_YOUR_KEY"
#E8A0BF">def scrape_houzz_products(category, page=1):
#A8D4A0">""#A8D4A0">"Scrape Houzz Shop product listings"#A8D4A0">""
url = f#A8D4A0">"https://www.houzz.com/products/{category}?pg={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'] .product-title",
#A8D4A0">"prices": #A8D4A0">"[data-testid=#A8D4A0">'product-card'] .product-price",
#A8D4A0">"original_prices": #A8D4A0">"[data-testid=#A8D4A0">'product-card'] .original-price",
#A8D4A0">"sellers": #A8D4A0">"[data-testid=#A8D4A0">'product-card'] .seller-name",
#A8D4A0">"ratings": #A8D4A0">"[data-testid=#A8D4A0">'product-card'] .rating-value",
#A8D4A0">"review_counts": #A8D4A0">"[data-testid=#A8D4A0">'product-card'] .review-count",
#A8D4A0">"links": #A8D4A0">"[data-testid=#A8D4A0">'product-card'] a::attr(href)",
#A8D4A0">"images": #A8D4A0">"[data-testid=#A8D4A0">'product-card'] img::attr(src)"
},
#A8D4A0">"use_flaresolverr": true
}
)
#E8A0BF">return resp.json()[#A8D4A0">"data"]
# Scrape bathroom vanities across 3 pages
all_products = []
#E8A0BF">for page #E8A0BF">in range(1, 4):
data = scrape_houzz_products(#A8D4A0">"bathroom-vanities", page)
names = data.get(#A8D4A0">"names", [])
#E8A0BF">for i #E8A0BF">in range(len(names)):
all_products.append({
#A8D4A0">"name": names[i],
#A8D4A0">"price": data[#A8D4A0">"prices"][i] #E8A0BF">if i < len(data.get(#A8D4A0">"prices", [])) #E8A0BF">else #A8D4A0">"",
#A8D4A0">"original_price": data[#A8D4A0">"original_prices"][i] #E8A0BF">if i < len(data.get(#A8D4A0">"original_prices", [])) #E8A0BF">else #A8D4A0">"",
#A8D4A0">"seller": data[#A8D4A0">"sellers"][i] #E8A0BF">if i < len(data.get(#A8D4A0">"sellers", [])) #E8A0BF">else #A8D4A0">"",
#A8D4A0">"rating": data[#A8D4A0">"ratings"][i] #E8A0BF">if i < len(data.get(#A8D4A0">"ratings", [])) #E8A0BF">else #A8D4A0">"",
})
#E8A0BF">print(f#A8D4A0">"Page {page}: {len(names)} products")
#E8A0BF">print(f#A8D4A0">"Total: {len(all_products)} products scraped")2. Professional directory scraping
Houzz has one of the largest directories of home improvement professionals. Extract contractor listings with ratings and specialties:
#E8A0BF">def scrape_houzz_professionals(location, specialty, page=1):
#A8D4A0">""#A8D4A0">"Scrape Houzz professional directory"#A8D4A0">""
url = (
f#A8D4A0">"https://www.houzz.com/professionals/"
f#A8D4A0">"{specialty}/{location}?pg={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">".professional-card .pro-title a",
#A8D4A0">"ratings": #A8D4A0">".professional-card .rating-value",
#A8D4A0">"review_counts": #A8D4A0">".professional-card .review-count",
#A8D4A0">"locations": #A8D4A0">".professional-card .pro-location",
#A8D4A0">"descriptions": #A8D4A0">".professional-card .pro-description",
#A8D4A0">"badges": #A8D4A0">".professional-card .badge-text",
#A8D4A0">"links": #A8D4A0">".professional-card .pro-title a::attr(href)",
#A8D4A0">"photos": #A8D4A0">".professional-card .cover-photo img::attr(src)"
},
#A8D4A0">"use_flaresolverr": true
}
)
#E8A0BF">return resp.json()[#A8D4A0">"data"]
# Find kitchen remodelers #E8A0BF">in San Francisco
pros = []
#E8A0BF">for page #E8A0BF">in range(1, 6):
data = scrape_houzz_professionals(
#A8D4A0">"San-Francisco-CA",
#A8D4A0">"kitchen-#E8A0BF">and-bath-remodelers",
page
)
names = data.get(#A8D4A0">"names", [])
#E8A0BF">for i #E8A0BF">in range(len(names)):
pros.append({
#A8D4A0">"name": names[i],
#A8D4A0">"rating": data[#A8D4A0">"ratings"][i] #E8A0BF">if i < len(data.get(#A8D4A0">"ratings", [])) #E8A0BF">else #A8D4A0">"",
#A8D4A0">"reviews": data[#A8D4A0">"review_counts"][i] #E8A0BF">if i < len(data.get(#A8D4A0">"review_counts", [])) #E8A0BF">else #A8D4A0">"",
#A8D4A0">"location": data[#A8D4A0">"locations"][i] #E8A0BF">if i < len(data.get(#A8D4A0">"locations", [])) #E8A0BF">else #A8D4A0">"",
})
#E8A0BF">print(f#A8D4A0">"Page {page}: {len(names)} professionals")
#E8A0BF">print(f#A8D4A0">"Total: {len(pros)} professionals found")3. Professional profile details
Individual professional profiles include reviews, specialties, project photos, and business details:
#E8A0BF">def scrape_pro_profile(profile_url):
#A8D4A0">""#A8D4A0">"Scrape detailed professional profile"#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": profile_url,
#A8D4A0">"selectors": {
#A8D4A0">"name": #A8D4A0">".pro-info-section h1",
#A8D4A0">"rating": #A8D4A0">".rating-summary .rating-value",
#A8D4A0">"review_count": #A8D4A0">".rating-summary .review-count",
#A8D4A0">"location": #A8D4A0">".pro-info-section .location",
#A8D4A0">"phone": #A8D4A0">".pro-info-section .phone-number",
#A8D4A0">"website": #A8D4A0">".pro-info-section .website-link::attr(href)",
#A8D4A0">"specialties": #A8D4A0">".specialties-list li",
#A8D4A0">"description": #A8D4A0">".about-section p",
#A8D4A0">"project_count": #A8D4A0">".projects-count",
#A8D4A0">"years_in_business": #A8D4A0">".business-details .years",
#A8D4A0">"reviews": #A8D4A0">".review-card .review-text",
#A8D4A0">"review_ratings": #A8D4A0">".review-card .rating-value"
},
#A8D4A0">"use_flaresolverr": true
}
)
#E8A0BF">return resp.json()[#A8D4A0">"data"]
profile = scrape_pro_profile(
#A8D4A0">"https://www.houzz.com/professionals/kitchen-remodelers/example-pro"
)
#E8A0BF">print(json.dumps(profile, indent=2))Pro tip
Use professional profile data to build a contractor comparison tool. Cross-reference ratings, review counts, and specialties to help homeowners make informed hiring decisions.
4. Market analysis
Analyze scraped professional data to understand the contractor landscape in any market:
#E8A0BF">import pandas #E8A0BF">as pd
# Analyze Houzz professional data
df = pd.DataFrame(pros)
# Clean data
df[#A8D4A0">"rating_num"] = pd.to_numeric(df[#A8D4A0">"rating"], errors=#A8D4A0">"coerce")
df[#A8D4A0">"review_num"] = (
df[#A8D4A0">"reviews"]
.str.extract(r#A8D4A0">"([\d,]+)")
.replace(#A8D4A0">",", #A8D4A0">"", regex=#E8A0BF">True)
.astype(float)
)
#E8A0BF">print(#A8D4A0">"=== SF Kitchen Remodelers ===")
#E8A0BF">print(f#A8D4A0">"Professionals: {len(df)}")
#E8A0BF">print(f#A8D4A0">"Avg rating: {df[#A8D4A0">'rating_num'].mean():.2f}")
#E8A0BF">print(f#A8D4A0">"Median reviews: {df[#A8D4A0">'review_num'].median():.0f}")
# Top rated #E8A0BF">with significant reviews
top_pros = df[df[#A8D4A0">"review_num"] >= 10].nlargest(10, #A8D4A0">"rating_num")
#E8A0BF">print(#A8D4A0">"\n=== Top Rated (10+ reviews) ===")
#E8A0BF">print(top_pros[[#A8D4A0">"name", #A8D4A0">"rating", #A8D4A0">"reviews"]].to_string(index=#E8A0BF">False))
# Review distribution
tiers = pd.cut(
df[#A8D4A0">"review_num"],
bins=[0, 5, 20, 50, 100, float(#A8D4A0">"inf")],
labels=[#A8D4A0">"1-5", #A8D4A0">"6-20", #A8D4A0">"21-50", #A8D4A0">"51-100", #A8D4A0">"100+"]
)
#E8A0BF">print(#A8D4A0">"\n=== Review Count Distribution ===")
#E8A0BF">print(tiers.value_counts().sort_index())
df.to_csv(#A8D4A0">"houzz_sf_remodelers.csv", index=#E8A0BF">False)Scrape Houzz without getting blocked
SnapRender handles JavaScript rendering, bot detection bypass, and structured data extraction. Get home improvement data from Houzz with a single API call.
Get Your API Key — FreeFrequently asked questions
Houzz's Terms of Service prohibit automated scraping. Publicly available product listings and professional profiles can be accessed for personal research and market analysis. Do not republish photos, reviews, or build a competing home improvement directory.
Houzz uses a React-based SPA with lazy-loaded content, infinite scroll pagination, and bot detection. Product images and professional profiles load dynamically as users scroll. Standard HTTP requests return minimal HTML without product data.
Product names, prices, descriptions, photos, seller info, and reviews from the Houzz Shop. Professional directory data includes contractor names, ratings, review counts, location, specialties, and project photos. Ideabook content includes room styles and design trends.
Yes. Houzz shows review text, ratings, dates, and project types for listed professionals. This data is useful for market research on contractor pricing, popular specialties, and service quality in specific regions.
Houzz loads more results as you scroll down. With SnapRender, you can use pagination parameters in the URL or set scroll behavior options to trigger content loading. Alternatively, scrape individual category pages which have standard pagination.