# SaaS Pricing Monitor 💰 (competitor pricing page change alerts) (`tagadanar/saas-pricing-monitor`) Actor

Watch competitors' pricing pages and get alerted when a plan, price or feature list changes. Plans extracted as clean JSON, change digests to Slack, no browser or API key to set up. Schedule it daily and pay cents per page, only when something is captured. Platform usage included.

- **URL**: https://apify.com/tagadanar/saas-pricing-monitor.md
- **Developed by:** [Tagada Data](https://apify.com/tagadanar) (community)
- **Categories:** Automation, Developer tools, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $7.00 / 1,000 page snapshots

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

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

Know the day a competitor changes their pricing. Point this actor at any set of
pricing pages and it extracts each page's plans as structured data: plan name,
price, billing period, per-user or flat, feature bullets and the call to
action. Run it on a schedule and it alerts you only when something actually
changed: a price moved, a plan appeared or disappeared, a feature was added to
a tier. Competitive intel tools charge hundreds to thousands per month for
this; here you pay cents per page.

No browser to babysit, no API key, nothing to install on your site.

### Who uses this

- **Product marketing and competitive intel teams** keeping battlecards current
  without re-reading competitor sites every week.
- **Founders and product managers** watching how rivals reprice, repackage and
  gate features.
- **Sales teams** who want to hear about a competitor's price increase before
  their prospects do.
- **Analysts and journalists** tracking pricing moves across a market segment.

### What you get

A snapshot record per page (first run, or every run outside monitor mode):

| Field | Description |
| --- | --- |
| `company` | Company the page belongs to |
| `plans` | Extracted plan cards: `name`, `price`, `amount`, `currency`, `currencyCode` (ISO code like USD or EUR when the page states it, null for a bare `$`), `unit`, `perUser`, `features`, `cta` |
| `priceTokens` | Every normalized price found on the page |
| `parseStatus` | `plans` (structured extraction worked), `tokens` (prices found without card structure) or `unparseable` |
| `url`, `pageTitle`, `fetchedAt` | Where and when |

And in monitor mode, a change record per detected difference:

| Field | Description |
| --- | --- |
| `changeType` | `price-changed`, `plan-added`, `plan-removed`, `features-changed`, `prices-changed` or `content-changed` |
| `plan` | Which plan changed |
| `before` / `after` | The old and new price |
| `featuresAdded` / `featuresRemoved` | Feature bullets that changed |
| `summary` | One human-readable line, e.g. `Zapier: "Team" price $59/mo -> $69/mo` |

### Input examples

A one-off structured capture of three competitors:

```json
{
  "urls": [
    "https://zapier.com/pricing",
    "https://linear.app/pricing",
    "https://slack.com/pricing"
  ]
}
````

A daily watch that posts changes to Slack:

```json
{
  "urls": ["https://competitor.com/pricing"],
  "monitorMode": true,
  "webhookUrl": "https://hooks.slack.com/services/XXX/YYY/ZZZ"
}
```

### How monitor mode works

Turn on `monitorMode` and schedule the actor (daily is typical, as a Task so it
keeps its own memory). The first run stores a baseline snapshot of each page.
Every run after that compares against the stored state and returns, and charges
for, only what changed, posting a digest to your webhook if you set one. A page
that did not change costs you nothing beyond the run itself.

### How the extraction works

The actor reads the page over plain HTTP and looks for the pricing-card
structure nearly every SaaS pricing page uses: a row of plans, each with a
name, a price and a feature list. It understands US and European price formats,
monthly and annual periods, per-user pricing, and Free and "contact sales"
tiers. When a page does not expose that structure, it falls back to comparing
the set of prices found anywhere on the page, and as a last resort the page's
visible text, so a change is still caught even when structured extraction is
not possible.

### Pricing

Pay per event, no subscription. Users on higher Apify plans get automatic discounts.

| Event | Price | When |
|---|---|---|
| Run started | **$0.005** | Flat, once per run |
| Page snapshot | **$0.01** | Per pricing page captured and parsed this run |
| Change found | **$0.02** | Per detected change (price, plan added or removed, features) |
| Digest sent | **$0.03** | Monitor mode only, per Slack/webhook digest actually posted |

Watching 10 competitor pricing pages daily costs about $3 a month, platform usage included, and changes are only billed when something actually changed.

### FAQ

**Does it work on any pricing page?** It works best on standard SaaS pricing
pages, which is most of them. Pages that render entirely in the browser with no
prices in the HTML are marked `unparseable` and monitored by text comparison
instead of plan structure.

**Will I get noise from A/B tests and copy tweaks?** Plan and price diffs only
fire on actual plan or price differences. Feature-list alerts can be switched
off with `trackFeatures: false` if a competitor edits bullets often.

**Do I need an API key or a browser?** No. Nothing to set up.

**How many pages can I watch?** Up to 60 per run. Run several schedules if you
need more.

**What currencies are supported?** Prices in dollars, euros and pounds,
including European decimal formats like `19,90 €`.

***

Pricing page monitor, competitor price tracking, SaaS pricing intelligence,
price change alerts, competitor plan comparison, pricing page scraper, Crayon
alternative, Visualping alternative for pricing, competitive intelligence,
battlecard automation.

# Actor input Schema

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

The pricing pages to watch, one URL per line, e.g. <code>https://competitor.com/pricing</code>. Up to 60 pages per run.

## `trackFeatures` (type: `boolean`):

Also alert when a plan's feature bullets change, not only prices and plans. Turn off if feature copy edits are noise for you.

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

Remember each page's last state and return only what <b>changed</b> since the previous run. The first run records a baseline snapshot per page. Schedule this actor daily (as a Task, so it keeps its own memory) for a live pricing-change feed.

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

Optional. A Slack incoming-webhook URL (or any endpoint accepting a JSON <code>{"text": ...}</code> body) that receives a digest of detected changes. Pairs with monitor mode and a daily schedule.

## Actor input object example

```json
{
  "urls": [
    "https://zapier.com/pricing",
    "https://linear.app/pricing"
  ],
  "trackFeatures": true,
  "monitorMode": false
}
```

# Actor output Schema

## `records` (type: `string`):

One item per pricing snapshot or detected change in the default dataset.

# 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://zapier.com/pricing",
        "https://linear.app/pricing"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tagadanar/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://zapier.com/pricing",
        "https://linear.app/pricing",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("tagadanar/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://zapier.com/pricing",
    "https://linear.app/pricing"
  ]
}' |
apify call tagadanar/saas-pricing-monitor --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "SaaS Pricing Monitor 💰 (competitor pricing page change alerts)",
        "description": "Watch competitors' pricing pages and get alerted when a plan, price or feature list changes. Plans extracted as clean JSON, change digests to Slack, no browser or API key to set up. Schedule it daily and pay cents per page, only when something is captured. Platform usage included.",
        "version": "0.2",
        "x-build-id": "J2rIrWanaZZUtOzhI"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/tagadanar~saas-pricing-monitor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-tagadanar-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/tagadanar~saas-pricing-monitor/runs": {
            "post": {
                "operationId": "runs-sync-tagadanar-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/tagadanar~saas-pricing-monitor/run-sync": {
            "post": {
                "operationId": "run-sync-tagadanar-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,
                        "type": "array",
                        "description": "The pricing pages to watch, one URL per line, e.g. <code>https://competitor.com/pricing</code>. Up to 60 pages per run.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "trackFeatures": {
                        "title": "Track feature-list changes",
                        "type": "boolean",
                        "description": "Also alert when a plan's feature bullets change, not only prices and plans. Turn off if feature copy edits are noise for you.",
                        "default": true
                    },
                    "monitorMode": {
                        "title": "Monitor mode (changes only)",
                        "type": "boolean",
                        "description": "Remember each page's last state and return only what <b>changed</b> since the previous run. The first run records a baseline snapshot per page. Schedule this actor daily (as a Task, so it keeps its own memory) for a live pricing-change feed.",
                        "default": false
                    },
                    "webhookUrl": {
                        "title": "Slack / webhook URL",
                        "type": "string",
                        "description": "Optional. A Slack incoming-webhook URL (or any endpoint accepting a JSON <code>{\"text\": ...}</code> body) that receives a digest of detected changes. Pairs with monitor mode and a daily schedule."
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
