# Whatnot Scraper (`phantom_coder/whatnot-scraper`) Actor

Scrape Whatnot listings, live shows, sellers, and categories in one dataset. Track viewer and show-count stats over time, monitor only new or changed items, and add an AI Fair Value estimate for Pokémon cards. No account needed.

- **URL**: https://apify.com/phantom_coder/whatnot-scraper.md
- **Developed by:** [Phantom Coder](https://apify.com/phantom_coder) (community)
- **Categories:** E-commerce, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 whatnot results

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

## Whatnot Scraper

Scrape **listings, live shows, sellers, reviews, and category demand** from [Whatnot](https://www.whatnot.com) in one flat dataset - with monitor mode for an ongoing feed of changes, and category snapshots that show where demand is moving run over run. No Whatnot account or API key required.

***

### Who is this for

- **Resellers and dropshippers** tracking a keyword or a seller's shop daily for new or repriced listings, without refreshing Whatnot by hand
- **Category and trend researchers** watching viewer counts and live-show counts for a niche (for example `pokemon_cards`) to spot when demand is rising or falling
- **Lead generation and competitor research teams** building seller lists with follower counts, ratings, and sold counts for a keyword or category
- **Collectors and investors** pulling Pokémon single-card listings with an AI-powered fair value estimate to spot underpriced copies

***

### Why it's different

Most Whatnot scrapers return one shape of data for one mode: a keyword search, or a seller profile, or a category feed. This Actor combines all of them into **one dataset with a `recordType` column**, so a single run (or a single schedule) can cover a keyword search, a seller's shop, and a category's demand at once - and adds two things none of the alternatives combine: **category and live-show stats tracked over time**, and **monitor mode**.

For example, scheduling this Actor once a day against `categories: ["pokemon_cards"]` with `trackCategoryStats` on produces a `categorySnapshot` row each day like:

```
viewerCount: 18,420   viewerDelta: +881 (+5%)   liveShowCount: 431   liveShowDelta: +13
top1SellerUsername: "cardbreakers_co"   top1ShowViewers: 612   top1RankChange: +2
```

That `viewerDelta`/`liveShowDelta` pair - and seeing a seller jump 2 ranks in the category's top shows - is what tells you demand is moving, which a single snapshot never shows on its own.

***

### What you get

- **Listings** - price, format (auction or buy it now), condition-aware filtering, seller, and whether it is being sold live right now
- **Live shows** - status, viewer count, categories, tags, and host, from a search, a category, or a seller
- **Sellers** - profile, rating breakdown, follower/sold counts, and optionally their shop, shows, and reviews
- **Reviews** - buyer reviews and ratings for a seller
- **Categories** - the category tree, or a single category's live demand
- **Category snapshots** - viewer count, live-show count, and top live shows right now, plus the change since the last run
- **Monitor mode** - only new or changed listings, shows, and sellers since the last run with the same input
- **Fair Value Analysis add-on** - an AI-powered fair value estimate for Pokémon single-card listings

***

### How to use

<ol>
<li>Open the Actor and, under <strong>Start points</strong>, add search terms, Whatnot URLs, sellers, or categories - any combination.</li>
<li>Set limits and filters if you want fewer or more targeted results.</li>
<li>Turn on <strong>Category and live-show stats tracking</strong> or <strong>Monitor mode</strong> if you plan to schedule this Actor.</li>
<li>Click <strong>Start</strong>, then open the dataset and switch between the view tabs (Listings, Live shows, Sellers, ...) to see each record type on its own.</li>
</ol>

> ⚠️ The first run with `monitorMode` on pushes every result as `new` - there is nothing to compare against yet. On a later run, **0 rows is a normal result**: it means nothing changed since last time, not that something failed.

### Input configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `searchQueries` | array | `["pokemon cards"]` | Terms to search for |
| `searchType` | string | `products` | `products`, `liveShows`, `sellers`, or `all` |
| `startUrls` | array | `[]` | Any Whatnot URL (listing, seller, live show, category, or search) |
| `sellers` | array | `[]` | Usernames or profile URLs |
| `categories` | array | none | Category slugs or URLs, for example `pokemon_cards` |
| `listCategoryTree` | boolean | `false` | Return the category tree instead of scraping |
| `categoryTreeDepth` | integer | `2` | Levels of subcategories to include |
| `maxResultsPerQuery` | integer | `30` | Max results per search term |
| `maxResultsPerSeller` | integer | `30` | Max shop listings/shows/reviews per seller |
| `maxResultsPerCategory` | integer | `30` | Max live shows per category - set to `0` for category-level stats only |
| `minPrice` / `maxPrice` | number | none | Price range in USD |
| `listingFormat` | string | `any` | `any`, `auction`, or `buyItNow` |
| `condition` | array | `[]` | Condition values, when the category offers one |
| `sortBy` | string | `bestMatch` | Price sort for product searches, viewer sort for live-show searches |
| `excludeSellers` | array | `[]` | Usernames to leave out of every result |
| `includeSellerShop` | boolean | `true` | Return each seller's current shop listings |
| `includeSellerShows` | boolean | `true` | Return each seller's live/scheduled shows |
| `includeSellerReviews` | boolean | `false` | Return each seller's buyer reviews |
| `trackCategoryStats` | boolean | `false` | Add a category snapshot row with deltas since the last run |
| `monitorMode` | boolean | `false` | Push only new or changed rows since the last run |
| `trackingStoreName` | string | `whatnot-tracking` | Key-value store name used to remember state between runs |
| `resetTracking` | boolean | `false` | Clear stored tracking state before this run |
| `enableFairValue` | boolean | `false` | Add-on: Fair Value Analysis for Pokémon singles ($) |

`includeSellerShop` and `includeSellerShows` are on by default, so scraping a seller normally returns their shop listings and shows as extra rows alongside the seller row itself - each one charged as a result, same as any other row. For example, 1 seller with 30 shop listings and 2 shows returns 33 rows, about $0.036 on Free.

```json
{
  "searchQueries": ["pokemon cards"],
  "searchType": "products",
  "categories": ["pokemon_cards"],
  "maxResultsPerQuery": 30,
  "trackCategoryStats": true,
  "enableFairValue": false
}
```

***

### Output

One flat dataset, discriminated by `recordType`. A field only used by one record type is simply absent (not `null`-padded) on the others.

**`listing`:**

```json
{
  "recordType": "listing",
  "listingId": 2452163974,
  "url": "https://www.whatnot.com/listing/TGlzdGluZ05vZGU6MjQ1MjE2Mzk3NA==",
  "title": "Charizard ex 199/165 SIR 151 PSA 10",
  "status": "ACTIVE",
  "listingFormat": "buyItNow",
  "priceUsd": 450,
  "currency": "USD",
  "isLive": false,
  "categoryLabel": "Pokemon Cards",
  "sellerUsername": "firepalmcreations",
  "sellerUrl": "https://www.whatnot.com/user/firepalmcreations",
  "sellerRatingOverall": 5,
  "fairValueUsd": 315.97,
  "fairValueBasis": "psa10",
  "psa10PriceUsd": 520,
  "discountVsBasisPct": 13.5,
  "source": "search",
  "searchQuery": "pokemon cards",
  "scrapedAt": "2026-10-21T16:00:00.000Z"
}
```

**`liveShow`:**

```json
{
  "recordType": "liveShow",
  "id": "dc46af2c-5e85-496c-9011-82c053949cb0",
  "url": "https://www.whatnot.com/live/dc46af2c-5e85-496c-9011-82c053949cb0",
  "title": "Pokemon break night",
  "status": "PLAYING",
  "isLive": true,
  "viewerCount": 612,
  "categoryLabels": ["Pokemon Cards"],
  "sellerUsername": "cardbreakers_co",
  "scrapedAt": "2026-10-21T16:00:00.000Z"
}
```

**`seller`:**

```json
{
  "recordType": "seller",
  "username": "pokemoncards",
  "url": "https://www.whatnot.com/user/pokemoncards",
  "followerCount": 360,
  "soldCount": 923,
  "ratingOverall": 4.9,
  "ratingNumReviews": 233,
  "isPremierShop": false,
  "shopListingCount": 42,
  "upcomingShowCount": 2,
  "scrapedAt": "2026-10-21T16:00:00.000Z"
}
```

**`review`:**

```json
{
  "recordType": "review",
  "sellerUsername": "firepalmcreations",
  "averageRating": 5,
  "overallReview": "Fast shipping, card exactly as described.",
  "reviewedByUsername": "buyer123",
  "reviewedOn": "2026-10-01T00:00:00Z",
  "scrapedAt": "2026-10-21T16:00:00.000Z"
}
```

**`category`:**

```json
{
  "recordType": "category",
  "slug": "pokemon_cards",
  "label": "Pokemon Cards",
  "viewerCount": 17539,
  "liveShowCount": 418,
  "url": "https://www.whatnot.com/tag/pokemon_cards",
  "scrapedAt": "2026-10-20T16:00:00.000Z"
}
```

**`categorySnapshot`:**

```json
{
  "recordType": "categorySnapshot",
  "category": "pokemon_cards",
  "viewerCount": 18420,
  "viewerDelta": 881,
  "viewerDeltaPct": 5,
  "liveShowCount": 431,
  "liveShowDelta": 13,
  "previousScrapedAt": "2026-10-20T16:00:00.000Z",
  "top1SellerUsername": "cardbreakers_co",
  "top1ShowViewers": 612,
  "top1RankChange": 2,
  "scrapedAt": "2026-10-21T16:00:00.000Z"
}
```

**Empty result** - a run with no matches succeeds with a clear status message and an empty dataset:

```json
{ "statusMessage": "Scraped 0 row(s) from 0 of 1 start point(s). 1 returned nothing." }
```

**Failed run** - when Whatnot can't be reached for every start point, the run fails instead of returning an empty dataset, and no results are charged:

```json
{ "statusMessage": "Whatnot could not be reached for 1 of 1 start point(s), and nothing was scraped. This is a temporary block or outage, not an empty result. Re-run the Actor in a few minutes." }
```

***

### Understanding the data

- **Category snapshot deltas** (`viewerDelta`, `viewerDeltaPct`, `liveShowDelta`) compare this run's numbers to the *last* snapshot taken for that category with this Actor, however long ago that was - they are `null` on the first run, because there is nothing to compare against yet.
- **`topNRankChange`** is how many places that seller's show moved up (positive) or down (negative) in the category's top 3 by viewers since the last snapshot; `null` means it was not in the previous top 3 at all.
- **Monitor mode `changeType`**: `new` (not seen before); listing - `priceChanged` or `statusChanged`; live show - `statusChanged`; seller - `soldCountChanged`, `followerCountChanged`, or `liveStatusChanged`. `previousValue` carries that field's old value. When more than one tracked field changed in the same run, `changeType` reports the highest-priority one and `changedFields` lists every field that changed, comma-separated.
- **Fair value basis**: `fairValueBasis` is the grade stated in the listing title - `raw` (ungraded), `psa9`, or `psa10`. `fairValueUsd` is an estimate for an ungraded copy, so `discountVsFairValuePct` is only set on `raw` listings. `discountVsBasisPct` compares every matched listing to the market price for its own grade (`rawPriceUsd`, `psa9PriceUsd`, or `psa10PriceUsd`).

***

### Common use cases

- **Daily repricing watch**: schedule with `monitorMode: true` and your keyword; act on any row with `changeType: "priceChanged"` and `previousValue - priceUsd > 5`. For a typical 30-result search, the first run costs about $0.033 on Free (everything is new); every run after that only charges for rows that actually changed, typically a few cents a month.
- **Category demand tracking**: schedule daily with `trackCategoryStats: true`; flag a category once `viewerDeltaPct > 20` two days running as "heating up."
- **Underpriced grading flips**: enable Fair Value Analysis and filter for `discountVsBasisPct > 15` on `fairValueBasis: "psa10"` rows.
- **Seller due diligence before a trade**: scrape a seller URL with `includeSellerReviews: true` and check `ratingAccuracy` and `ratingShipping` before relying on their shipping estimate.
- **Competitor seller lists**: search a niche keyword with `searchType: "sellers"`, then sort the seller rows by `followerCount` or `soldCount` in your spreadsheet and export them for outreach.

***

### FAQ

**Do I need a Whatnot account?** No. Everything this Actor returns is public, logged-out data.

**Why did I get 0 results?** Either the search term or seller has nothing matching your filters right now, or (with `monitorMode` on) nothing changed since the last run - check the status message, which always says which case it was.

**How is `discountVsFairValuePct` calculated?** `(fairValueUsd - priceUsd) / fairValueUsd × 100`, on ungraded (`raw`) listings only. Positive means the listing is priced below the estimate. Graded listings use `discountVsBasisPct` instead.

**Does `condition` always filter?** Only when the category offers that attribute - see the `condition` field description above for how matching works.

**Can I track more than one category?** Yes - list as many as you like in `categories`; each gets its own tracked history.

***

### Limitations

1. Whatnot does not expose **sold prices** or completed-sale history to a logged-out session - only active listings.
2. Follower lists, following lists, and a show's buyer list are login-only and always empty; they are not included in the output.
3. **Fair Value Analysis** covers Pokémon single cards only, mainly Scarlet & Violet and Mega Evolution sets, and only when the listing title clearly states the card name and collector number - sellers who write free-text titles without a number will not match. Graded listings are priced only for PSA 9 and PSA 10; listings graded by another company or at another grade get no fair value and are not charged.
4. Category "leaderboard" rankings are approximated from current live viewer counts, since a sales-based seller leaderboard is a login-only feature.
5. `condition` filtering depends on the category offering that attribute; not every category does.
6. Monitor mode and category-stats history live in a key-value store tied to this Actor's own runs under your account - duplicating the Actor or changing `trackingStoreName` starts a fresh history.
7. Seller reviews are reachable only up to about 128 per seller, a limit on Whatnot's own side - `includeSellerReviews` never returns more than that even for a seller with far more.
8. A run processes at most 60 start points (searches, URLs, sellers, and categories combined); extra ones are dropped, and the run's status message says by how many.
9. Monitor and category-stats state is scoped to one tracking store (`trackingStoreName`). Do not run overlapping schedules of the same input against the same store at the same time - concurrent runs reading and writing the same state can produce inconsistent deltas.

***

### Pricing

Pay-per-event. Only the Actor start fee ($0.00005) applies to a run that returns nothing.

| Event | Free | Starter | Scale | Business | Enterprise |
|---|---|---|---|---|---|
| Actor start | $0.00005 | $0.00005 | $0.00005 | $0.00005 | $0.00005 |
| Whatnot result (per row) | $0.0011 | $0.001 | $0.0009 | $0.0008 | $0.0008 |
| Add-on: Fair Value Analysis (per matched listing) | $0.07 | $0.06 | $0.05 | $0.04 | $0.04 |

A typical 30-result search run costs about $0.033 on Free.

A category start point always pushes 1 `category` row, plus up to `maxResultsPerCategory` `liveShow` rows, plus 1 `categorySnapshot` row when stats tracking is on. With the default `maxResultsPerCategory` of 30, a daily tracked-category schedule pushes 32 rows/day - about $0.035/day, or about $1.06/month on Free. Set `maxResultsPerCategory` to `0` to track only the category-level stats (2 rows/day - about $0.066/month on Free).

Monitor mode only charges for listings, live shows, and sellers that are new or changed, so a quiet day can cost nothing beyond the Actor start fee. Category, category snapshot, and review rows are returned and charged on every run.

***

### Output field reference

**`listing`**

| Field | Description |
|---|---|
| `id`, `listingId`, `url`, `title`, `subtitle`, `description` | Listing identity |
| `status`, `transactionType`, `listingFormat` | Whatnot status and whether it is an auction or buy it now |
| `priceUsd`, `currency`, `compareAtPriceUsd`, `quantity` | Pricing and quantity available |
| `currentBidUsd`, `currentBidCount` | Auction state |
| `isLive`, `liveShowUrl` | Whether it is being sold live right now, and where |
| `imageUrl`, `imageUrls` | Images |
| `categoryLabel`, `categoryId` | Category |
| `sellerUsername`, `sellerUrl`, `sellerRatingOverall`, `sellerReviewCount`, `sellerIsVerified`, `sellerIsPremierShop` | Seller |
| `createdAt`, `updatedAt` | Timestamps |
| `source`, `searchQuery` | How this row was found (search, sellerShop, or url), and the search term, when it came from one |
| `scrapedAt` | When this row was scraped, ISO 8601 |
| `fairValueUsd`, `fairValueBasis`, `discountVsFairValuePct` | Add-on: fair value estimate for an ungraded copy, the listing's grade basis, and the discount against the estimate (`raw` listings only) - `(fairValueUsd - priceUsd) / fairValueUsd × 100` |
| `rawPriceUsd`, `psa9PriceUsd`, `psa10PriceUsd`, `discountVsBasisPct` | Add-on: market price per grade and the discount against the one matching the listing's grade - `(basisPrice - priceUsd) / basisPrice × 100` |
| `gemRatePct`, `psa10Pop`, `totalPop`, `gemRateDate` | Add-on: grading population |
| `price1dChangePct`, `price7dVs30dChangePct` | Add-on: price momentum |
| `changeType`, `previousValue`, `changedFields` | Monitor mode only |

**`liveShow`**

| Field | Description |
|---|---|
| `id`, `url`, `title` | Show identity |
| `status`, `isLive`, `startTime`, `endTime` | Status and timing |
| `viewerCount`, `totalWatchlistUsers` | Audience |
| `categoryLabels`, `categoryIds`, `tags` | Classification |
| `thumbnailUrl`, `shippingSourceCountry` | Media and shipping |
| `sellerUsername`, `sellerUrl`, `sellerRatingOverall`, `sellerIsVerified`, `sellerIsPremierShop` | Host |
| `source`, `searchQuery` | How this row was found (search, seller, category, or url), and the search term, when it came from one |
| `scrapedAt` | When this row was scraped, ISO 8601 |
| `changeType`, `previousValue`, `changedFields` | Monitor mode only |

**`seller`**

| Field | Description |
|---|---|
| `username`, `url`, `displayName`, `bio` | Identity |
| `isSeller`, `isVerifiedSeller`, `canGoLive`, `isLive`, `vacationMode` | Status |
| `followerCount`, `followingCount`, `soldCount`, `averageShipDays`, `shippingSourceCountry` | Audience and fulfillment |
| `ratingOverall`, `ratingNumReviews`, `ratingShipping`, `ratingPackaging`, `ratingAccuracy` | Rating breakdown |
| `isPremierShop`, `profileImageUrl`, `storeImageUrl` | Shop |
| `shopListingCount`, `upcomingShowCount` | Shop listing and show counts (null unless `includeSellerShop` or `includeSellerShows` is on) |
| `reviewCount` | Total number of reviews the seller has |
| `source`, `searchQuery` | How this row was found (search, seller, or url), and the search term, when it came from one |
| `scrapedAt` | When this row was scraped, ISO 8601 |
| `changeType`, `previousValue`, `changedFields` | Monitor mode only |

**`review`**

| Field | Description |
|---|---|
| `sellerUsername`, `sellerUrl` | Which seller this review is for |
| `reviewId`, `averageRating`, `overallReview`, `sellerResponse`, `reviewedOn` | The review |
| `reviewedByUsername` | Reviewer |
| `ratingShipping`, `ratingPackaging`, `ratingAccuracy` | Sub-ratings |
| `scrapedAt` | When this row was scraped, ISO 8601 |

**`category`**

| Field | Description |
|---|---|
| `slug`, `label`, `categoryId` | Identity |
| `parentSlug`, `parentLabel`, `depth` | Tree position, when using `listCategoryTree` |
| `tagType`, `viewerCount`, `liveShowCount` | Current demand |
| `url`, `imageUrl` | Links |
| `scrapedAt` | When this row was scraped, ISO 8601 |

**`categorySnapshot`**

| Field | Description |
|---|---|
| `category`, `categoryLabel`, `categoryUrl` | Identity |
| `viewerCount`, `liveShowCount` | Current demand |
| `viewerDelta`, `viewerDeltaPct`, `liveShowDelta` | Change vs. the previous snapshot - `null` on the first run |
| `previousScrapedAt` | When that previous snapshot was taken |
| `top1SellerUsername` … `top3SellerUsername`, `topNShowTitle`, `topNShowUrl`, `topNShowViewers` | Top 3 live shows right now, by viewers |
| `topNRankChange` | Places moved up (+) or down (-) since the last snapshot; `null` if not previously in the top 3 |
| `scrapedAt` | When this row was scraped, ISO 8601 |

***

See also: [TCGplayer Listings Scraper](https://apify.com/phantom_coder/tcgplayer-listings-scraper) and [Cardmarket Listings Scraper](https://apify.com/phantom_coder/cardmarket-listings-scraper).

Questions or issues? Open a ticket in the **Issues** tab on the Actor page.

# Actor input Schema

## `searchQueries` (type: `array`):

Terms to search for on Whatnot, for example "pokemon cards". Each search adds its top results to the run.

## `searchType` (type: `string`):

What a search term should look for.

## `startUrls` (type: `array`):

Any Whatnot URL: a listing, a seller profile, a live show, a category/tag page, or a search results page. Each is routed automatically.

## `sellers` (type: `array`):

Usernames or profile URLs to scrape directly, without a search.

## `categories` (type: `array`):

Category slugs or URLs, for example "pokemon_cards" or https://www.whatnot.com/tag/pokemon_cards.

## `listCategoryTree` (type: `boolean`):

Returns the category tree as rows instead of listings or shows. Starts from the categories above, or the whole tree when none are given. Ignores every other start point and setting below.

## `categoryTreeDepth` (type: `integer`):

How many levels of subcategories to include when listing the category tree.

## `maxResultsPerQuery` (type: `integer`):

How many of the top results to return for each search term.

## `maxResultsPerSeller` (type: `integer`):

How many shop listings, shows, and reviews to return for each seller.

## `maxResultsPerCategory` (type: `integer`):

How many live shows to return for each category. Set to 0 to return only the category row itself (plus a category snapshot, when stats tracking is on) - the cheapest way to track just category-level demand.

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

Only return listings at or above this price in USD.

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

Only return listings at or below this price in USD.

## `listingFormat` (type: `string`):

Only return listings of this format.

## `condition` (type: `array`):

Only return listings in one of these conditions, for example "New", "Used", or "Near Mint". Applies only to product searches, and only when the category offers a condition attribute - otherwise it is ignored. Sellers enter this value as free text, so the exact options differ by category (trading cards and sneakers both offer dozens, e.g. "Near Mint", "Light Played", "Brand New"); matching against Whatnot's own current list is case-insensitive, so "new" also matches "New".

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

Applies to product searches (price options) and live-show searches (viewer options). Live shows from a category are always sorted by most viewers.

## `excludeSellers` (type: `array`):

Usernames to leave out of every result.

## `includeSellerShop` (type: `boolean`):

For each seller, also return their current shop listings.

## `includeSellerShows` (type: `boolean`):

For each seller, also return their live and scheduled shows.

## `includeSellerReviews` (type: `boolean`):

For each seller, also return their buyer reviews.

## `trackCategoryStats` (type: `boolean`):

For each category above, add a snapshot row with the current viewer count, live-show count, and top live shows, plus the change since the last run of this Actor. Schedule the Actor (for example daily) to build a trend.

## `monitorMode` (type: `boolean`):

Push (and charge for) only listings, shows, and sellers that are new or changed since the last run with this same input. Schedule the Actor to get an ongoing feed of changes instead of the full result every time.

## `trackingStoreName` (type: `string`):

Name of the key-value store used to remember state between runs, for both monitor mode and category stats. Use letters, digits, and hyphens. Change it to keep separate tracking histories for different schedules.

## `resetTracking` (type: `boolean`):

Clears the stored monitor and category-stats history before this run, as if it were the first run.

## `enableFairValue` (type: `boolean`):

Attach Fair Value Analysis data to covered Pokémon single-card listings. See below for details.

## Actor input object example

```json
{
  "searchQueries": [
    "pokemon cards"
  ],
  "searchType": "products",
  "listCategoryTree": false,
  "categoryTreeDepth": 2,
  "maxResultsPerQuery": 30,
  "maxResultsPerSeller": 30,
  "maxResultsPerCategory": 30,
  "listingFormat": "any",
  "sortBy": "bestMatch",
  "includeSellerShop": true,
  "includeSellerShows": true,
  "includeSellerReviews": false,
  "trackCategoryStats": false,
  "monitorMode": false,
  "trackingStoreName": "whatnot-tracking",
  "resetTracking": false,
  "enableFairValue": false
}
```

# Actor output Schema

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

All scraped rows

# 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 = {
    "searchQueries": [
        "pokemon cards"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("phantom_coder/whatnot-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 = { "searchQueries": ["pokemon cards"] }

# Run the Actor and wait for it to finish
run = client.actor("phantom_coder/whatnot-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 '{
  "searchQueries": [
    "pokemon cards"
  ]
}' |
apify call phantom_coder/whatnot-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,phantom_coder/whatnot-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/46EbYxNwL8sKR0zVJ/builds/cO6c3gaw93cfle48v/openapi.json
