# Authorized Content Diff (`immemorial_sarinda/authorized-content-diff`) Actor

Compare two caller-supplied text or restricted HTML snapshots and receive a deterministic content-difference report. For authorized, nonpersonal, nonconfidential data only. No website fetching or monitoring.

- **URL**: https://apify.com/immemorial_sarinda/authorized-content-diff.md
- **Developed by:** [Picknotes](https://apify.com/immemorial_sarinda) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$100.00 / 1,000 completed reports

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

## Authorized Content Diff

Compare two snapshots you supply, using text-lines-v1 or restricted html-block-v1. This Actor does not fetch pages, monitor sites, execute HTML or JavaScript, repair markup, infer semantic meaning, or determine browser DOM/CSS visibility. Unsupported input is rejected without a partial report. This is a separate product from Business Snapshot.

### Try it

The synthetic demo input is {"useDemo":true}. Omit own-input fields in demo mode.

For your own snapshots, set useDemo=false and provide beforeText, afterText, optionsJson, and authorizedNonpersonalNonconfidentialData=true. optionsJson is a JSON string, for example {"profile":"text-lines-v1","ignore_ids":\[]}. HTML mode uses {"profile":"html-block-v1","ignore_ids":\[]} and accepts only the native restricted fragment grammar. Do not normalize strings. You can enter those fields directly. For local files, save the following optional Python 3 script as make_input.py. It reads exact UTF-8 bytes without newline translation and produces an envelope. It requires only the Python standard library.

```python
"""Create an own-input JSON envelope without changing supplied UTF-8 bytes."""
import argparse,json,sys
from pathlib import Path
p=argparse.ArgumentParser(description=__doc__)
p.add_argument('before');p.add_argument('after');p.add_argument('options')
p.add_argument('--authorized-nonpersonal-nonconfidential-data',action='store_true',required=True)
a=p.parse_args()
values=[Path(n).read_bytes().decode('utf-8') for n in (a.before,a.after,a.options)]
sys.stdout.write(json.dumps(dict(useDemo=False,authorizedNonpersonalNonconfidentialData=True,beforeText=values[0],afterText=values[1],optionsJson=values[2]),ensure_ascii=True,separators=(',',':'))+'\n')
```

Run:

python3 make_input.py before.txt after.txt options.json --authorized-nonpersonal-nonconfidential-data > INPUT.json

This flag is your confirmation that you may submit these nonpersonal, nonconfidential inputs. Apify stores INPUT before execution. Reports contain supplied text, IDs, spans and hashes. There is no anonymization, secret detection, acquisition-completeness, privacy, deletion, or rights guarantee. Review reports before sharing.

### Results and price

A successful delivery places one full item in the default dataset. Fetch the raw dataset items JSON and read reportJson for the canonical report. Each completed report costs USD 0.10, including platform usage and reports with findings. Check the Actor's displayed pricing before running. The receipt describes the expected completion event; it is not proof of configured billing, a charge or settlement. One POST is attempted; uncertain acceptance may be billed and must never be automatically retried. Exit 124 is ambiguous after append: inspect the original run and dataset before deciding what to do.

### Save the complete report

Export the default dataset as raw JSON, preserving all fields, and save it as dataset.json in a trusted local directory. Do not use CSV or a field-filtered export. The export should contain one item. Its reportJson string is the full report; no separate helper download is needed.

For an optional local copy, save this standard-library Python 3 script as save_report.py beside dataset.json, then run python3 save_report.py. It refuses to overwrite report.json. This is extraction with a report byte/hash check, not full contract validation, sender authentication, original-input reconstruction or billing verification. Only use an export you intentionally downloaded from your own run. Review the JSON as data; do not execute its contents.

```python
import hashlib, json
from pathlib import Path
raw = Path("dataset.json").read_bytes()
if len(raw) > 4_500_000:
    raise ValueError("Export exceeds supported size")
value = json.loads(raw)
if isinstance(value, list):
    if len(value) != 1:
        raise ValueError("Expected exactly one item")
    value = value[0]
report = value["reportJson"].encode("utf-8")
if len(report) != value["reportBytes"]:
    raise ValueError("Report size mismatch")
if hashlib.sha256(report).hexdigest() != value["reportSha256"]:
    raise ValueError("Report hash mismatch")
with Path("report.json").open("xb") as output:
    output.write(report)
```

### Limits

Each snapshot is bounded at 1 MiB; options at 524,288 bytes. The worker frame is at most 4,500,000 bytes, including a 12-byte header. Report size is at most min(4,194,304, 4,499,988 - beforeBytes - afterBytes - optionsBytes). Escaped singleton POST size is separately capped at 4,500,000 bytes; receipt at 2,048 bytes. Linux per-process address space remains 256 MiB, CPU soft/hard 30/31 seconds, outer wall 50 seconds and worker wall 10 seconds, all lower-only.

The Actor uses 512 MB platform memory with a lower 256 MiB per-process address-space ceiling. Parent and worker share the platform budget. Resource exhaustion can stop a run before a final status is written; inspect the original run and dataset before retrying any uncertain delivery. Only supported isolated Linux runtimes are accepted.

The report uses deterministic exact block/line matching, not semantic similarity or an optimal-edit guarantee. HTML mode is a restricted fragment grammar, not a browser parser. Dataset views are presentation metadata; use raw JSON for the complete report.

# Actor input Schema

## `afterText` (type: `string`):

Own mode only. Exact UTF-8 bytes; do not normalize. All three own strings and explicit consent are required in own mode.

## `authorizedNonpersonalNonconfidentialData` (type: `boolean`):

Required as true for own mode. Submit only authorized nonpersonal, nonconfidential snapshots.

## `beforeText` (type: `string`):

Own mode only. Exact UTF-8 bytes; do not normalize. All three own strings and explicit consent are required in own mode.

## `optionsJson` (type: `string`):

Own mode only. Exact UTF-8 bytes; do not normalize. All three own strings and explicit consent are required in own mode.

## `useDemo` (type: `boolean`):

Use the included synthetic snapshots; omit all own-input fields.

## Actor input object example

```json
{
  "authorizedNonpersonalNonconfidentialData": false,
  "useDemo": true
}
```

# Actor output Schema

## `results` (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 = {
    "useDemo": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("immemorial_sarinda/authorized-content-diff").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 = { "useDemo": True }

# Run the Actor and wait for it to finish
run = client.actor("immemorial_sarinda/authorized-content-diff").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 '{
  "useDemo": true
}' |
apify call immemorial_sarinda/authorized-content-diff --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,immemorial_sarinda/authorized-content-diff"
        }
    }
}
```

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/t1F89Xwv58Trppd4x/builds/icImMs0mbiB9SdAD8/openapi.json
