# Cross-Crawler Social Preview Drift Guard (`firstrate/social-preview-drift-guard-api`) Actor

Detect when Facebook, X, LinkedIn, Slack, Discord, and normal crawlers receive inconsistent social-preview state. Returns deterministic PASS, RISK, FAIL, or INCONCLUSIVE verdicts for publishing agents, CI, and CMS workflows.

- **URL**: https://apify.com/firstrate/social-preview-drift-guard-api.md
- **Developed by:** [First Rate](https://apify.com/firstrate) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$5.00 / 1,000 url 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?

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

## Social Preview Drift Guard API

Check whether a public URL has a **consistent, usable social-preview state across crawler-style consumers** before it reaches a publishing workflow, CMS, CI pipeline, or automated agent.

Instead of only extracting Open Graph tags, Social Preview Drift Guard returns a deterministic decision for each URL:

- `PASS` — the tested crawler-facing state was observed and no material issue was detected
- `RISK` — the page was observed, but social-preview weaknesses or inconsistencies were found
- `FAIL` — the page was observed and a decisive broken or contradictory state was found
- `INCONCLUSIVE` — the Actor could not gather enough transport-level evidence to judge the URL

The normal starting price is **$0.005 per successfully observed URL**. `INCONCLUSIVE` measurements are not charged as `url-checked` events.

### What it checks

For each URL, the Actor can fetch the page using multiple crawler-style user agents and compare what each receives. The default profiles represent a normal crawler plus Facebook, X/Twitter, and LinkedIn; Slack and Discord profiles are also available.

Checks include:

- HTTP status and crawler-dependent status drift
- redirects and final URL consistency
- canonical URL consistency
- `og:title`, `og:image`, and `og:url`
- Twitter Card metadata
- crawler-conditioned metadata differences
- canonical / Open Graph URL conflicts
- missing or invalid social metadata
- preview-image reachability and image content type
- bounded public-network safety checks for URLs and redirects

The output is designed for both humans and machines. Every inspected URL produces one dataset item containing the verdict, risk score, issue codes, crawler-profile observations, image checks, and an explicit scope statement.

### Quick start

For one URL:

```json
{
  "url": "https://www.apify.com"
}
```

For a batch:

```json
{
  "urls": [
    "https://example.com/article-a",
    "https://example.com/article-b"
  ]
}
```

The Actor audits up to 100 URLs per run. The defaults are intended to work without additional configuration.

### Example result

```json
{
  "inputUrl": "https://example.com/article-a",
  "verdict": "RISK",
  "riskScore": 24,
  "measurementStatus": "observed",
  "issues": [
    {
      "code": "MISSING_OG_IMAGE",
      "severity": "risk",
      "message": "og:image is missing."
    }
  ],
  "profileCount": 4,
  "rulesetVersion": "0.1.0"
}
```

### Useful workflows

#### Publishing QA

Run the Actor before publishing or distributing a URL. A workflow can stop on `FAIL`, request review on `RISK`, continue on `PASS`, and retry or route `INCONCLUSIVE` separately.

#### CI and CMS automation

Use the machine-readable verdict and issue codes in CI, content pipelines, release checks, CMS publishing flows, or scheduled link-health jobs.

#### Agent and API workflows

The Actor uses bounded inputs, limited permissions, deterministic verdicts, and one result per URL, making it suitable for programmatic use from the Apify API and automated agents.

### Interpreting the verdict

A `PASS` means the **public HTTP responses and metadata returned to the selected crawler-style user agents were internally consistent under this test**. It is not a guarantee that a social platform will display a particular cached or final rendered card.

A `FAIL` is reserved for observed decisive problems such as HTTP errors, crawler-dependent status conflicts, material canonical/Open Graph drift, invalid preview-image state, or other fail-severity conditions.

An `INCONCLUSIVE` result is intentionally different from a failure. It means the Actor could not obtain enough evidence to make a trustworthy PASS/RISK/FAIL judgment. This prevents transport problems from being misreported as defects in the target page.

### Inputs

- `url` — one public HTTP(S) URL
- `urls` — additional URLs, up to 100 total per run
- `profiles` — crawler profiles to compare
- `checkImages` — probe discovered preview images
- `maxConcurrency` — parallel URL processing limit
- `requestTimeoutSecs` — per-request timeout
- `maxHtmlMb` — maximum HTML response size per crawler profile

### Output and pricing

One default-dataset item is produced for each inspected URL. The run summary also reports aggregate PASS/RISK/FAIL/INCONCLUSIVE counts.

The paid event is `url-checked` at **$0.005 per observed URL ($5 per 1,000 checks)**. An inconclusive measurement is returned for diagnostic transparency but is not charged as a successful `url-checked` event.

Platform caches, proprietary ranking logic, authenticated/private social data, and the exact final card rendered inside a social network are outside the Actor's scope.

# Actor input Schema

## `url` (type: `string`):

Public HTTP(S) URL to inspect. Use this for the quickest one-URL check.

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

Additional public HTTP(S) URLs to inspect. Maximum 100 per run.

## `profiles` (type: `array`):

Fetch each URL using these crawler user-agent profiles and compare the metadata each profile receives.

## `checkImages` (type: `boolean`):

Verify that discovered preview-image URLs respond successfully with an image content type.

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

Number of URLs processed in parallel.

## `requestTimeoutSecs` (type: `integer`):

Maximum time allowed for each request before it is treated as a timeout.

## `maxHtmlMb` (type: `number`):

Maximum HTML response size read per crawler profile.

## Actor input object example

```json
{
  "url": "https://www.apify.com",
  "urls": [],
  "profiles": [
    "default",
    "facebook",
    "x",
    "linkedin"
  ],
  "checkImages": true,
  "maxConcurrency": 4,
  "requestTimeoutSecs": 10,
  "maxHtmlMb": 2
}
```

# Actor output Schema

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

One machine-readable audit item per inspected URL, including verdict, risk score, issues, crawler-profile observations, and preview-image checks.

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

Aggregate PASS/RISK/FAIL/INCONCLUSIVE counts and diagnostic summary for the run.

# 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 = {
    "url": "https://www.apify.com"
};

// Run the Actor and wait for it to finish
const run = await client.actor("firstrate/social-preview-drift-guard-api").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 = { "url": "https://www.apify.com" }

# Run the Actor and wait for it to finish
run = client.actor("firstrate/social-preview-drift-guard-api").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 '{
  "url": "https://www.apify.com"
}' |
apify call firstrate/social-preview-drift-guard-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,firstrate/social-preview-drift-guard-api"
        }
    }
}

```

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/7EskFvYOwxznhKYhj/builds/fEpwkluL9TvkXH0tn/openapi.json
