# Competitor Pricing & Packaging Monitor (`gifted_wagon/competitor-pricing-monitor`) Actor

Monitor SaaS pricing pages and receive normalized plans, prices, billing units, packaging signals, screenshot evidence, and typed changes—not noisy page diffs.

- **URL**: https://apify.com/gifted\_wagon/competitor-pricing-monitor.md
- **Developed by:** [Michael Olmos](https://apify.com/gifted_wagon) (community)
- **Categories:** Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 pricing page analyzeds

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.

- **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

## Competitor Pricing & Packaging Monitor

Turn public SaaS pricing pages into **normalized competitive intelligence**—then detect the pricing and packaging changes that matter.

This Actor extracts plans, prices, currencies, billing periods, units, features, calls to action, free-plan and trial signals, annual discounts, seat-based pricing, and usage-based pricing. It stores a normalized per-URL baseline and compares every later successful run against that baseline. The result is a typed, evidence-backed change report instead of a noisy text diff.

### Why use it?

Generic website monitors tell you that a page changed. Raw pricing scrapers return whatever text happened to be visible. Neither reliably answers the questions a pricing, product-marketing, sales, or research team needs:

- Which plan was added or removed?
- Did the price change, and for which billing period or unit?
- Which features moved into or out of a package?
- Was a free plan, trial, enterprise tier, annual discount, seat model, or usage model introduced?
- What public evidence supports the finding?

Competitor Pricing & Packaging Monitor answers those questions in a stable schema that works in datasets, dashboards, webhooks, MCP clients, and scheduled workflows.

### Quick start

Run with no input for a safe built-in three-plan example. To monitor a real page:

```json
{
  "pages": [
    {
      "url": "https://www.notion.com/pricing",
      "competitor": "Notion",
      "label": "Notion pricing",
      "tags": ["productivity", "benchmark"]
    }
  ],
  "renderMode": "auto",
  "captureScreenshot": false,
  "stateStoreName": "my-saas-competitors"
}
```

The first successful run creates a baseline. Schedule the same input daily or weekly; future runs compare against the named store and return `unchanged` or `changed`.

### Better than a generic page diff

The comparison fingerprint is built from normalized plans, price semantics, feature lists, CTAs, and packaging signals. Navigation, footers, cookie banners, modals, chat widgets, scripts, and other common noise are removed before extraction. Copyright dates or rearranged whitespace do not create a pricing alert.

When a real change occurs, `change.details` contains typed evidence:

```json
{
  "status": "changed",
  "competitor": "Northstar Analytics",
  "change": {
    "material": true,
    "severity": "high",
    "summary": "1 price change; 1 feature added.",
    "details": [
      {
        "type": "price-changed",
        "plan": "Growth",
        "field": "prices",
        "before": "$49 per user / month",
        "after": "$69 per user / month",
        "evidence": "Growth For teams operating repeatable growth programs. $69 per user / month ..."
      }
    ]
  }
}
```

### What gets extracted

Each successful page record includes:

- named plans and descriptions
- numeric or custom prices
- normalized currency, billing period, price unit, and qualifier
- plan features and primary call to action
- free plan, enterprise plan, free trial, and annual-discount signals
- seat-based and usage-based pricing signals
- extraction confidence and warnings
- stable pricing fingerprint
- baseline, unchanged, or changed status
- typed before/after change details with evidence
- optional full-page screenshot key and normalized page evidence

### Fast HTTP checks with browser fallback

`renderMode: "auto"` uses an HTTP-first strategy to keep routine monitoring fast and inexpensive. It switches to browser rendering when extraction confidence is too low or screenshot evidence is requested.

- `auto` — HTTP first; use Chrome for low-confidence or screenshot requests.
- `http` — fastest and cheapest; best for server-rendered pages.
- `browser` — start with Chrome; best for JavaScript-heavy pricing widgets.

If browser rendering fails, the Actor can retain a useful HTTP result. If no useful pricing structure reaches `minConfidence`, it returns an uncharged `failed` record rather than a misleading paid result.

### Datasets and upstream integrations

Select an Apify dataset containing any of these URL fields:

- `url`
- `pricingUrl`
- `link`

Optional `competitor`, `label`, `tags`, `contentSelector`, and `ignoreSelectors` fields are accepted. Inline pages and dataset pages can be combined; duplicate URLs are checked once.

This makes the Actor suitable after a company-discovery scraper, CRM export, research dataset, or portfolio inventory.

### Scheduling and state

Set a task or schedule with a stable `stateStoreName`. The Actor stores one compact normalized snapshot per URL in that named key-value store. A separate name creates an independent baseline set.

Use `resetBaseline: true` after an intentional scope or parser change. The current result becomes the new baseline and is not reported as a competitor move.

### Evidence controls

- `includeEvidenceText: true` includes up to 20,000 characters of cleaned public-page text.
- `captureScreenshot: true` saves a full-page PNG in the run's default key-value store and returns its record key.
- Every normalized plan contains the public text used as its extraction evidence.
- Every material change includes before/after values and supporting evidence.

Screenshots require browser rendering and may increase run duration and platform compute.

### Pricing

You pay only for successful `pricing-page-analyzed` events. Failed, blocked, empty, or low-confidence pages are returned without that value charge.

| Apify tier | Price per analyzed page |
|---|---:|
| Free | $0.015 |
| Bronze | $0.014 |
| Silver | $0.012 |
| Gold | $0.010 |
| Platinum and Diamond | $0.009 |

There is also a `$0.002` Actor-start event that covers fixed browser-image startup and safety-validation cost. A 20-page scan costs `$0.302` on the Free tier before platform compute or proxy charges, with normalized extraction and change detection included.

### Privacy, rights, and network safety

- Limited permissions: read the selected dataset and public HTTP/HTTPS pages; write the output dataset, evidence store, and named baseline store.
- Localhost, private, loopback, link-local, and reserved network addresses are blocked, including redirects and browser subrequests.
- HTML is limited to 3 MB and screenshots to 8 MB per page.
- The Actor does not log into sites, bypass access controls, or accept cookies or credentials.
- It does not send page content to an external AI model.
- Use it only for public pages you are permitted to monitor, and respect applicable site terms, laws, and rate limits.

### Important limitations

Pricing pages can personalize content by geography, account, experiment, or cookies. Some prices appear only after clicking toggles, configuring a calculator, or signing in. Extraction can therefore miss interactive, personalized, geographic, or login-only pricing.

Confidence is a structural extraction signal—not a guarantee of factual completeness. Verify evidence before making consequential pricing, legal, financial, or sales decisions.

### Automate through the API

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/gifted_wagon~competitor-pricing-monitor/runs" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"pages":[{"url":"https://www.notion.com/pricing","competitor":"Notion"}],"stateStoreName":"my-saas-competitors"}'
```

The run response contains the default dataset and key-value-store IDs. You can also use Apify schedules, tasks, webhooks, API clients, Make, Zapier, n8n, or the hosted Apify MCP server.

### Support

If a public pricing page is not extracted correctly, open an issue from the Actor's **Issues** tab. Include the run ID, URL, rendering mode, confidence, and a redacted result. Do not post credentials, private URLs, or confidential pricing in a public issue.

# Actor input Schema

## `pages` (type: `array`):

Public pricing-page URLs. Optional labels, tags, a content selector, and noise selectors are supported. Leave empty to run the built-in sample.

## `datasetId` (type: `string`):

Optional Apify dataset containing url, pricingUrl, or link fields.

## `maxPages` (type: `integer`):

Maximum successfully or unsuccessfully attempted pages across both sources.

## `renderMode` (type: `string`):

Auto tries inexpensive HTTP extraction first, then browser rendering for low-confidence or screenshot requests.

## `captureScreenshot` (type: `boolean`):

Use browser rendering and save a full-page PNG in the run key-value store. This may increase run time and compute.

## `waitSecs` (type: `number`):

Additional wait after DOM ready for pricing widgets and billing toggles.

## `minConfidence` (type: `number`):

Pages below this confidence return an uncharged failed result instead of a misleading pricing record.

## `stateStoreName` (type: `string`):

Named key-value store that persists normalized baselines across scheduled runs. Use a different name for an independent monitor.

## `resetBaseline` (type: `boolean`):

Replace the saved baseline for each checked URL without treating the replacement as a change.

## `includeEvidenceText` (type: `boolean`):

Include up to 20,000 characters of cleaned page text in each result for audit and downstream analysis.

## Actor input object example

```json
{
  "pages": [
    {
      "url": "https://www.notion.com/pricing",
      "competitor": "Notion",
      "label": "Notion pricing",
      "tags": [
        "productivity",
        "benchmark"
      ]
    }
  ],
  "maxPages": 25,
  "renderMode": "auto",
  "captureScreenshot": false,
  "waitSecs": 1,
  "minConfidence": 0.55,
  "stateStoreName": "competitor-pricing-monitor-state",
  "resetBaseline": false,
  "includeEvidenceText": true
}
```

# Actor output Schema

## `dataset` (type: `string`):

Normalized plans, packaging signals, typed changes, evidence, and uncharged failure rows.

## `summary` (type: `string`):

Counts, source, state-store name, pricing mode, screenshots, and budget status.

# 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 = {
    "pages": [
        {
            "url": "https://www.notion.com/pricing",
            "competitor": "Notion",
            "label": "Notion pricing",
            "tags": [
                "productivity",
                "benchmark"
            ]
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("gifted_wagon/competitor-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 = { "pages": [{
            "url": "https://www.notion.com/pricing",
            "competitor": "Notion",
            "label": "Notion pricing",
            "tags": [
                "productivity",
                "benchmark",
            ],
        }] }

# Run the Actor and wait for it to finish
run = client.actor("gifted_wagon/competitor-pricing-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "pages": [
    {
      "url": "https://www.notion.com/pricing",
      "competitor": "Notion",
      "label": "Notion pricing",
      "tags": [
        "productivity",
        "benchmark"
      ]
    }
  ]
}' |
apify call gifted_wagon/competitor-pricing-monitor --silent --output-dataset

```

## MCP server setup

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

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ZvmHng45K8nf7rdkr/builds/yq66k9gayKAo89rl9/openapi.json
