# Product & Price Drop Tracker (`second_coming/price-drop-tracker`) Actor

Monitor product prices and get alerted when they drop below your target. Tracks price history, stock status, and sends webhook notifications on price drops.

- **URL**: https://apify.com/second\_coming/price-drop-tracker.md
- **Developed by:** [Richard P](https://apify.com/second_coming) (community)
- **Categories:** AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Product & Price Drop Tracker

Monitor product prices on any e-commerce website and get notified when prices drop below your target threshold.

### Features

- **Multi-product monitoring** — Track prices for multiple products in a single run
- **Automatic price detection** — Intelligent price extraction using common CSS selectors (.price, [data-price], [itemprop="price"], meta tags, and more)
- **Custom CSS selectors** — Specify a custom selector if auto-detection doesn't work
- **Price history tracking** — Persists prices between runs using Apify key-value store
- **Target price alerts** — Get notified only when the price drops to or below your target
- **Stock status detection** — Detects "In Stock", "Out of Stock", and add-to-cart availability
- **Webhook notifications** — POST price drop alerts to any HTTP endpoint
- **Smart output** — Configurable to report only price drops or all check results
- **Graceful shutdown** — Handles abort signals cleanly to save costs

### Input

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `products` | array of objects | ✓ | List of products to monitor |
| `notificationType` | string | | `"changes_only"` (default) or `"all_runs"` |
| `webhookUrl` | string | | URL for price drop webhook notifications |

#### Product Object

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `url` | string | ✓ | Full URL of the product page |
| `name` | string | ✓ | Friendly label for the product |
| `targetPrice` | number | ✓ | Alert when price drops to or below this amount |
| `selector` | string | | Custom CSS selector for the price element (optional) |

#### Example Input

```json
{
  "products": [
    {
      "url": "https://www.amazon.com/dp/B0ABCDEFGH",
      "name": "Sony WH-1000XM5 Headphones",
      "targetPrice": 299.99,
      "selector": ".a-price-whole"
    },
    {
      "url": "https://www.bestbuy.com/site/some-product",
      "name": "Some Electronics",
      "targetPrice": 150.00
    }
  ],
  "notificationType": "changes_only",
  "webhookUrl": "https://hooks.example.com/price-alert"
}
````

### Output / Dataset Fields

| Field | Description |
|-------|-------------|
| `timestamp` | ISO 8601 timestamp of the check |
| `name` | Product label |
| `url` | Product URL |
| `currentPrice` | Current price extracted (or null) |
| `previousPrice` | Price from the previous run (or null) |
| `targetPrice` | Target price threshold |
| `priceDropped` | Boolean — true if price dropped below target |
| `dropAmount` | Dollar amount of the drop |
| `dropPercent` | Percentage drop |
| `inStock` | Boolean — true/false/null (unknown) |
| `error` | Error message if the check failed |

A summary record with `_summary: true` is appended at the end of each run.

### Price Detection

The Actor uses a multi-strategy approach to extract prices:

1. **Custom selector** — If provided, this is tried first
2. **Common selectors** — `.price`, `[data-price]`, `[itemprop="price"]`, `meta[property="product:price:amount"]`, `.product-price`, `.sale-price`, `.current-price`, etc.
3. **Class/id heuristics** — Elements with "price" in their class or id
4. **Amazon-specific** — `.a-price-whole`, `.a-offscreen`
5. **Text fallback** — Scans text content for price-like patterns

#### Supported Price Formats

- `$1,234.56` — US/UK format with comma thousands separator
- `€1.234,56` — European format with dot thousands separator and comma decimal
- `£99.99` — Various currency symbols
- Plain numbers with 0-2 decimal places

### Notifications

#### Webhook Payload

When a price drop is detected, the Actor POSTs to the configured webhook URL:

```json
{
  "event": "price_dropped",
  "product": "Sony WH-1000XM5 Headphones",
  "url": "https://...",
  "currentPrice": 278.00,
  "previousPrice": 349.99,
  "targetPrice": 299.99,
  "dropAmount": 71.99,
  "dropPercent": 20.6,
  "checkedAt": "2026-07-04T12:00:00+00:00",
  "inStock": true
}
```

#### Notification Types

| Mode | Behavior |
|------|----------|
| `changes_only` | Only pushes price drops and first-time checks to the dataset |
| `all_runs` | Pushes every check result to the dataset |

### State Persistence

Price history is stored in a named key-value store (`price-drop-tracker-state`) keyed by `price-state-{md5(url+|+selector)}`. This means prices are tracked across runs — each run compares against the previous run's price.

### Use Cases

- **Deal hunting** — Get notified when products hit your desired price
- **Competitor price monitoring** — Track competitor pricing over time
- **Price drop alerts** — Set up recurring runs (e.g., every hour) and receive webhooks when prices drop
- **Inventory monitoring** — Track stock availability alongside pricing

### Local Development

```bash
## Install dependencies
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

## Run locally
APIFY_ACTOR_PYTHON_VENV_PATH=.venv apify run --purge

## Push to Apify cloud
apify push
```

### Pricing

This Actor uses pay-per-event pricing at $0.01 per run — one flat charge per execution regardless of how many products you check.

# Actor input Schema

## `products` (type: `array`):

List of products to monitor for price drops.

## `notificationType` (type: `string`):

When to push results to the dataset and send webhooks.

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

Optional URL to POST price drop alerts to.

## Actor input object example

```json
{
  "products": [
    {
      "url": "https://example.com/product-page",
      "name": "Example Product",
      "targetPrice": 49.99,
      "selector": ""
    }
  ],
  "notificationType": "changes_only"
}
```

# Actor output Schema

## `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 = {
    "products": [
        {
            "url": "https://example.com/product-page",
            "name": "Example Product",
            "targetPrice": 49.99,
            "selector": ""
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("second_coming/price-drop-tracker").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 = { "products": [{
            "url": "https://example.com/product-page",
            "name": "Example Product",
            "targetPrice": 49.99,
            "selector": "",
        }] }

# Run the Actor and wait for it to finish
run = client.actor("second_coming/price-drop-tracker").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 '{
  "products": [
    {
      "url": "https://example.com/product-page",
      "name": "Example Product",
      "targetPrice": 49.99,
      "selector": ""
    }
  ]
}' |
apify call second_coming/price-drop-tracker --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Product & Price Drop Tracker",
        "description": "Monitor product prices and get alerted when they drop below your target. Tracks price history, stock status, and sends webhook notifications on price drops.",
        "version": "0.0",
        "x-build-id": "w768nbYR5uXRhPwjU"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/second_coming~price-drop-tracker/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-second_coming-price-drop-tracker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/second_coming~price-drop-tracker/runs": {
            "post": {
                "operationId": "runs-sync-second_coming-price-drop-tracker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/second_coming~price-drop-tracker/run-sync": {
            "post": {
                "operationId": "run-sync-second_coming-price-drop-tracker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "products"
                ],
                "properties": {
                    "products": {
                        "title": "Products to Track",
                        "type": "array",
                        "description": "List of products to monitor for price drops.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "url": {
                                    "title": "Product URL",
                                    "type": "string",
                                    "description": "Full URL of the product page.",
                                    "editor": "textfield"
                                },
                                "name": {
                                    "title": "Product Name",
                                    "type": "string",
                                    "description": "Friendly label for the product.",
                                    "editor": "textfield"
                                },
                                "targetPrice": {
                                    "title": "Target Price",
                                    "type": "number",
                                    "description": "Alert when price drops to or below this amount.",
                                    "editor": "number"
                                },
                                "selector": {
                                    "title": "Custom CSS Selector",
                                    "type": "string",
                                    "description": "Optional custom CSS selector for the price element. Leave empty for auto-detection.",
                                    "editor": "textfield"
                                }
                            },
                            "required": [
                                "url",
                                "name",
                                "targetPrice"
                            ]
                        }
                    },
                    "notificationType": {
                        "title": "Notification Type",
                        "enum": [
                            "changes_only",
                            "all_runs"
                        ],
                        "type": "string",
                        "description": "When to push results to the dataset and send webhooks.",
                        "default": "changes_only"
                    },
                    "webhookUrl": {
                        "title": "Webhook URL",
                        "type": "string",
                        "description": "Optional URL to POST price drop alerts to."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
