# Wayfair Scraper | Product Specs, Prices & Stock (`datascraperes/wayfair-scraper`) Actor

Scrape Wayfair products by keyword, category URL or SKU across the US, Canada and UK. Collect prices, discounts, ratings, stock and images, with optional descriptions, dimensions, materials and specifications. Filter by brand, price, rating or stock. Export to JSON, CSV or Excel.

- **URL**: https://apify.com/datascraperes/wayfair-scraper.md
- **Developed by:** [DataScraperES](https://apify.com/datascraperes) (community)
- **Features:** Limited permissions
- **Stats:** 17 total users, 0 monthly users, 97.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.75 / 1,000 catalog records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

Collect Wayfair product specifications, prices, images, listings and stock for the **United States, Canada and United Kingdom**. Start with a SKU, category URL or search term and export structured results to JSON, CSV or Excel.

### What this Actor does

Five modes deliver one Dataset record per collected product, listing, search resolution or stock check:

- **Products** (`products`): identity, current price, description, feature bullets, specifications, dimensions, product weight and materials when supplied by Wayfair.
- **Category listing** (`category`): paginated listings with brand, price, rating, review count, stock and usable image URLs. Enable `includeDetails` to add product specifications to each listing.
- **Search for products** (`searchProducts`): resolves keywords and collects the resulting listings, or the directly matched product. Supports optional details, listing filters and source ordering.
- **Search resolution** (`search`): preserves the lightweight mode that returns a resolved category or product URL for each term.
- **Stock by postal code** (`inventory`): checks availability and quantity for specific SKUs in one delivery area.

No Wayfair account is required. Specifications and dimensions retain the source labels and units. Savings and discount percentages are calculated from comparable current and previous prices.

### Use cases

- Build a furniture catalog with descriptions, materials and product dimensions.
- Compare assortments and prices across keyword or category listings.
- Find products within a price range, brand, rating or stock requirement.
- Monitor price and availability changes by running the same input again.

### How to use

1. Open the Actor in Apify Console.
2. Choose **Products** and enter a SKU, or **Search for products** and enter keywords.
3. For listing modes, optionally enable product details and choose filters or ordering.
4. Set **Maximum records**, click **Start**, then open the **Dataset**.

### Input

The form groups collection settings, source inputs, listing options and advanced filters. Choose **Products by keyword** to collect keyword results, or **Search destinations (URLs only)** to return just the matching destination. Existing API mode values remain unchanged.

If the Actor detects invalid input, read the warning in the run log, correct the indicated field or item, and run again. Basic input mistakes stop before collection. Category filters and brands are checked against the options available for each listing; invalid selections are skipped without delivering or charging results for that listing. Apify may reject malformed JSON or values outside the input schema before a run starts; in that case, correct the fields highlighted in the form.

Only identifiers for the selected mode are required. The complete example below collects one product.

- `mode`: `products` (default), `category`, `searchProducts`, `search` or `inventory`.
- `productUrls`: up to 200 product URLs or SKUs, used by products/inventory. The URL domain determines its market. Duplicate SKUs are collected once per market.
- `categoryUrls`: up to 20 category URLs or numeric IDs for category mode.
- `searchTerms`: up to 20 terms for search/searchProducts.
- `filters`: optional advanced category filters, up to 10 pairs. Use **Add item** to fill the **Filter ID** and **Option ID** boxes; no JSON editing is needed. Find available pairs in `REFINEMENTS`. Prefer the Brand, Price, Rating and In stock controls for everyday filtering.
- `postalCode`: required by inventory; used as the listing delivery context. It must be valid for every selected market.
- `market`: `us`, `ca` or `uk`; used for identifiers without a domain.
- `maxItems`: between 1 and 500 results across the run, default 50. The prepared example uses one.
- `includeDetails`: default false. Adds product details to category/searchProducts listings before delivery.
- `brand`: an exact brand name offered in the source refinements, compared without case sensitivity or trademark symbols. Empty disables it. An unavailable brand is reported rather than collecting an unrestricted catalog.
- `minPrice`, `maxPrice`: bounds in the market currency. Zero disables a bound. With an enabled bound, unknown prices are excluded.
- `minRating`: 0–5; zero disables. Unknown ratings are excluded when enabled.
- `inStockOnly`: default false. When enabled, includes only explicit in-stock listings; unknown stock is excluded.
- `sortBy`: `RECOMMENDED` (default), `REVIEW_RATING`, `PRICE_PER_ITEM_ASC` or `PRICE_PER_ITEM_DESC`. This is the source order, including any sponsored placements.

The seven listing controls from `includeDetails` through `sortBy` require category or searchProducts mode when enabled. Neutral values remain valid in other modes. Price/rating/stock filters are applied to received listings; they may require scanning additional pages. A directly matched product can have fewer listing fields, so controls requiring absent values exclude it.

```json
{
  "mode": "products",
  "productUrls": [
    "W009559366"
  ],
  "categoryUrls": [
    "https://www.wayfair.com/furniture/sb0/sofas-c413892.html"
  ],
  "searchTerms": [
    "coffee table"
  ],
  "filters": [],
  "postalCode": "10001",
  "market": "us",
  "maxItems": 1,
  "includeDetails": false,
  "brand": "",
  "minPrice": 0,
  "maxPrice": 0,
  "minRating": 0,
  "inStockOnly": false,
  "sortBy": "RECOMMENDED"
}
```

### Output

The default Dataset contains one final record per delivered item. `SUMMARY` reports delivered counts, completeness and unresolved inputs; category and keyword listing collections also store available source filters in `REFINEMENTS`.

Product details use `description`, `featureBullets`, `specifications`, `dimensions`, `productWeight` and `materials`. `detailsFetched` means the product detail response was validated; individual fields can still be absent. Specification groups contain named items and any child items. Listing images are available as `imageIds`, `imageUrl` and `imageUrls`. `savings` and `discountPercent` are calculated comparisons, not a guarantee of a promotional offer. Unavailable scalar values are null; unavailable collections are empty arrays.

This is the complete Dataset item from the successful input above:

```json
{
  "description": "Festive and elegant at the same time, this Foil Print Snowflake Table Runner is perfect to dress up your holiday tablescape for special occasions and celebrations. It features an allover foil snowflake pattern print on vivid red background brings an ultra-glam appeal. Designed with a metallic glowing accent, this table runner will add grace and finesse to your holiday tabletop, pair with shimmery placemats or solid color flatware for a complete wow effect.",
  "featureBullets": [
    "PERFECT HOLIDAY DINING TABLE COVER – This rectangle table cover is perfectly sized for layering your table décor. The festive red and metallic gold hues make this elegant table runner is perfect for an eye-catching winterly look. It not only protects wooden tables but also offers a stylish background for your holiday tableware and centerpieces. Pair with our matching placemats and napkins for a coordinated look.",
    "PREMIUM QUALITY – We craft our festive table linen from superior quality with 100% polyester construction. Durable and easy to clean, this gorgeous table cover is sure to offer an inviting enhancement to your dining area while protecting the table against scratches and spills. Care: Machine wash cold, delicate cycle, hang dry.",
    "MULTI-PURPOSE UTILIZATION – Elegance and charm, this Foil Print Snowflake Table Runner added flair to your holiday tablescapes. Use it to decorating indoor/outdoor parties and banquets, or use it inside when hosting casual or holiday meals for friends and family which helps protect your table from any potential scratches and messy spills. Mix and match or blend with your favorite holiday décor to create an elegant chic Christmas dining table décor.",
    "CREATIVE GIFT IDEA – Makes a thoughtful and functional housewarming gift, hostess gift with this stylish table linen for Thanksgiving, Christmas, Birthday or any other special events."
  ],
  "specifications": [
    {
      "group": "FEATURES",
      "items": [
        {
          "name": "Product Type",
          "value": "Table Runnner",
          "children": []
        },
        {
          "name": "Overall Shape",
          "value": "Rectangle",
          "children": []
        },
        {
          "name": "Material",
          "value": "Polyester",
          "children": []
        },
        {
          "name": "Pattern",
          "value": "Floral",
          "children": []
        },
        {
          "name": "Color",
          "value": "Red",
          "children": []
        },
        {
          "name": "General Features",
          "value": "Reversible",
          "children": []
        }
      ]
    },
    {
      "group": "WARRANTY",
      "items": [
        {
          "name": "Commercial Warranty",
          "value": "No",
          "children": []
        }
      ]
    }
  ],
  "dimensions": [
    {
      "group": null,
      "items": [
        {
          "name": "Overall Dimensions",
          "value": "16'' D X 54'' L",
          "children": []
        },
        {
          "name": "Overall Product Weight",
          "value": "0.5 lb.",
          "children": []
        }
      ]
    }
  ],
  "productWeight": "0.5 lb.",
  "materials": [
    "Polyester"
  ],
  "detailsFetched": true,
  "recordType": "product",
  "market": "us",
  "sku": "W009559366",
  "variantId": "AV23077906",
  "name": "Red Holiday Foil Snowflake 16\"x54\" Table Runner",
  "brand": null,
  "url": "https://www.wayfair.com/kitchen-tabletop/pdp/the-holiday-aisle-red-holiday-foil-snowflake-16x54-table-runner-w009559366.html?piid=766195378",
  "price": 19.99,
  "wasPrice": null,
  "currency": "USD",
  "stockStatus": null,
  "stockMessage": null,
  "maxPurchasableQuantity": null,
  "availableQuantity": null,
  "rating": null,
  "reviewCount": null,
  "classId": null,
  "className": null,
  "categoryId": null,
  "categoryName": null,
  "imageIds": [],
  "choiceCategories": [
    {
      "name": null,
      "selected": "72920960",
      "optionCount": null
    }
  ],
  "categoryUrl": null,
  "resultType": null,
  "postalCode": "10001",
  "sourceInput": "W009559366",
  "scrapedAt": "2026-11-02T14:01:27.011430+00:00",
  "imageUrls": [],
  "imageUrl": null,
  "savings": null,
  "discountPercent": null
}
```

### Pricing

This Actor uses pay-per-event pricing. One `product` event corresponds to one verified Dataset record: a product, listing, search resolution or stock row. Optional details are included in that same result. There is no startup fee or separate usage charge. Invalid selections and inputs that produce no delivered record are not charged; a valid listing preserved after an optional detail failure is still a delivered record.

| Apify tier | Price per delivered result (USD) | Equivalent per 1,000 results (USD) |
|---|---:|---:|
| FREE | $0.00100 | $1.00 |
| BRONZE | $0.00090 | $0.90 |
| SILVER | $0.00080 | $0.80 |
| GOLD | $0.00075 | $0.75 |
| PLATINUM | $0.00075 | $0.75 |
| DIAMOND | $0.00075 | $0.75 |

Apify applies the rate for your plan. The run stops when its spending limit prevents another delivery. Check the **Pricing** tab before starting for the current configuration.

### Related Actors

| Actor | Best for |
|---|---|
| [Shopify Products Scraper | Prices & Variants](https://apify.com/datascraperes/shopify-products-scraper) | Comparing Wayfair prices against Shopify store catalogs |
| [Houzz Scraper | Photos, Products, Pros & Ideas](https://apify.com/datascraperes/houzz-content-scraper) | Home-improvement and interior product research next to furniture data |
| [Craigslist Scraper | Listings, Prices & Details](https://apify.com/datascraperes/craigslist-scraper) | Used-furniture and local-marketplace price comparison |

### Limits and data quality

- Supported markets are the United States, Canada and United Kingdom. Other storefronts are outside this contract. SKUs and category IDs are market-specific.
- Products returns detail and price fields. Brand, rating, stock and listing images generally come from category/keyword listings and may be null or empty for a direct SKU.
- Review counts and average ratings are supported on listings; individual reviews, AI review summaries and exhaustive variant enumeration are not collected.
- Listing collection follows up to 40 pages per input, up to 24 listings per page, stopping at the record cap or source end. Filtering can yield fewer records than requested. A page limit reached before source end is reported as partial.
- `searchProducts` follows supported category, product and keyword listing resolutions. An unresolved search is reported; the Actor does not replace it with an unrelated category.
- Optional detail failure preserves the base listing with `detailsFetched: false` and makes the run partial. Details are merged only for the same verified SKU and variant.
- Prices, stock and images reflect available source data and can change. Delivery dates, a complete product gallery and every available variant are not guaranteed.
- Without a listing postal code, the delivery context defaults to 10001 (US), M5V 2T6 (Canada) or SW1A 1AA (UK). Use separate runs for different delivery areas.
- A record cap or a verified source end is a valid completion, including zero matches after filtering. Source outages, missing products and incomplete or unprocessable source responses are recorded in `SUMMARY`: `outcome: "partial"` when rows were preserved, or `"source_unavailable"` when none could be collected. These handled source problems end normally with `complete: false`; they never indicate a complete collection. A spending limit can also stop collection normally, with `"stopped"` when no records were delivered. Check `SUMMARY.complete` when deciding whether all requested work finished.
- Invalid user input logs a warning explaining what to correct. If all requested selections are invalid, `SUMMARY` reports `outcome: "invalid_input"` and `complete: false`. Rejected selections produce no result events, and filters are never silently removed to broaden a listing. Already saved records remain available. Unresolved storage, charging or recovery-state problems still fail the execution to protect your results and spending. An unverified saved-record count is reported as `null` rather than zero.
- A resumed run reuses verified saved rows. Start a new run to collect a fresh snapshot.
- Batches containing unusually large records can stop at a processing resource limit. Saved records remain available, the summary stays incomplete, and undelivered records are not charged.

### Frequently asked questions

#### How do I collect products for a keyword?

Choose `searchProducts` and fill `searchTerms`. The existing `search` mode returns only the resolved URL. Enable `includeDetails` if you also need descriptions and specifications.

#### How do I filter a category?

Use the friendly brand, price, rating and stock controls, or use `filterId`/`optionId` pairs from `REFINEMENTS`. Each filter and option must belong to the selected listing and market; a requested brand must also be offered there. Incorrect selections are skipped with an input warning. If available options cannot be verified, that listing is not collected with the requested source filters. Category filters cannot be applied to a directly matched product. Missing values do not satisfy enabled price, rating or stock conditions.

#### Are the product weight and dimensions converted?

No. They retain Wayfair's labels and units. `productWeight` is the reported overall product weight, not the weight capacity.

#### Why are some fields empty?

Wayfair supplies different fields on listings and product details. Enable optional details for listing modes where needed. Check `SUMMARY` to distinguish an absent optional field from a failed collection.

### Responsible use

Use the Actor lawfully and comply with Wayfair's terms and applicable privacy rules and regulations. Collect public catalog data responsibly and do not misrepresent availability or pricing.

### Support

Open an issue in the Actor's **Issues** tab with your input and run ID.

[Python, JavaScript and CSV integration examples on GitHub](https://github.com/datacrawler-edu/wayfair-product-data-api)

# Actor input Schema

## `mode` (type: `string`):

Choose Product details for product URLs or SKUs; Category products for category URLs or IDs; Products by keyword for keyword results; Stock by postal code for stock checks. Search destinations returns the matching destination URL rather than its product listing.

## `market` (type: `string`):

Wayfair storefront used when the identifier does not include a domain. Products and category IDs are market-specific: a US SKU does not resolve on the Canadian or UK site.

## `maxItems` (type: `integer`):

Upper bound for unique records across the whole run. Reaching this cap is a valid completion when no collection or delivery problems remain. Missing or incomplete data is reported separately in the run summary.

## `productUrls` (type: `array`):

Add one Wayfair product URL or SKU per item, for example W005299789. URLs may come from wayfair.com, wayfair.ca or wayfair.co.uk; the market is detected from the domain and overrides the market setting. Used by the Products and Inventory modes. Up to 200 identifiers.

## `categoryUrls` (type: `array`):

Add one Wayfair category URL or numeric category ID per item, for example https://www.wayfair.com/furniture/sb0/sofas-c413892.html or 413892. Used by the Category mode. Up to 20 categories.

## `searchTerms` (type: `array`):

Add one keyword or phrase per item, such as coffee table. Used by Products by keyword and Search destinations. Up to 20 terms.

## `postalCode` (type: `string`):

Postal code used for stock and delivery information and the shipping context of listings. Required by Inventory. It must be valid for every market selected by the active input URLs. Omitted category postal codes default to 10001 (US), M5V 2T6 (Canada), or SW1A 1AA (UK).

## `includeDetails` (type: `boolean`):

Enrich category/searchProducts rows with description, dimensions and specifications before delivery. A failed enrichment preserves the listing and marks the run partial. Used only by category and searchProducts.

## `brand` (type: `string`):

Exact brand name offered by the category/search refinement. Empty disables. Unavailable brands produce an input warning and skip that listing, never a broader unfiltered catalog. Used only by category and searchProducts.

## `minPrice` (type: `number`):

Keep known prices at or above this value in the market currency. Zero disables. Missing prices are excluded when enabled. Used only by category and searchProducts.

## `maxPrice` (type: `number`):

Keep known prices at or below this value. Zero disables. Missing prices are excluded when enabled. Used only by category and searchProducts.

## `minRating` (type: `number`):

Keep known ratings at or above this value. Zero disables. Missing ratings are excluded when enabled. Used only by category and searchProducts.

## `inStockOnly` (type: `boolean`):

Keep listings explicitly marked IN_STOCK. Unknown stock is excluded. Used only by category and searchProducts.

## `sortBy` (type: `string`):

Source order for category/searchProducts. Filtering preserves that order. Used only by category and searchProducts.

## `filters` (type: `array`):

Optional advanced filters. Click Add item and fill Filter ID and Option ID in the form; no JSON is needed. Use identifiers from a previous listing run in REFINEMENTS. For most runs, use the Brand, Price, Rating and In stock controls instead. Leave empty to apply no additional source filters.

## Actor input object example

```json
{
  "mode": "products",
  "market": "us",
  "maxItems": 1,
  "productUrls": [
    "W009559366"
  ],
  "categoryUrls": [
    "https://www.wayfair.com/furniture/sb0/sofas-c413892.html"
  ],
  "searchTerms": [
    "coffee table"
  ],
  "postalCode": "10001",
  "includeDetails": false,
  "brand": "",
  "minPrice": 0,
  "maxPrice": 0,
  "minRating": 0,
  "inStockOnly": false,
  "sortBy": "RECOMMENDED",
  "filters": []
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (type: `string`):

No description

## `refinements` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "products",
    "market": "us",
    "maxItems": 1,
    "productUrls": [
        "W009559366"
    ],
    "categoryUrls": [
        "https://www.wayfair.com/furniture/sb0/sofas-c413892.html"
    ],
    "searchTerms": [
        "coffee table"
    ],
    "postalCode": "10001",
    "includeDetails": false,
    "brand": "",
    "minPrice": 0,
    "maxPrice": 0,
    "minRating": 0,
    "inStockOnly": false,
    "sortBy": "RECOMMENDED",
    "filters": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("datascraperes/wayfair-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "products",
    "market": "us",
    "maxItems": 1,
    "productUrls": ["W009559366"],
    "categoryUrls": ["https://www.wayfair.com/furniture/sb0/sofas-c413892.html"],
    "searchTerms": ["coffee table"],
    "postalCode": "10001",
    "includeDetails": False,
    "brand": "",
    "minPrice": 0,
    "maxPrice": 0,
    "minRating": 0,
    "inStockOnly": False,
    "sortBy": "RECOMMENDED",
    "filters": [],
}

# Run the Actor and wait for it to finish
run = client.actor("datascraperes/wayfair-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "products",
  "market": "us",
  "maxItems": 1,
  "productUrls": [
    "W009559366"
  ],
  "categoryUrls": [
    "https://www.wayfair.com/furniture/sb0/sofas-c413892.html"
  ],
  "searchTerms": [
    "coffee table"
  ],
  "postalCode": "10001",
  "includeDetails": false,
  "brand": "",
  "minPrice": 0,
  "maxPrice": 0,
  "minRating": 0,
  "inStockOnly": false,
  "sortBy": "RECOMMENDED",
  "filters": []
}' |
apify call datascraperes/wayfair-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datascraperes/wayfair-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/5UNWHisSZSBnSTuh1/builds/pvLMbqxxML7MUQSfG/openapi.json
