# Pokémon Restock Monitor (Target + Best Buy, Discord alerts) (`integrative_cafe_8pc/pokemon-restock-monitor`) Actor

Get alerted when Pokémon cards, Elite Trainer Boxes and other collectibles come back in stock, drop in price or appear at Target and Best Buy. Watches searches and product lists, online and at your nearest Target store, and sends only what changed to Discord, Slack, Telegram or any webhook.

- **URL**: https://apify.com/integrative_cafe_8pc/pokemon-restock-monitor.md
- **Developed by:** [Bluefield Data](https://apify.com/integrative_cafe_8pc) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 change delivered (monitor)s

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Pokémon Restock Monitor (Target + Best Buy)

Schedule it every 10 minutes and get only what changed: **Pokémon cards, Elite Trainer Boxes, booster bundles and other collectibles that came back in stock, dropped in price or just appeared at Target and Best Buy**, sent straight to your Discord channel, Slack, Telegram or any webhook. Or run it once to see the stock of every retail-priced Pokémon item, online and at your nearest Target store.

### Why this one

- **It watches the items that actually sell out.** Store searches hide sold-out products and fill the first pages with marketplace resellers at 2 to 3 times retail. This Actor asks Target and Best Buy for items **they sell themselves, sold-out ones included**, so you watch the $49.99 Elite Trainer Box, not a $170 resale listing. In our test, "pokemon elite trainer box" returned 10 Target items (9 sold out) and 10 Best Buy items, all at retail price.
- **Search and watch at both stores with one list.** Type `pokemon elite trainer box` once and it runs at Target and Best Buy. Add product URLs or IDs for the exact items you want.
- **Online and in store.** For Target you get shipping availability plus pickup status and units on hand at the Target store nearest to your ZIP code. For Best Buy you get the state of the product page button (`ADD_TO_CART`, `SOLD_OUT`, `COMING_SOON`, `IN_STORE_ONLY`, `CHECK_STORES`, `PRE_ORDER`...).
- **Discord-ready alerts.** A Discord webhook URL gets one rich card per product (title, price, previous price, stock, nearest store, link). Slack and Telegram get readable text; any other URL gets clean JSON.
- **It gets through.** Data comes from the same services the Target and Best Buy websites call, through US residential sessions; a blocked request opens a new session on a new IP. In our tests: 7 of 7 real inputs (2 searches at both stores, 1 Target product, 2 Best Buy SKUs) returned 34 products with 0 errors, and the default input returns 48 products.
- **No missed alerts.** If your webhook is down, alerts stay queued and are resent on the next run. In our monitor test, a forced restock at Best Buy, a forced price drop at Target and a new product were reported, and nothing else.
- **Nothing is lost.** An input that fails (wrong URL, product that does not exist) comes back in the dataset with the reason, and you are not charged for it.

### Schedule it and get only restocks

1. Add searches (for example `pokemon elite trainer box`), Target product URLs and Best Buy SKUs, set your ZIP code and turn on **Monitor mode**.
2. Paste a **Webhook URL**: a Discord channel webhook (Channel settings > Integrations > Webhooks > New Webhook > Copy URL), a Slack incoming webhook, a Telegram `https://api.telegram.org/bot<token>/sendMessage?chat_id=<id>`, Zapier or Make.
3. In Apify Console, save the input as a Task and add a Schedule, for example every 10 minutes (`*/10 * * * *`).

The first monitor run returns the current snapshot of every product and remembers it. Every later run returns only the products that came back in stock, dropped in price, or are new in your searches. You can also report items that went out of stock and price increases, choose what counts as in stock (online, store or both), set a maximum price and ignore small price drops.

Example input for a Discord restock channel:

```json
{
  "searchTerms": ["pokemon elite trainer box", "pokemon booster bundle"],
  "retailers": ["target", "bestbuy"],
  "bestBuyProducts": ["6606082"],
  "zipCode": "90012",
  "maxPrice": 80,
  "monitorMode": true,
  "notifyOn": ["backInStock", "priceDrop", "newProduct"],
  "webhookUrl": "https://discord.com/api/webhooks/...",
  "monitorName": "my-discord-restocks"
}
```

Text alerts (Slack, Telegram) look like this:

```
BACK IN STOCK at Best Buy: Pokémon - Trading Card Game: Scarlet & Violet - Prismatic Evolutions Elite Trainer Box $49.99, online https://www.bestbuy.com/product/...
PRICE DROP at Target: Pokémon Trading Card Game: Mega Evolution Pitch Black Elite Trainer Box $59.99 (was $69.99), sold out https://www.target.com/p/.../-/A-1011483406
```

### Input

| Field | What it does |
|---|---|
| `searchTerms` | Searches, one per line; each runs at every selected retailer and lists up to `maxItemsPerSearch` products per retailer, sold-out ones included |
| `retailers` | Where searches run: `target`, `bestbuy` (default both) |
| `targetProducts` | Target product URLs (`/-/A-95230445`) or TCIN numbers |
| `bestBuyProducts` | Best Buy product URLs or SKU numbers |
| `soldByRetailerOnly` | Only items Target or Best Buy sell themselves, at retail price (default on) |
| `zipCode` | Optional US ZIP code; Target store stock is read at the nearest store (default 10001) |
| `maxPrice` | Optional; leave out products above this price (USD) |
| `maxItemsPerSearch` | Products per search per retailer (default 24) |
| `monitorMode` | Return only changes since the last run |
| `notifyOn` | `backInStock`, `priceDrop`, `newProduct`, `outOfStock`, `priceIncrease` |
| `stockScope` | What counts as in stock: online or store (default), online only, store only |
| `minPriceDropPercent` | Ignore smaller drops |
| `webhookUrl` | Discord, Slack, Telegram or any URL to POST the delivered products to |
| `monitorName` | Optional memory name; keep it to keep the memory when you edit the list |
| `proxy` | US residential by default; keep it |

### Output

```json
{
  "store": "target",
  "productId": "95230445",
  "title": "Pokémon Trading Card Game: Mega Evolution Perfect Order Elite Trainer Box",
  "price": 59.99,
  "regularPrice": 59.99,
  "currency": "USD",
  "soldBy": "Target",
  "isMarketplace": false,
  "inStock": false,
  "inStockOnline": false,
  "inStockAtStore": false,
  "onlineStatus": "OUT_OF_STOCK",
  "storePickupStatus": "UNAVAILABLE",
  "storeQuantity": 0,
  "storeName": "Chelsea 23rd and 8th",
  "storeId": "3412",
  "soldOutEverywhere": true,
  "url": "https://www.target.com/p/pok-233-mon-trading-card-game-mega-evolution-perfect-order-elite-trainer-box/-/A-95230445",
  "input": "pokemon elite trainer box",
  "scrapedAt": "2026-10-27T01:22:04+00:00",
  "changeType": "back_in_stock",
  "previousPrice": 59.99,
  "previousInStock": false
}
```

`changeType` (`new`, `back_in_stock`, `price_drop`, `out_of_stock`, `price_increase`), `previousPrice` and `previousInStock` appear in monitor mode. A product found by several inputs is returned once, under the first input.

### Good to know

- **Best Buy store stock**: Best Buy sells many Pokémon products as `IN_STORE_ONLY`; for those the Actor reports the button state, not units per store. A switch to `ADD_TO_CART` or `PRE_ORDER` is reported as back in stock.
- No login, no account and no personal data: only public product, price and stock information.

### Pricing

You pay per result: **$0.003 per product** in a normal run. In monitor mode, **$0.003 per check** (one scheduled run) plus **$0.003 per change delivered**, so a quiet day costs only the checks. Unchanged products, resent alerts and failures are free.

# Actor input Schema

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

Words you would type in the store's search box, one per line. Each search runs at every retailer selected below and lists up to 'Max products per search' per retailer, including items that are sold out right now (those are the ones that restock). Leave every product field empty to try the Actor with 'pokemon trading card game'.

## `retailers` (type: `array`):

Where the searches run. Product URLs and IDs below always go to their own retailer.

## `targetProducts` (type: `array`):

Target product URLs (https://www.target.com/p/.../-/A-95230445) or TCIN numbers (95230445), one per line.

## `bestBuyProducts` (type: `array`):

Best Buy product URLs (https://www.bestbuy.com/site/...6606082.p?skuId=6606082 or .../sku/6606082) or SKU numbers (6606082), one per line.

## `soldByRetailerOnly` (type: `boolean`):

Searches keep only items Target or Best Buy sell themselves, at retail price. Turn off to also list marketplace resellers (usually marked up and rarely out of stock).

## `zipCode` (type: `string`):

Optional US ZIP code. Target store stock and pickup are checked at the Target store nearest to it. Default 10001 (New York).

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

Optional. Products above this price are left out (and not charged). Empty or 0 means no limit.

## `maxItemsPerSearch` (type: `integer`):

Stop each search after this many products per retailer.

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

Remember every product's price and stock between runs and return only what changed. Schedule the Actor (for example every 10 minutes) and keep the same input. The first run returns the current snapshot of every product.

## `notifyOn` (type: `array`):

Which changes monitor mode returns and sends to the webhook.

## `stockScope` (type: `string`):

Which availability triggers a back-in-stock alert.

## `minPriceDropPercent` (type: `integer`):

Ignore price drops smaller than this percentage. 0 reports any drop.

## `webhookUrl` (type: `string`):

Optional. Delivered products are POSTed here in batches of 10. A Discord webhook (https://discord.com/api/webhooks/...) gets one rich embed per product with price, stock and link; Slack and Telegram bot sendMessage URLs (with chat_id) get readable text; any other URL gets JSON with 'text' and 'items'. In monitor mode, alerts the webhook refuses are resent on the next run.

## `monitorName` (type: `string`):

Optional memory name for this watch list. Leave empty and the input itself is the memory key. Use the same name to keep the memory when you edit the list, or a new name to start fresh.

## `proxy` (type: `object`):

US residential proxy by default. Best Buy blocks datacenter IPs; keep it for reliable runs.

## Actor input object example

```json
{
  "searchTerms": [
    "pokemon elite trainer box",
    "pokemon booster bundle"
  ],
  "retailers": [
    "target",
    "bestbuy"
  ],
  "targetProducts": [
    "https://www.target.com/p/-/A-95230445"
  ],
  "bestBuyProducts": [
    "6606082"
  ],
  "soldByRetailerOnly": true,
  "zipCode": "10001",
  "maxItemsPerSearch": 24,
  "monitorMode": false,
  "notifyOn": [
    "backInStock",
    "priceDrop",
    "newProduct"
  ],
  "stockScope": "any",
  "minPriceDropPercent": 0,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `results` (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 = {
    "searchTerms": [
        "pokemon elite trainer box",
        "pokemon booster bundle"
    ],
    "targetProducts": [
        "https://www.target.com/p/-/A-95230445"
    ],
    "bestBuyProducts": [
        "6606082"
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("integrative_cafe_8pc/pokemon-restock-monitor").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 = {
    "searchTerms": [
        "pokemon elite trainer box",
        "pokemon booster bundle",
    ],
    "targetProducts": ["https://www.target.com/p/-/A-95230445"],
    "bestBuyProducts": ["6606082"],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("integrative_cafe_8pc/pokemon-restock-monitor").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 '{
  "searchTerms": [
    "pokemon elite trainer box",
    "pokemon booster bundle"
  ],
  "targetProducts": [
    "https://www.target.com/p/-/A-95230445"
  ],
  "bestBuyProducts": [
    "6606082"
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call integrative_cafe_8pc/pokemon-restock-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,integrative_cafe_8pc/pokemon-restock-monitor"
        }
    }
}
```

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/6Zq2mtfkKU85MyPql/builds/LcgEiY1DhpjREd4aq/openapi.json
