# Policy Change Detector (`riad_h/policy-change-detector`) Actor

Monitor privacy policies, terms of service, and legal pages for meaningful changes.

- **URL**: https://apify.com/riad\_h/policy-change-detector.md
- **Developed by:** [Riad Hossain](https://apify.com/riad_h) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

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

## Policy Change Detector — Privacy & Terms Monitoring

> Monitor privacy policies, terms of service, and legal pages for meaningful changes. Extract policy text, detect policy type, compare versions, classify changes by category, and assess severity.

### The Problem

Legal pages change. When a company updates their Privacy Policy or Terms of Service, the changes can be significant — new data sharing, different retention periods, removed user rights. But detecting meaningful changes in legal pages is hard because:

- Raw HTML changes constantly (CSS, navigation, scripts)
- Generic change detectors just say "something changed"
- You need to know WHAT changed and HOW IMPORTANT it is

**This Actor tells you: "This policy changed, here are the changed sections, these changes may relate to data sharing and retention, review may be recommended."**

### What It Does

```
Policy URL
    ↓
Fetch HTML
    ↓
Extract policy text (remove scripts, styles, nav, footer, cookie banners)
    ↓
Detect policy type (privacy_policy, terms_of_service, etc.)
    ↓
Normalize text (collapse whitespace, normalize Unicode)
    ↓
Generate content hash (SHA-256)
    ↓
Compare with previous version (if provided)
    ↓
Detect added/removed/modified sections (difflib)
    ↓
Classify changes by category (13 policy categories)
    ↓
Assess severity (low/medium/high)
    ↓
Push structured results to Apify Dataset
```

### Two Operating Modes

#### Mode 1 — Analyze Current Policy

Fetch a policy page, extract text, detect type, generate hash.

```json
{
  "urls": ["https://example.com/privacy"],
  "compareWithPrevious": false
}
```

#### Mode 2 — Compare Policies

Compare previous content with the current version.

```json
{
  "urls": ["https://example.com/privacy"],
  "previousContent": "Previous policy text here...",
  "analyzeChanges": true
}
```

Or use oldUrl + newUrl for explicit comparison:

```json
{
  "oldUrl": "https://example.com/privacy-old",
  "newUrl": "https://example.com/privacy"
}
```

### Output Example

```json
{
  "url": "https://example.com/privacy",
  "success": true,
  "policyType": "privacy_policy",
  "title": "Privacy Policy",
  "contentHash": "abc123...",
  "changed": true,
  "changeSummary": "Potentially significant changes detected (2 changes). Review recommended.",
  "severity": "high",
  "changes": [
    {
      "category": "data_sharing",
      "changeType": "added",
      "severity": "high",
      "summary": "New Data Sharing language was added.",
      "oldText": null,
      "newText": "We may share information with advertising partners."
    },
    {
      "category": "data_retention",
      "changeType": "modified",
      "severity": "medium",
      "summary": "Data Retention section was modified.",
      "oldText": "We retain information for 30 days.",
      "newText": "We retain information for 12 months."
    }
  ],
  "checkedAt": "2026-09-02T00:00:00Z"
}
```

### Change Categories (13)

| Category | What It Detects |
|----------|----------------|
| `data_collection` | What data is collected |
| `data_sharing` | Sharing with third parties |
| `third_party_services` | Service providers, vendors |
| `analytics_tracking` | Analytics, tracking, pixels |
| `data_retention` | How long data is stored |
| `cookies` | Cookie policy, local storage |
| `user_rights` | Access, deletion, opt-out rights |
| `security` | Security measures, breach notification |
| `international_data_transfer` | Cross-border data transfers |
| `children_data` | Data about children/minors |
| `marketing` | Marketing, promotional emails |
| `legal_basis` | Legal basis for processing |
| `other` | Uncategorized changes |

### Severity Levels

| Level | Examples |
|-------|---------|
| **high** | New third-party data sharing, new sensitive data collection, user rights removed, international transfer changes |
| **medium** | Retention period changed, cookie policy changed, analytics section changed |
| **low** | Minor wording changes, formatting, typo corrections |

> The Actor does NOT claim legal violations. It uses language like "potentially significant" and "review recommended."

### Use Cases

- **Vendor monitoring** — Track vendor privacy policy changes
- **Compliance research** — Monitor regulatory compliance across policies
- **Privacy research** — Track data sharing and retention changes
- **Competitor monitoring** — Watch competitor policy changes

### Input

```json
{
  "urls": ["https://example.com/privacy", "https://example.com/terms"],
  "previousContent": "Previous policy text...",
  "detectPolicyType": true,
  "extractText": true,
  "compareWithPrevious": true,
  "analyzeChanges": true,
  "maxUrls": 100,
  "requestDelayMs": 500
}
```

### Pricing

**Pay-per-event: $0.05 per `policy-analysis` event**

Charged for each successfully analyzed URL.

### Limitations

- The Actor does not guarantee legal compliance
- The Actor does not claim legal violations
- AI analysis is optional and not required for basic functionality
- Structured-data interpretation may change over time
- The Actor detects changes; it does not determine whether a change was intentional

### License

MIT

# Actor input Schema

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

List of policy page URLs to analyze.

## `previousContent` (type: `string`):

Previous policy text to compare against. The Actor will fetch the current version and compare.

## `oldUrl` (type: `string`):

URL of the old version. Used with newUrl for explicit comparison.

## `newUrl` (type: `string`):

URL of the new version. Used with oldUrl.

## `detectPolicyType` (type: `boolean`):

Whether to auto-detect the policy type.

## `extractText` (type: `boolean`):

Whether to include extracted policy text in output.

## `compareWithPrevious` (type: `boolean`):

Whether to compare with previous content (if provided).

## `analyzeChanges` (type: `boolean`):

Whether to categorize and assess detected changes.

## `maxUrls` (type: `integer`):

Maximum URLs to process (1-500).

## `requestDelayMs` (type: `integer`):

Delay between HTTP requests.

## Actor input object example

```json
{
  "urls": [
    "https://example.com/privacy"
  ],
  "previousContent": "",
  "oldUrl": "",
  "newUrl": "",
  "detectPolicyType": true,
  "extractText": true,
  "compareWithPrevious": true,
  "analyzeChanges": true,
  "maxUrls": 100,
  "requestDelayMs": 500
}
```

# Actor output Schema

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

View all policy analysis results with changes, categories, and severity.

# 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": [
        "https://example.com/privacy"
    ],
    "detectPolicyType": true,
    "extractText": true,
    "compareWithPrevious": true,
    "analyzeChanges": true,
    "maxUrls": 100,
    "requestDelayMs": 500
};

// Run the Actor and wait for it to finish
const run = await client.actor("riad_h/policy-change-detector").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": ["https://example.com/privacy"],
    "detectPolicyType": True,
    "extractText": True,
    "compareWithPrevious": True,
    "analyzeChanges": True,
    "maxUrls": 100,
    "requestDelayMs": 500,
}

# Run the Actor and wait for it to finish
run = client.actor("riad_h/policy-change-detector").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": [
    "https://example.com/privacy"
  ],
  "detectPolicyType": true,
  "extractText": true,
  "compareWithPrevious": true,
  "analyzeChanges": true,
  "maxUrls": 100,
  "requestDelayMs": 500
}' |
apify call riad_h/policy-change-detector --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,riad_h/policy-change-detector"
        }
    }
}

```

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/awXECIrVNBEeCen5q/builds/dyFadzfjc0x4AoOp0/openapi.json
