# SaaS Status Page Monitor (`junipr/saas-status-page-monitor`) Actor

Monitor public status pages, incidents, component states, and status-history changes.

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

## Pricing

from $6.50 / 1,000 target 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/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 Status Page Monitor

Compare public SaaS status page snapshots and turn component, incident, and overall service changes into structured dataset rows and a concise operations report.

### What It Monitors

- Overall service indicators and descriptions.
- Component additions, removals, and status changes.
- Incident openings, resolutions, removals, and update changes.
- Incident impact, start time, resolution time, and latest message when the source supplies them.

The parser accepts Statuspage summary JSON, generic JSON component or incident collections, structured status records, and HTML elements with explicit `data-component-*` attributes. It does not infer outages from arbitrary page prose.

### Input

Use `targets` for multiple comparisons, or provide the direct single-target fields at the top level.

| Field | Purpose |
| --- | --- |
| `targets` | Previous/current comparisons with IDs, titles, snapshots, records, and optional source URLs. |
| `sourceUrl` / `urls` | Public current-state URLs. Retrieval occurs only when `fetchUrls` is true and no current snapshot is supplied. |
| `previousSnapshot` / `currentSnapshot` | Statuspage JSON, supported generic JSON, or explicit component HTML. |
| `previousEntities` / `currentEntities` | Structured overall, component, or incident records. |
| `records` | Pre-paired records containing old and new values. |
| `includeUnchanged` | Include comparable entities whose supported fields did not change. |
| `includeReport` | Write results, summary, and Markdown report records. |
| `maxTargets` | Target cap, from 1 through 50. |
| `maxEntitiesPerTarget` | Entity cap per side, from 1 through 5,000. |
| `maxItems` | Dataset row cap. |
| `maxTextBytes` | Snapshot size cap, up to 1,000,000 bytes. |
| `fetchTimeoutMs` | HTTP timeout, from 1,000 through 30,000 milliseconds. |

```json
{
  "sourceId": "payments-status",
  "title": "Payments status",
  "previousEntities": [
    { "id": "api", "type": "component", "name": "API", "status": "operational" }
  ],
  "currentEntities": [
    { "id": "api", "type": "component", "name": "API", "status": "partial_outage" },
    { "id": "incident-42", "type": "incident", "name": "Elevated API errors", "status": "investigating", "impact": "minor" }
  ],
  "maxItems": 25,
  "includeReport": true
}
````

### Dataset Rows

Each row identifies one changed or diagnostic entity. Important fields include:

- `entityType`, `entityKey`, `serviceName`, `component`, and `incidentTitle`.
- `changeType`, `oldStatus`, `newStatus`, `oldMessage`, and `newMessage`.
- `impact`, `startedAt`, `resolvedAt`, `severity`, and `score`.
- `sourceId`, `sourceUrl`, `sourceType`, `checkedAt`, and `recommendation`.
- `diagnosticCode` and `sourceError` for blocked retrieval or unrecognized content.

Change types are `overall-status-changed`, `component-added`, `component-removed`, `component-status-changed`, `incident-opened`, `incident-resolved`, `incident-updated`, `incident-removed`, and `unchanged`.

### Stored Artifacts

- Dataset: one row per changed, unchanged, or diagnostic entity that passes the configured filters and caps.
- `SAAS_STATUS_PAGE_MONITOR_RESULTS.json`: emitted rows.
- `SAAS_STATUS_PAGE_MONITOR_SUMMARY.json`: target and change counts, diagnostics, and charge-limit status.
- `SAAS_STATUS_PAGE_MONITOR_REPORT.md`: readable incident and component digest.

When report charging is unavailable, the actor records why the report was skipped instead of writing an unpaid report.

### Usage Charges

The actor uses pay per event. Platform usage is included in these event prices.

| Event | Price | When charged |
| --- | ---: | --- |
| `actor-start` | $0.02000 | Once before paid work starts. |
| `target-checked` | $0.00650 | Before each target is processed. |
| `snapshot-compared` | $0.00650 | Before a successfully prepared snapshot pair is compared. |
| `change-detected` | $0.01300 | Before each changed entity row is emitted. |
| `digest-generated` | $0.05000 | Before JSON result and summary records are written. |
| `executive-report-generated` | $0.10000 | Before the Markdown report is written. |

If Apify reports that a charge was limited or only partly accepted, the actor stops before the corresponding paid output. Set `includeReport` to false when KVS report artifacts are not needed.

### Public Tasks

Five capped task inputs cover component state changes, new incidents, incident resolutions, overall health, and an operations digest. Each task compares actor-specific status records and limits output volume.

### Retrieval Safety

- Only `http` and `https` URLs are accepted.
- Credentials in URLs and redirects are rejected.
- Loopback, link-local, and private network destinations are blocked unless `allowPrivateUrls` is explicitly enabled for controlled testing.
- Response length, retained snapshot bytes, target count, entity count, and request duration are bounded.
- Fetch failures and empty parses produce explicit diagnostic rows. The actor does not invent component states or incidents.

### Limitations

- JavaScript-only pages must expose a JSON endpoint or provide a snapshot; the actor does not run a browser.
- HTML parsing requires explicit component data attributes. Free-form prose is not converted into status facts.
- Scheduling and baseline retention are managed by the caller. Pass the prior snapshot or records into each comparison.
- Private status pages and credentialed endpoints are not supported.

# Actor input Schema

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

Capped previous/current comparisons.

## `sourceId` (type: `string`):

Stable identifier for a direct single-target comparison.

## `title` (type: `string`):

Human-readable direct target name.

## `sourceUrl` (type: `string`):

Public current-state URL fetched only when enabled.

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

Public URLs converted into capped fetch targets.

## `previousSnapshot` (type: `string`):

Previous JSON, HTML, or text snapshot.

## `currentSnapshot` (type: `string`):

Current JSON, HTML, or text snapshot.

## `records` (type: `array`):

Records that already contain previous/current comparison fields.

## `fetchUrls` (type: `boolean`):

Fetch sourceUrl only when the current snapshot is omitted.

## `fetchTimeoutMs` (type: `integer`):

Per-request timeout in milliseconds.

## `allowPrivateUrls` (type: `boolean`):

Permit private or loopback hosts only for controlled testing.

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

Maximum comparisons in one run.

## `maxItems` (type: `integer`):

Maximum billable dataset rows emitted by one run.

## `maxEntitiesPerTarget` (type: `integer`):

Maximum records read from each side of one target.

## `maxTextBytes` (type: `integer`):

Maximum bytes retained for each snapshot.

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

Include records with no comparable changes.

## `includeReport` (type: `boolean`):

Write results, summary, and Markdown report artifacts.

## `dryRun` (type: `boolean`):

Validate input without paid output.

## `debug` (type: `boolean`):

Enable debug logging.

## `previousEntities` (type: `array`):

Previous components, incidents, or overall-state records.

## `currentEntities` (type: `array`):

Current components, incidents, or overall-state records.

## Actor input object example

```json
{
  "targets": [],
  "sourceId": "",
  "title": "",
  "sourceUrl": "",
  "urls": [],
  "previousSnapshot": "",
  "currentSnapshot": "",
  "records": [],
  "fetchUrls": false,
  "fetchTimeoutMs": 10000,
  "allowPrivateUrls": false,
  "maxTargets": 1,
  "maxItems": 100,
  "maxEntitiesPerTarget": 500,
  "maxTextBytes": 120000,
  "includeUnchanged": false,
  "includeReport": true,
  "dryRun": false,
  "debug": false,
  "previousEntities": [],
  "currentEntities": []
}
```

# Actor output Schema

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

Compare Statuspage-style components, incidents, and overall service state.

## `artifact1` (type: `string`):

SAAS\_STATUS\_PAGE\_MONITOR\_RESULTS.json

## `artifact2` (type: `string`):

SAAS\_STATUS\_PAGE\_MONITOR\_SUMMARY.json

## `artifact3` (type: `string`):

SAAS\_STATUS\_PAGE\_MONITOR\_REPORT.md

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("junipr/saas-status-page-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("junipr/saas-status-page-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 '{}' |
apify call junipr/saas-status-page-monitor --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "SaaS Status Page Monitor",
        "description": "Monitor public status pages, incidents, component states, and status-history changes.",
        "version": "1.0",
        "x-build-id": "Y82Of8cSj9OuuwdnA"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/junipr~saas-status-page-monitor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-junipr-saas-status-page-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/junipr~saas-status-page-monitor/runs": {
            "post": {
                "operationId": "runs-sync-junipr-saas-status-page-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/junipr~saas-status-page-monitor/run-sync": {
            "post": {
                "operationId": "run-sync-junipr-saas-status-page-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",
                "properties": {
                    "targets": {
                        "title": "Status entities targets",
                        "type": "array",
                        "description": "Capped previous/current comparisons.",
                        "items": {
                            "type": "object"
                        },
                        "default": []
                    },
                    "sourceId": {
                        "title": "Source ID",
                        "type": "string",
                        "description": "Stable identifier for a direct single-target comparison.",
                        "default": ""
                    },
                    "title": {
                        "title": "Target title",
                        "type": "string",
                        "description": "Human-readable direct target name.",
                        "default": ""
                    },
                    "sourceUrl": {
                        "title": "Current source URL",
                        "type": "string",
                        "description": "Public current-state URL fetched only when enabled.",
                        "default": ""
                    },
                    "urls": {
                        "title": "Current source URLs",
                        "type": "array",
                        "description": "Public URLs converted into capped fetch targets.",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "previousSnapshot": {
                        "title": "Previous snapshot",
                        "type": "string",
                        "description": "Previous JSON, HTML, or text snapshot.",
                        "default": ""
                    },
                    "currentSnapshot": {
                        "title": "Current snapshot",
                        "type": "string",
                        "description": "Current JSON, HTML, or text snapshot.",
                        "default": ""
                    },
                    "records": {
                        "title": "Structured change records",
                        "type": "array",
                        "description": "Records that already contain previous/current comparison fields.",
                        "items": {
                            "type": "object"
                        },
                        "default": []
                    },
                    "fetchUrls": {
                        "title": "Fetch current URLs",
                        "type": "boolean",
                        "description": "Fetch sourceUrl only when the current snapshot is omitted.",
                        "default": false
                    },
                    "fetchTimeoutMs": {
                        "title": "Fetch timeout",
                        "minimum": 1000,
                        "maximum": 30000,
                        "type": "integer",
                        "description": "Per-request timeout in milliseconds.",
                        "default": 10000
                    },
                    "allowPrivateUrls": {
                        "title": "Allow private URLs",
                        "type": "boolean",
                        "description": "Permit private or loopback hosts only for controlled testing.",
                        "default": false
                    },
                    "maxTargets": {
                        "title": "Max targets",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Maximum comparisons in one run.",
                        "default": 1
                    },
                    "maxItems": {
                        "title": "Max output rows",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Maximum billable dataset rows emitted by one run.",
                        "default": 100
                    },
                    "maxEntitiesPerTarget": {
                        "title": "Max status entities",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Maximum records read from each side of one target.",
                        "default": 500
                    },
                    "maxTextBytes": {
                        "title": "Max snapshot bytes",
                        "minimum": 1000,
                        "maximum": 2000000,
                        "type": "integer",
                        "description": "Maximum bytes retained for each snapshot.",
                        "default": 120000
                    },
                    "includeUnchanged": {
                        "title": "Include unchanged rows",
                        "type": "boolean",
                        "description": "Include records with no comparable changes.",
                        "default": false
                    },
                    "includeReport": {
                        "title": "Include report artifacts",
                        "type": "boolean",
                        "description": "Write results, summary, and Markdown report artifacts.",
                        "default": true
                    },
                    "dryRun": {
                        "title": "Dry run",
                        "type": "boolean",
                        "description": "Validate input without paid output.",
                        "default": false
                    },
                    "debug": {
                        "title": "Debug logs",
                        "type": "boolean",
                        "description": "Enable debug logging.",
                        "default": false
                    },
                    "previousEntities": {
                        "title": "Previous status entities",
                        "type": "array",
                        "description": "Previous components, incidents, or overall-state records.",
                        "items": {
                            "type": "object"
                        },
                        "default": []
                    },
                    "currentEntities": {
                        "title": "Current status entities",
                        "type": "array",
                        "description": "Current components, incidents, or overall-state records.",
                        "items": {
                            "type": "object"
                        },
                        "default": []
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
