# AI Tools Pricing Monitor — OpenAI, Claude, Notion AI | $3/1K (`bovi/ai-tools-pricing-monitor`) Actor

**Stateful SaaS pricing-page monitor.** Structured plan cards (name ↔ price ↔ period ↔ features), typed change events (`price_changed`, `plan_added`, `trial_changed`…) via KV diffing, plus a competitive battlecard. Keyword mode auto-discovers competitor pricing pages — no URL paste needed.

- **URL**: https://apify.com/bovi/ai-tools-pricing-monitor.md
- **Developed by:** [Vitalii Bondarev](https://apify.com/bovi) (community)
- **Categories:** Marketing, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.88 / 1,000 ai tools pricing monitor — openai, claude, notion ai | $3/1ks

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/actors/running/actors-in-store.md#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

## AI Tools Pricing Monitor — OpenAI, Claude, Notion AI | Change Alerts | $3/1K

Monitor AI tool pricing pages and get **structured plans**, **typed change alerts**, and a **decision-ready battlecard** — not a wall of page text.

Point it at pricing URLs, or just give it a **keyword** ("AI writing assistant") and it auto-discovers the top competitor pricing pages itself. These live pricing-page URLs were verified on 2026-07-15: `https://openai.com/pricing` for OpenAI/ChatGPT, `https://claude.com/pricing` for Anthropic/Claude, and `https://www.notion.com/pricing` for Notion.

### Why this monitor

Most pricing trackers regex the page text and dump it. You get junk plan names, prices with no plan attached, and "changes" that are just copy edits. Built for AI-tooling buyers, procurement functions, and competitive-intelligence teams, this actor extracts the actual **plan cards**:

```json
{
  "name": "Plus",
  "amount": 20,
  "currency": "USD",
  "period": "month",
  "per_seat": true,
  "is_free": false,
  "is_custom_price": false,
  "features": ["Access to advanced models", "Higher message limits", "Priority support"],
  "cta": "Upgrade"
}
```

…and diffs them statefully between runs, so you get **typed events**, each one answerable with an action:

| Event | Fires when |
|---|---|
| `price_changed` | a plan's price moved — with old, new, % and direction |
| `plan_added` / `plan_removed` | the plan lineup changed |
| `trial_changed` | free trial appeared, disappeared, or changed length |
| `annual_discount_changed` | annual-billing discount appeared or changed |
| `billing_period_changed` | a plan switched monthly ↔ annual billing |
| `features_changed` | a plan's feature list materially changed |
| `page_changed_unparsed` | page changed but nothing structured moved (honest signal, never silent) |

The first run on a URL bootstraps a baseline (no change events, no surprises). Every scheduled run after that emits **only what changed**.

### Keyword auto-discovery (no URL paste)

Set `keyword` to your category and the actor finds the top competitor pricing pages via search (Google SERP when your account has the `GOOGLE_SERP` proxy group, otherwise Bing/DuckDuckGo), filters out review sites and "best X software" listicles, verifies each candidate is a live pricing page, and monitors them.

You can mix modes: pin your must-watch competitors in `pricingPageUrls` and let discovery fill the remaining slots up to `maxCompetitors`.

### Battlecard

Each run can emit one competitive battlecard across all monitored pages:

- cheapest & priciest paid entry points, median entry price
- free-tier and trial matrix per competitor
- full plan matrix (name, price, period, per-seat)
- everything that changed this run, summarized
- positioning notes ("X has no trial and no free tier — friction opportunity")

Pipe it to Slack or your CRM via a webhook on the run, or schedule the actor weekly and read the battlecard as your Monday AI tooling pricing brief.

### Input

| Field | Type | Notes |
|---|---|---|
| `keyword` | string | AI software category for auto-discovery. Optional if URLs given. |
| `pricingPageUrls` | array | Public AI pricing page URLs. Optional if keyword given. |
| `maxCompetitors` | integer | Cap on pages per run (default 10, max 25). |
| `emitBattlecard` | boolean | One battlecard per run (default true). |
| `eventTypes` | array | Filter which change events to emit. Empty = all. |
| `kvStoreName` | string | Named KV store for state. Keep it stable across runs. |
| `forceBrowser` | boolean | Force managed-browser rendering (rarely needed — escalation is automatic). |
| `proxyConfiguration` | object | Apify Proxy; defaults to residential. |

### Output records

All records land in the default dataset with a `record_type` discriminator:

- `snapshot` — one per monitored page per run: plans, trial/discount signals, `parse_confidence`, `extraction_method`
- `change_event` — typed events as in the table above
- `battlecard` — one per run

Dataset views (Snapshots / Change events / Battlecard) are pre-configured in the Apify console.

### How it parses (and why it's reliable)

1. Fast static fetch with TLS impersonation; JS-shell pages **escalate automatically** to a managed Camoufox browser render.
2. Plan cards are found **structurally** — repeated sibling card patterns in the DOM, not class-name guessing, not page-text regex. JSON-LD offers enrich the result when present.
3. Junk grids (FAQ accordions, feature-comparison tables) are rejected by per-grid quality scoring.
4. Every snapshot carries `parse_confidence` and `extraction_method`, and a degraded parse **never** fabricates plan-removal events — you get an honest `page_changed_unparsed` instead.

### Pricing events

| Event | Charged |
|---|---|
| `pricing-snapshot` | per pricing page successfully extracted |
| `pricing-change-event` | per typed change event emitted |
| `battlecard-report` | per battlecard generated |

Failed pages are never charged. Baselines are charged as snapshots only — a first run never bills change events.

### Scheduling

Typical setup: a weekly (or daily) schedule with your competitor set, a stable `kvStoreName`, and a webhook or integration reading the dataset. The actor is stateless between runs except for the named KV store, so you can fork configurations per product line by changing `kvStoreName`.

### Legal

Only public pricing pages — no login, no paywall, no personal data. You own your runs and the extracted data. Monitoring public competitor pricing is standard competitive-intelligence practice; this actor reads nothing a regular visitor's browser wouldn't.

### More scrapers from our toolkit

Building a data pipeline? These actors pair well with this one — each runs on your own Apify account with the same pay-per-result pricing, no subscription:

- [Ambitionbox Reviews Scraper](https://apify.com/bovi/ambitionbox-reviews-scraper)
- [Indeed Employer Intelligence](https://apify.com/bovi/indeed-employer-intelligence)
- [Meta Ads Library Scraper](https://apify.com/bovi/meta-ads-library-scraper)

Chain any of them together from the **Integrations** tab (the *Run succeeded* trigger) to build a multi-step workflow — one actor's output feeds the next.

# Actor input Schema

## `keyword` (type: `string`):

Describe the SaaS category and the actor finds the top competitor pricing pages itself — no URL paste needed. Example: 'project management software' or 'email marketing platform'. Combine with explicit URLs below; discovery fills the remaining slots up to Max competitors.

## `pricingPageUrls` (type: `array`):

Public SaaS pricing page URLs to monitor, e.g. \['https://slack.com/pricing', 'https://www.notion.com/pricing']. Optional when a keyword is set.

## `maxCompetitors` (type: `integer`):

Cap on the number of pricing pages monitored in one run (explicit URLs + auto-discovered). Each successfully extracted page = one pricing-snapshot charge.

## `emitBattlecard` (type: `boolean`):

Aggregate all monitored pages into one decision-ready battlecard record: cheapest paid entry, price ranges, free-tier/trial matrix, plan matrix, and this run's changes. One battlecard-report charge per run.

## `eventTypes` (type: `array`):

Filter which typed change events are emitted (and charged). Leave empty for ALL. Valid: price\_changed, plan\_added, plan\_removed, trial\_changed, annual\_discount\_changed, billing\_period\_changed, features\_changed, page\_changed\_unparsed.

## `kvStoreName` (type: `string`):

Named Apify Key-Value store that persists per-URL pricing state between runs. Keep the same name across scheduled runs to enable change detection — the first run on a URL bootstraps a baseline and emits no change events.

## `forceBrowser` (type: `boolean`):

Skip the fast static fetch and render every page in a managed browser (Camoufox). Slower; use only if a target page returns empty plans via the default path. The actor normally escalates to the browser automatically when needed.

## `proxyConfiguration` (type: `object`):

Apify Proxy settings. Defaults to US residential proxies — pinning one country keeps geo-localized pricing pages stable between runs (a rotating exit country flips currencies and re-baselines your monitors).

## Actor input object example

```json
{
  "keyword": "project management software",
  "pricingPageUrls": [
    "https://openai.com/pricing",
    "https://claude.com/pricing",
    "https://www.notion.com/pricing"
  ],
  "maxCompetitors": 10,
  "emitBattlecard": true,
  "kvStoreName": "ai-tools-pricing-monitor-state-2",
  "forceBrowser": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

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

Dataset containing Saas Pricing Monitor records (record\_type, domain, url, plan\_count, plans, has\_free\_tier, has\_free\_trial, trial\_days, has\_annual\_discount, annual\_discount\_pct, has\_usage\_based, has\_enterprise, currency, parse\_confidence, extraction\_method, extracted\_at, event\_type, plan\_name).

# 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 = {
    "keyword": "project management software",
    "pricingPageUrls": [
        "https://openai.com/pricing",
        "https://claude.com/pricing",
        "https://www.notion.com/pricing"
    ],
    "maxCompetitors": 10,
    "kvStoreName": "ai-tools-pricing-monitor-state-2",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("bovi/ai-tools-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 = {
    "keyword": "project management software",
    "pricingPageUrls": [
        "https://openai.com/pricing",
        "https://claude.com/pricing",
        "https://www.notion.com/pricing",
    ],
    "maxCompetitors": 10,
    "kvStoreName": "ai-tools-pricing-monitor-state-2",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("bovi/ai-tools-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 '{
  "keyword": "project management software",
  "pricingPageUrls": [
    "https://openai.com/pricing",
    "https://claude.com/pricing",
    "https://www.notion.com/pricing"
  ],
  "maxCompetitors": 10,
  "kvStoreName": "ai-tools-pricing-monitor-state-2",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call bovi/ai-tools-pricing-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bovi/ai-tools-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/fnzOKLD6LX2rRU3Tv/builds/Q4XhjsNCjQUcEXFb4/openapi.json
