# Woot Scraper (`crawlerbros/woot-scraper`) Actor

Scrape Woot.com daily deals - browse or search live offers across Electronics, Computers, Home, Tools, Sport, Grocery, Shirt.Woot and Clearance, fetch offer detail by slug/URL, and pull active site-wide events. Prices, discounts, images, stock status, ratings.

- **URL**: https://apify.com/crawlerbros/woot-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** E-commerce, Automation, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

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

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Woot Scraper

Scrape live deals from [Woot.com](https://www.woot.com) — Amazon's daily-deals site. Search or browse offers across Electronics, Computers, Home & Kitchen, Sports & Outdoors, Tools & Garden, Grocery, Shirt.Woot, Wine.Woot, and Clearance; fetch a specific offer by its slug or URL; or list active site-wide events (Woot-Offs, seasonal sales). HTTP-only, no login, no cookies, no residential proxy.

### What this actor does

- **Four modes:** `search` (keyword + category browse), `byOfferSlugs` (exact offer lookup), `activeEvents` (site-wide sales/Woot-Offs currently running), `byEventSlugs` (every individual offer within one specific event/Woot-Off)
- **Full category coverage:** all 10 Woot categories/sub-sites (or search across all of them at once)
- **Sort options:** best selling, biggest discount, newest, price high→low, price low→high
- **Filters:** min/max sale price, min discount %, sold-out inclusion, item color (server-side facet)
- **Rich offer data:** title, sale/list price, discount %, images, stock status, Amazon review stars/count, event info, item condition/color/model, SKU, and a full per-purchase-option breakdown (size/color/model/capacity/etc.) for multi-option offers
- **Empty fields are omitted** — no null/placeholder values in the output

### Output per offer

`offerId`, `title`, `subtitle`, `slug`, `offerUrl`, `soldOut`, `isFeatured`, `isAppFeatured`, `isWootOff`, `discountPercentage`, `salePrice`, `salePriceMax`, `listPrice`, `listPriceMax`, `itemCount`, `stockQuantity`, `totalUnitsSold`, `firstOrderedAt`, `lastOrderedAt`, `imageUrl`, `eventType`, `eventSlug`, `siteHostname`, `siteName`, `endDate`, `startDate`, `tags`, `purchaseLimit`, `sku`, `features`, `specs`, `writeUp`, `teaser`, `reviewStars`, `reviewCount`, `asin`, `condition`, `color`, `model`, `itemVariants`, `taxonomyCategory`, `taxonomyProductCategory`, `taxonomyProductGroup`, `shippingOptions`, `recordType`, `scrapedAt`.

`taxonomyCategory` / `taxonomyProductCategory` / `taxonomyProductGroup` — Woot's own internal category taxonomy for the offer (e.g. `Accessories` / `TECH` / `Batteries`), more granular than the top-level `category` search filter.

`shippingOptions` — the real shipping cost tiers Woot charges for this offer (`[{name, itemCost, eventCost, orderCost}]`, e.g. `Standard`/`Two-Day`/`One-Day`); cost components are only included when non-zero.

`itemVariants` — full per-purchase-option breakdown (`[{asin, imageUrl, salePrice, listPrice, quantity, attributes}]`) for offers with more than one buyable option (e.g. different sizes/colors/capacities/models bundled under one offer). `imageUrl` is that specific variant's own product photo when Woot has one (often differs from the offer's main `imageUrl`, e.g. each color option's own photo). `attributes` is a free-form key/value map since Woot has no fixed schema (observed keys include `Color`, `Size`, `Model`, `Capacity`, `Carrier`, `Screen Size`, `Style`, `Count`, `Fit`, `Gender`, `Condition`). Omitted for single-option offers.

`stockQuantity` is the total remaining units across all SKU variants of the offer (summed from Woot's own per-item inventory count) — a useful signal for deal urgency alongside `soldOut`.

`totalUnitsSold` is the cumulative number of units Woot has sold for this offer to date (its own running order count); `firstOrderedAt`/`lastOrderedAt` are the timestamps of the first and most recent purchase — together a real popularity signal independent of `reviewCount`/`reviewStars`.

Event records (`mode=activeEvents`) use a subset: `eventId`, `title`, `subtitle`, `slug`, `eventType`, `eventUrl`, `startDate`, `endDate`, `siteHostname`, `siteName`, `imageUrl`, `recordType`, `scrapedAt`.

`mode=byEventSlugs` returns full offer records (same fields as `mode=search`/`byOfferSlugs`, `recordType: "offer"`) for every individual offer that belongs to the given event(s) — useful for grabbing an entire themed multi-item sale or Woot-Off in one call instead of enumerating individual offer slugs by hand. Every returned offer also carries `eventSlug` echoing which event it came from.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` / `byOfferSlugs` / `activeEvents` / `byEventSlugs` |
| `keyword` | string | `headphones` | Free-text search across offer titles (mode=search) |
| `category` | string | `all` | One of 10 Woot categories, or `all` — also used for mode=activeEvents |
| `sortBy` | string | `BestSelling` | `BestSelling` / `DiscountPercentage` / `NewestFirst` / `PriceHighToLow` / `PriceLowToHigh` (mode=search) |
| `soldOutFilter` | string | `excludeSoldOut` | `excludeSoldOut` / `any` / `onlySoldOut` |
| `minPrice` / `maxPrice` | integer | – | Sale-price bounds in USD |
| `minDiscountPercentage` | integer | – | Minimum discount off list price |
| `condition` | string | – | Only keep offers whose condition contains this text, e.g. `New`, `Refurbished` |
| `color` | string | – | Exact item color/finish (case-insensitive, e.g. `Black`, `Blue`) — server-side facet (mode=search) |
| `offerSlugs` | array | – | Offer slugs or full URLs (mode=byOfferSlugs) |
| `eventSlugs` | array | – | Event slugs or full URLs (mode=byEventSlugs) |
| `maxItems` | integer | `40` | Cap on emitted records (1-500) |

#### Example: search deals by keyword

```json
{
  "mode": "search",
  "keyword": "headphones",
  "category": "all",
  "sortBy": "BestSelling",
  "soldOutFilter": "excludeSoldOut",
  "maxItems": 40
}
```

#### Example: browse biggest discounts in a category

```json
{
  "mode": "search",
  "category": "tech",
  "sortBy": "DiscountPercentage",
  "minDiscountPercentage": 30,
  "maxItems": 40
}
```

#### Example: fetch specific offers by slug

```json
{
  "mode": "byOfferSlugs",
  "offerSlugs": ["philips-g3-wired-over-ear-gaming-headphones"]
}
```

#### Example: list active Woot-Offs / site-wide sales

```json
{
  "mode": "activeEvents",
  "category": "all"
}
```

### Use cases

- **Deal aggregation** — pull live daily deals for a deals-alert site, newsletter, or browser extension.
- **Price-drop tracking** — monitor `discountPercentage`, `salePrice`, and `stockQuantity` for target products.
- **Reseller sourcing** — find deeply discounted inventory (`minDiscountPercentage`) worth flipping.
- **Market research** — analyze category mix, pricing, and Amazon review signals across Woot's daily catalog.
- **Event/Woot-Off coverage** — grab every offer in a themed multi-item sale in one call via `byEventSlugs`.

### FAQs

**Do I need Woot login or cookies?**
No. This actor reads Woot's own public deals API anonymously, exactly like a signed-out visitor's browser does.

**Does it include sold-out deals?**
By default, sold-out offers are excluded. Set `soldOutFilter` to `any` or `onlySoldOut` to include/target them. Note: with `soldOutFilter=any`, sold-out and in-stock offers are fetched as two separate passes (sold-out first) and `sortBy` is applied independently within each pass, so the combined output is not one continuous global sort across the sold-out/in-stock boundary; with `excludeSoldOut` or `onlySoldOut` the sort is fully global.

**Can I look up one specific deal?**
Yes — use `mode=byOfferSlugs` with the offer's slug (from its URL, e.g. `philips-g3-wired-over-ear-gaming-headphones`) or the full `woot.com/offers/...` URL.

**How current is the data?**
Every run reads Woot's live deals feed — prices, stock, and discounts reflect what's on the site at run time. Woot rotates its "deal of the day" offers roughly every 24 hours.

### Limitations

- Woot's site-wide text search box redirects to category browsing in the UI; this actor uses the same `Keyword` filter the site's own search-as-you-browse feature uses, which matches offer titles.
- Per-offer customer reviews (full review text) are not exposed by the public API — only the aggregate Amazon star rating and review count are available.
- `activeEvents` reflects currently-running site-wide sales/Woot-Offs; Woot does not run one on every category at all times, so an empty result for a given category is expected and reported via a status message, not an error.
- Woot's `sellout` (clearance) category and other high-turnover offers can genuinely sell out and disappear from the site within minutes of being scraped — every field reflects the exact moment the run executed, so an `offerUrl` may occasionally 404 by the time you visit it. This is normal churn on a flash-deal site, not a broken link.
- The `category` filter narrows by Woot's own internal category grouping, not strictly by which sub-site (`siteHostname`) hosts the offer -- Woot itself occasionally cross-lists an offer under a category (e.g. `home`) while hosting it on another sub-site's domain (e.g. `electronics.woot.com`). This is confirmed live against Woot's own GraphQL API (not an artifact of this actor), so a `home`-filtered run can legitimately include a handful of `siteHostname` values other than `home.woot.com`.

# Actor input Schema

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

What to fetch.

## `keyword` (type: `string`):

Free-text search across offer titles (e.g. `headphones`, `air fryer`). Leave empty to browse a category or all deals.

## `category` (type: `string`):

Restrict to one Woot category/sub-site. `all` searches every category. Also used as the category for mode=activeEvents.

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

Result ordering. Applied within each fetch pass; when `soldOutFilter` is `any`, sold-out and in-stock offers are fetched as two separate passes (sold-out first) and each pass is independently sorted, so the combined output is not one continuous global sort across the sold-out/in-stock boundary. With `excludeSoldOut` or `onlySoldOut` (a single pass) the sort is fully global.

## `soldOutFilter` (type: `string`):

Whether to include sold-out offers.

## `minPrice` (type: `integer`):

Drop offers whose sale price is below this.

## `maxPrice` (type: `integer`):

Drop offers whose sale price is above this.

## `minDiscountPercentage` (type: `integer`):

Drop offers discounted less than this percentage off list price.

## `condition` (type: `string`):

Only keep offers whose condition contains this text (case-insensitive), e.g. `New`, `Refurbished`, `Reconditioned`. Offers without a condition attribute always pass.

## `color` (type: `string`):

Restrict to offers with this exact item color/finish (case-insensitive, e.g. `Black`, `Blue`, `White`). Applied server-side via Woot's own `Color` facet, so it narrows the source results (not just a post-filter). Color values vary per product line, so this is free text rather than a fixed dropdown; leave blank to include every color. Not available in mode=byOfferSlugs or mode=activeEvents.

## `offerSlugs` (type: `array`):

Woot offer slugs (e.g. `philips-g3-wired-over-ear-gaming-headphones`) or full offer URLs.

## `eventSlugs` (type: `array`):

Woot event slugs (e.g. `samsung-hw-q990f`) or full event URLs (`woot.com/events/<slug>`). Returns every individual offer that belongs to that event/Woot-Off/multi-item sale -- useful for grabbing a whole themed sale in one call instead of guessing offer slugs.

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

Hard cap on emitted records.

## Actor input object example

```json
{
  "mode": "search",
  "keyword": "headphones",
  "category": "all",
  "sortBy": "BestSelling",
  "soldOutFilter": "excludeSoldOut",
  "offerSlugs": [],
  "eventSlugs": [],
  "maxItems": 40
}
```

# Actor output Schema

## `deals` (type: `string`):

Dataset containing all scraped Woot offers/events.

# 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": "search",
    "keyword": "headphones",
    "category": "all",
    "sortBy": "BestSelling",
    "soldOutFilter": "excludeSoldOut",
    "offerSlugs": [],
    "eventSlugs": [],
    "maxItems": 40
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/woot-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": "search",
    "keyword": "headphones",
    "category": "all",
    "sortBy": "BestSelling",
    "soldOutFilter": "excludeSoldOut",
    "offerSlugs": [],
    "eventSlugs": [],
    "maxItems": 40,
}

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

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": "search",
  "keyword": "headphones",
  "category": "all",
  "sortBy": "BestSelling",
  "soldOutFilter": "excludeSoldOut",
  "offerSlugs": [],
  "eventSlugs": [],
  "maxItems": 40
}' |
apify call crawlerbros/woot-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=crawlerbros/woot-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ce2d7AickD37Nz5lo/builds/zTvBpgp8IEzoAE4US/openapi.json
