# SaaS Changelog & Status Page Watcher (`aibuildersuse/saas-changelog-status-watcher`) Actor

Watch vendor changelog and status pages and get structured diffs when new releases, incidents or maintenance windows appear. Keeps state between runs and can POST to Slack, Discord, Zapier, Make or n8n.

- **URL**: https://apify.com/aibuildersuse/saas-changelog-status-watcher.md
- **Developed by:** [AIBuildersUse](https://apify.com/aibuildersuse) (community)
- **Categories:** Developer tools, Automation, AI
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$5.00 / 1,000 page checkeds

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

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

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## SaaS Changelog & Status Page Watcher

**SaaS Changelog & Status Page Watcher** watches vendor changelog and status pages and tells you when something new appears: a release note, a feature announcement, an incident, or a maintenance window. Each run compares the page with the snapshot from the previous run and outputs a clean dataset of changes, with an optional webhook to Slack, Discord, Zapier, Make or n8n.

Built for competitive intel, SRE vendor watches, and product teams that need to know the same day a tool they rely on ships or breaks.

### What it does

- **Extracts structured events** from changelog and status pages (heading + date + summary).
- **Renders JavaScript pages automatically** (`auto` mode: fast HTTP first, Chromium only when needed).
- **Diffs against the previous run** using a named key-value store that survives between scheduled runs.
- **Outputs clear change types:** `event_added`, `event_removed`, `event_updated`, `page_text_changed`, plus baseline / no_change / error rows.
- **Sends one webhook** with all changes in a Slack- and Discord-compatible payload.

### Use cases

- Track competitor release notes (Vercel, Linear, Notion, Cursor, GitHub).
- Watch status pages for tools in your stack (Stripe, OpenAI, Anthropic, GitHub).
- Feed a Slack channel or newsletter with "what shipped / what broke today".
- Build a history of vendor reliability and product velocity.

### How to use

1. Add the changelog / status URLs. Optionally set `pageKind` to `changelog` or `status`, or a CSS selector.
2. Run once to save a **baseline** of detected events.
3. Schedule daily or hourly. Later runs output only the diffs (plus optional `no_change` rows).
4. Optional: add a **webhook URL**.

Keep the same **State store name** across runs.

### Input

| Field | Description |
| --- | --- |
| `urls` | Changelog / status pages. Each item can carry `selector`, `label`, `pageKind`. |
| `cssSelector` | Optional CSS selector for all pages without their own. |
| `pageKind` | `auto` (default), `changelog`, or `status`. |
| `renderMode` | `auto` / `http` / `browser`. |
| `includeUnchanged` | On by default: one `no_change` row per unchanged page. |
| `ignoreTextPatterns` | Regexes for noisy text to ignore. |
| `webhookUrl`, `webhookHeaders` | Where to POST changes. |
| `stateStoreName` | Snapshot store name (default `saas-changelog-status-state`). |
| `maxConcurrency` | Pages in parallel (1–10). |
| `proxyConfiguration` | Optional Apify Proxy. |

Example input:

```json
{
  "urls": [
    { "url": "https://vercel.com/changelog", "pageKind": "changelog" },
    { "url": "https://github.blog/changelog/", "pageKind": "changelog" },
    { "url": "https://status.stripe.com/", "pageKind": "status" }
  ],
  "renderMode": "auto",
  "webhookUrl": "https://hooks.slack.com/services/XXX/YYY/ZZZ"
}
```

### Output

Example of a new release:

```json
{
  "url": "https://vercel.com/changelog",
  "checkedAt": "2026-11-06T15:00:00Z",
  "previousCheckedAt": "2026-11-05T15:00:00Z",
  "fetchMethod": "http",
  "eventsDetected": 24,
  "changeType": "event_added",
  "eventTitle": "Fluid Compute now generally available",
  "eventDate": "Nov 5, 2026",
  "eventKind": "changelog",
  "summary": "New changelog: Fluid Compute now generally available"
}
```

#### Change types

| `changeType` | Meaning |
| --- | --- |
| `baseline` | First run: events saved. |
| `event_added` / `event_removed` / `event_updated` | An event appeared, disappeared, or its summary changed. |
| `page_text_changed` | Other page text changed. |
| `no_change` | Checked, nothing changed. |
| `events_not_found` | Previously had events; now none — snapshot kept to avoid false removals. |
| `selector_not_found` / `fetch_error` | Selector or load failure. |

### Pricing

Pay per event: **$0.005 per page checked**. Platform usage is separate. Schedule wisely and keep memory at 512 MB for best margin.

### Tips

- Prefer dedicated changelog / status URLs over marketing homepages.
- If a page is a heavy SPA, set `renderMode` to `browser` or add a CSS selector around the feed.
- Some status pages (e.g. behind Cloudflare) may need Apify Proxy; most changelogs work from datacenter IPs.
- For SaaS **pricing** pages specifically, use [Pricing Page Change Monitor](https://apify.com/aibuildersuse/pricing-page-change-monitor) instead — it extracts plan cards and price diffs.

# Actor input Schema

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

Vendor changelog or status pages to watch. Optional per-URL fields: selector, label, pageKind (changelog|status|auto).

## `cssSelector` (type: `string`):

Limit extraction to this CSS selector (e.g. main, #changelog). Per-URL selector overrides this.

## `pageKind` (type: `string`):

Hint for labeling extracted events. auto detects from page text.

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

auto uses HTTP first and falls back to a headless browser when the page looks empty or blocked. http never uses a browser. browser always renders with Chromium.

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

When on, unchanged pages get one no_change row so every run shows what was checked.

## `ignoreTextPatterns` (type: `array`):

Lines matching these regexes are ignored in text diffs (e.g. rotating dates, visitor counters).

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

POST one JSON payload with all detected changes. Works with Slack and Discord incoming webhooks; also includes a full changes array for Zapier/Make/n8n.

## `webhookHeaders` (type: `object`):

Extra HTTP headers to send with the webhook, for example an Authorization header.

## `webhookOnBaseline` (type: `boolean`):

By default the first run of a URL only saves a baseline and does not notify. Turn on to also send baseline rows to the webhook.

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

Named key-value store that keeps snapshots between runs. Letters, digits and hyphens only.

## `maxConcurrency` (type: `integer`):

How many pages to check at the same time. Keep it low (1-3) on small memory.

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

Optional. Most changelog/status pages load without a proxy.

## Actor input object example

```json
{
  "urls": [
    {
      "url": "https://vercel.com/changelog"
    },
    {
      "url": "https://github.blog/changelog/"
    },
    {
      "url": "https://status.stripe.com/"
    }
  ],
  "pageKind": "auto",
  "renderMode": "auto",
  "includeUnchanged": true,
  "ignoreTextPatterns": [
    "©\\s*\\d{4}",
    "\\d+\\s*(seconds?|minutes?)\\s+ago"
  ],
  "webhookHeaders": {},
  "webhookOnBaseline": false,
  "stateStoreName": "saas-changelog-status-state",
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `changes` (type: `string`):

No description

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

No description

# 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": [
        {
            "url": "https://vercel.com/changelog"
        },
        {
            "url": "https://github.blog/changelog/"
        },
        {
            "url": "https://status.stripe.com/"
        }
    ],
    "ignoreTextPatterns": [
        "©\\s*\\d{4}",
        "\\d+\\s*(seconds?|minutes?)\\s+ago"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("aibuildersuse/saas-changelog-status-watcher").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": [
        { "url": "https://vercel.com/changelog" },
        { "url": "https://github.blog/changelog/" },
        { "url": "https://status.stripe.com/" },
    ],
    "ignoreTextPatterns": [
        "©\\s*\\d{4}",
        "\\d+\\s*(seconds?|minutes?)\\s+ago",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("aibuildersuse/saas-changelog-status-watcher").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 '{
  "urls": [
    {
      "url": "https://vercel.com/changelog"
    },
    {
      "url": "https://github.blog/changelog/"
    },
    {
      "url": "https://status.stripe.com/"
    }
  ],
  "ignoreTextPatterns": [
    "©\\\\s*\\\\d{4}",
    "\\\\d+\\\\s*(seconds?|minutes?)\\\\s+ago"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call aibuildersuse/saas-changelog-status-watcher --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,aibuildersuse/saas-changelog-status-watcher"
        }
    }
}
```

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/y9DNkCeHKQkCGRTFY/builds/kqQhYgQykJEee2hRB/openapi.json
