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

Monitor public SaaS pricing pages for deterministic plan and price candidate changes without browser automation.

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

## Pricing

$0.80 / 1,000 checked pricing pages

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/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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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 Page Monitor

Monitor public SaaS pricing pages for deterministic plan and price candidate changes without browser automation, logins, cookies, screenshots, or LLM calls.

### What it does

- Fetches public HTTPS pricing pages with strict byte and target limits.
- Extracts visible plan-like price candidates such as `$19/mo`, `€49/month`, `Custom pricing`, or `Contact sales`.
- Stores a normalized baseline snapshot per target and `baselineKey`.
- Compares each new run with the previous baseline.
- Outputs changed pages by default, or all pages when `includeUnchanged=true`.

### Good use cases

- SaaS founders tracking competitor pricing-page changes.
- Agencies monitoring client and competitor price pages.
- Product marketers watching plan packaging changes.
- RevOps and research teams collecting lightweight pricing evidence.

### Input

- `targets`: public HTTPS pricing page URLs or bare domains/paths, for example `example.com/pricing`.
- `maxTargets`: safety cap, maximum 25 targets in v1.
- `includeUnchanged`: include pages that have not changed since the previous baseline.
- `baselineKey`: namespace for schedules, clients, or competitor sets.
- `maxChars`: maximum HTML characters parsed by the deterministic extractor.
- `maxBytes`: maximum upstream bytes read per page before streaming is cancelled.
- `includeRawContext`: include short visible-text snippets around each price candidate.

Example input:

```json
{
  "targets": ["https://example.com/pricing"],
  "maxTargets": 10,
  "includeUnchanged": false,
  "baselineKey": "competitors-weekly",
  "maxChars": 60000,
  "maxBytes": 524288,
  "includeRawContext": true
}
```

### Output

Each dataset item represents one checked pricing page that changed, or one included unchanged page when `includeUnchanged` is enabled.

Important fields:

- `normalizedTarget`: normalized public HTTPS pricing page URL.
- `status`: `ok`, `partial`, or `error`.
- `changed`: whether the current pricing candidate snapshot differs from the previous baseline.
- `previousPriceCandidates`: plan/price candidates from the previous baseline.
- `currentPriceCandidates`: plan/price candidates from the current page.
- `changeTypes`: `status` and/or `price_candidates`.
- `snapshotHash`: stable SHA-256 hash used for future comparisons.
- `warnings`: non-fatal warning codes such as `no_price_candidates`, `non_html_content_type`, or `upstream_body_truncated`.

Example dataset item:

```json
{
  "normalizedTarget": "https://example.com/pricing",
  "checkedAt": "2026-07-06T01:25:31.000Z",
  "status": "ok",
  "changed": true,
  "previousPriceCandidates": [],
  "currentPriceCandidates": [
    { "planName": "Pro", "priceText": "$19/mo", "context": "Pro $19/mo For growing teams" }
  ],
  "changeTypes": ["status", "price_candidates"],
  "snapshotHash": "...",
  "warnings": []
}
```

### Pricing

This Actor uses Apify Pay Per Event with one custom event:

| Event | When it is charged | Candidate price |
| --- | --- | ---: |
| `checked-pricing-page` | Before each public pricing page is fetched and checked, including unchanged checks that may be omitted from output | `$0.0012` |

That equals **$1.20 per 1,000 checked pricing pages**. Pricing is page-based rather than dataset-item based because unchanged checks still consume runtime while `includeUnchanged=false` omits unchanged dataset rows.

The current price is conservative for the first live cost-smoke. Reprice only after 1/10/25 target Apify cloud runs prove platform cost share stays below the 20-25% target.

### Limitations

- Public HTTPS pricing pages only.
- No browser rendering, screenshots, login pages, cookies, or private-network fetching.
- No LLM normalization in v1; output is deterministic evidence, not canonical price intelligence.
- Static HTML only. JavaScript-rendered prices may be missed.
- Candidate extraction is heuristic and should be treated as monitoring evidence, not financial advice.
- Third-party product and company names belong to their owners. This Actor is unofficial and not affiliated with monitored sites.

### Recommended workflow

1. Run once with a stable `baselineKey` to create the first baseline.
2. Schedule repeat runs with the same `baselineKey`.
3. Keep `includeUnchanged=false` for compact change-only datasets.
4. Enable `includeUnchanged=true` when you need an audit trail of all checks.
5. Review `warnings` before treating a page as fully monitored.

# Actor input Schema

## `targets` (type: `array`):

Public HTTPS SaaS pricing page URLs or bare domains/paths to monitor, for example example.com/pricing.

## `maxTargets` (type: `integer`):

Maximum number of unique pricing pages processed in one run. Hard-capped at 25 for predictable v1 costs.

## `includeUnchanged` (type: `boolean`):

When false, only changed pricing pages are pushed to the dataset after the first baseline run.

## `baselineKey` (type: `string`):

Namespace for stored snapshots, e.g. production, competitor-set-a, weekly.

## `maxChars` (type: `integer`):

Maximum number of HTML characters passed into the deterministic pricing extractor per page.

## `maxBytes` (type: `integer`):

Maximum upstream response bytes read per pricing page before streaming is cancelled.

## `includeRawContext` (type: `boolean`):

Include short visible-text snippets around each price candidate. Disable for smaller datasets.

## Actor input object example

```json
{
  "targets": [
    "https://example.com/pricing"
  ],
  "maxTargets": 10,
  "includeUnchanged": false,
  "maxChars": 60000,
  "maxBytes": 524288,
  "includeRawContext": true
}
```

# Actor output Schema

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

Default dataset items. Each item contains the normalized pricing page URL, change status, previous/current price candidates, warnings, and snapshot hash.

# 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 = {
    "targets": [
        "https://example.com/pricing"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("enfex/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 = { "targets": ["https://example.com/pricing"] }

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

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/8JvncPz9Q8Z4nlopG/builds/XFKUx5qWkXfKe0ql8/openapi.json
