# SaaS Pricing Monitor (`vedder1980/saas-pricing-monitor`) Actor

Monitor SaaS pricing pages for plan, price, and billing changes with historical snapshots and structured diffs.

- **URL**: https://apify.com/vedder1980/saas-pricing-monitor.md
- **Developed by:** [Daniel Ferreira de Almeida](https://apify.com/vedder1980) (community)
- **Categories:** Automation
- **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 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.

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

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.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/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

## SaaS Pricing Monitor

Track SaaS pricing pages and generate a clean diff of what changed between runs.

### What it does
This Actor monitors one or more public pricing pages, extracts the observed plan data, and compares the current snapshot against the previous one stored in Apify Key-Value Store.

It is designed to answer questions like:
- Did the monthly price change?
- Was a new plan added or removed?
- Did the free tier or trial terms change?
- Did plan features or billing periods change?

### Premium features
- historical snapshots per URL
- structured plan extraction
- diff output with added, removed, and modified plans
- change status: `new`, `unchanged`, `changed`, `error`
- compact history window for audit trails
- optional raw HTML capture for debugging
- optional webhook alert delivery

### Best for
- SaaS competitor monitoring
- pricing intelligence
- vendor watchlists
- sales and procurement workflows
- market research and lead qualification

### Input
- `urls` — pricing pages to monitor
- `html` — optional single HTML fixture for offline validation
- `planCardSelector` — optional CSS selector for pricing cards
- `priceSelector` — optional selector for the price element inside each card
- `ctaSelector` — optional selector for the CTA element inside each card
- `featureSelector` — optional selector for feature items inside each card
- `includeHistory` — include history in the output
- `historyLimit` — maximum number of historical snapshots to keep
- `includeSnapshot` — include the current snapshot object in the output
- `includeRawHtml` — include the raw HTML in the output
- `maxTextChars` — cap the preview text length
- `timeoutSecs` — request timeout per page
- `webhookUrl` — optional webhook for change notifications
- `runLabel` — optional label for downstream tracking

### Example input
```json
{
  "urls": ["https://example.com/pricing"],
  "includeHistory": true,
  "historyLimit": 10,
  "includeSnapshot": true,
  "includeRawHtml": false,
  "maxTextChars": 4000,
  "timeoutSecs": 30
}
````

### Output

Each item includes:

- page metadata
- extracted plans
- content hash
- change status
- changed fields
- plan diff summary
- historical snapshots
- optional raw HTML and current snapshot

### Notes

The Actor is intentionally built for pricing pages, not generic crawling.
It favors deterministic extraction, low operational cost, and a stable output contract that can feed alerts, dashboards, and downstream analysis.

# Actor input Schema

## `urls` (type: `array`):

Public pricing pages to monitor.

## `html` (type: `string`):

Optional single HTML document for offline testing and local validation.

## `planCardSelector` (type: `string`):

Optional CSS selector for pricing cards.

## `priceSelector` (type: `string`):

Optional selector for the price element inside each plan card.

## `ctaSelector` (type: `string`):

Optional selector for the primary call-to-action inside each plan card.

## `featureSelector` (type: `string`):

Optional selector for feature items inside each plan card.

## `includeHistory` (type: `boolean`):

Include recent snapshot history in the output.

## `historyLimit` (type: `integer`):

Maximum number of historical snapshots retained per URL.

## `includeSnapshot` (type: `boolean`):

Include the full current snapshot object in the output.

## `includeRawHtml` (type: `boolean`):

Include the raw HTML response in the output.

## `maxTextChars` (type: `integer`):

Maximum number of characters stored in the text preview.

## `timeoutSecs` (type: `integer`):

Maximum time allowed per page request.

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

Optional webhook endpoint to receive change notifications.

## `runLabel` (type: `string`):

Optional label for grouping related runs.

## Actor input object example

```json
{
  "urls": [
    "https://example.com/pricing"
  ],
  "includeHistory": true,
  "historyLimit": 10,
  "includeSnapshot": false,
  "includeRawHtml": false,
  "maxTextChars": 4000,
  "timeoutSecs": 30
}
```

# 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 = {
    "urls": [
        "https://example.com/pricing"
    ],
    "includeHistory": true,
    "historyLimit": 10,
    "includeSnapshot": false,
    "includeRawHtml": false,
    "maxTextChars": 4000,
    "timeoutSecs": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("vedder1980/saas-pricing-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 = {
    "urls": ["https://example.com/pricing"],
    "includeHistory": True,
    "historyLimit": 10,
    "includeSnapshot": False,
    "includeRawHtml": False,
    "maxTextChars": 4000,
    "timeoutSecs": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("vedder1980/saas-pricing-monitor").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 '{
  "urls": [
    "https://example.com/pricing"
  ],
  "includeHistory": true,
  "historyLimit": 10,
  "includeSnapshot": false,
  "includeRawHtml": false,
  "maxTextChars": 4000,
  "timeoutSecs": 30
}' |
apify call vedder1980/saas-pricing-monitor --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "SaaS Pricing Monitor",
        "description": "Monitor SaaS pricing pages for plan, price, and billing changes with historical snapshots and structured diffs.",
        "version": "1.1",
        "x-build-id": "dmhJVSiz6eQAz18cF"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/vedder1980~saas-pricing-monitor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-vedder1980-saas-pricing-monitor",
                "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/vedder1980~saas-pricing-monitor/runs": {
            "post": {
                "operationId": "runs-sync-vedder1980-saas-pricing-monitor",
                "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/vedder1980~saas-pricing-monitor/run-sync": {
            "post": {
                "operationId": "run-sync-vedder1980-saas-pricing-monitor",
                "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": [
                    "urls"
                ],
                "properties": {
                    "urls": {
                        "title": "Pricing page URLs",
                        "minItems": 1,
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Public pricing pages to monitor.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "html": {
                        "title": "HTML fixture",
                        "type": "string",
                        "description": "Optional single HTML document for offline testing and local validation."
                    },
                    "planCardSelector": {
                        "title": "Plan card selector",
                        "type": "string",
                        "description": "Optional CSS selector for pricing cards."
                    },
                    "priceSelector": {
                        "title": "Price selector",
                        "type": "string",
                        "description": "Optional selector for the price element inside each plan card."
                    },
                    "ctaSelector": {
                        "title": "CTA selector",
                        "type": "string",
                        "description": "Optional selector for the primary call-to-action inside each plan card."
                    },
                    "featureSelector": {
                        "title": "Feature selector",
                        "type": "string",
                        "description": "Optional selector for feature items inside each plan card."
                    },
                    "includeHistory": {
                        "title": "Include history",
                        "type": "boolean",
                        "description": "Include recent snapshot history in the output.",
                        "default": true
                    },
                    "historyLimit": {
                        "title": "History limit",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Maximum number of historical snapshots retained per URL.",
                        "default": 10
                    },
                    "includeSnapshot": {
                        "title": "Include snapshot",
                        "type": "boolean",
                        "description": "Include the full current snapshot object in the output.",
                        "default": false
                    },
                    "includeRawHtml": {
                        "title": "Include raw HTML",
                        "type": "boolean",
                        "description": "Include the raw HTML response in the output.",
                        "default": false
                    },
                    "maxTextChars": {
                        "title": "Max text chars",
                        "minimum": 200,
                        "maximum": 50000,
                        "type": "integer",
                        "description": "Maximum number of characters stored in the text preview.",
                        "default": 4000
                    },
                    "timeoutSecs": {
                        "title": "Timeout seconds",
                        "minimum": 5,
                        "maximum": 120,
                        "type": "integer",
                        "description": "Maximum time allowed per page request.",
                        "default": 30
                    },
                    "webhookUrl": {
                        "title": "Webhook URL",
                        "type": "string",
                        "description": "Optional webhook endpoint to receive change notifications."
                    },
                    "runLabel": {
                        "title": "Run label",
                        "type": "string",
                        "description": "Optional label for grouping related runs."
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
