# SiteVerdict — Social Link Preview Checker (`siteverdict/siteverdict-social-preview-checker`) Actor

See how your links look on Facebook, LinkedIn, X, WhatsApp and Slack before you post. Checks Open Graph, Twitter Cards and oEmbed, measures the image (size, ratio, weight), renders preview mockups and gives paste-ready meta tags.

- **URL**: https://apify.com/siteverdict/siteverdict-social-preview-checker.md
- **Developed by:** [Aman Thakran](https://apify.com/siteverdict) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

## SiteVerdict — Social Link Preview Checker

**See how your link is likely to look on Facebook, LinkedIn, X, WhatsApp and Slack before you post it, and get the tags that fix it.**

Common problems are a missing image, a cropped logo, a title cut off mid-word, or a WhatsApp preview with no thumbnail. Each one costs clicks on every share. Paste your URLs to get, for each page:

- one preview mockup per platform;
- a 0–100 score and a status per platform (ok, degraded or broken);
- every problem, with its fix and paste-ready meta tags.

### How to use it

1. Add one or more page URLs under **URLs**.
2. Set **Max cost per run** in the run options (each analysed URL costs $0.004).
3. Click **Start**. Open the **Output** tab for scores and fixes, or the `REPORT` record for all mockups on one page.

**The example input** (the same input the console pre-fills) costs **$0.004** and took about 4 seconds on 15 Oct 2026:

```json
{ "urls": [{ "url": "https://www.python.org/" }] }
```

Not sure yet? Set **Mode = Sample** to see the full output for two built-in demo pages, free.

### Who it is for

- **Content and social teams.** Check a blog post or landing page before a campaign goes out.
- **SEO and web agencies.** Bulk-check every template (home, product, article, category) after a redesign or plugin update.
- **E-commerce.** Find product pages whose images are too small, too heavy or the wrong ratio for social shares.

### What it checks

| Area | Checks |
|---|---|
| Open Graph | og:title, og:description, og:image (absolute, https), og:url vs canonical, og:type, og:site_name, og:image:width/height/alt, duplicate tags |
| X (Twitter) Cards | twitter:card present and valid (summary_large_image), title/description/image fallbacks, 300×157 minimum, 4096×4096 maximum |
| Image | Loads (status, content type), real pixel size from the file header (PNG/JPEG/GIF/WebP/AVIF/SVG), 1.91:1 ratio, 1200×630 recommended, 200×200 Facebook minimum, 5 MB (X/LinkedIn) and 8 MB (Facebook) limits, WhatsApp weight (~300–600 KB), unsupported SVG/AVIF |
| Text | Title and description length against each platform's cut-off |
| oEmbed | The page's oEmbed endpoint loads and returns valid JSON (type, version) |

### What you get

- **Dataset:** one row per URL. Views: Overview (score and per-platform status), Issues and fixes, and Preview data.
- **Preview mockups:** one `PREVIEW-…` HTML page per URL, linked from the `previewUrl` field of its row. It shows Facebook-, LinkedIn-, X-, WhatsApp- and Slack-style cards drawn with our own templates.
- **REPORT:** all URLs on one page.
- **REPORT_CSV:** one line per issue.
- **SUMMARY:** compact JSON for agents.

Example issue:

```json
{ "code": "og-image-relative", "severity": "error", "platforms": ["facebook", "linkedin", "x", "whatsapp"],
  "message": "og:image is a relative URL (/media/catalog/blue-shoe-thumb.webp); several platforms require an absolute URL.",
  "fix": "Use the full URL: https://shop.example-broken.com/media/catalog/blue-shoe-thumb.webp" }
```

Run with **Mode = Sample** to see the full output for two demo pages, free.

### Monitoring

Schedule the Actor with **Output = Only changed URLs**. A page is then reported only when its tags or image changed since the last run, for example when a theme or SEO-plugin update removes og:image from every product page. Every page is still fetched and analysed, so each one is still charged `url-checked`, even when nothing changed and no row is written.

To compare runs, the Actor keeps a small record per URL (a hash of its tags and the time of the check) in the named key-value store `siteverdict-social-preview-checker` in **your** Apify account (set by **State store name**). It stays there until you delete it.

### Optional: AI copy suggestions (your own key)

For pages scoring under 90, your Anthropic or OpenAI key generates:

- a better og:title (40–60 characters);
- an og:description (110–155 characters);
- image alt text;
- a brief for a 1200×630 image.

The suggestions use only the page's own data: its URL, title, description, site name and the problems found are sent to the AI provider you chose, under your own account with that provider. The key is a secret input (stored encrypted by Apify) and is masked in logs and output. They are AI-generated and kept in a separate `aiSuggestions` field; review them before you publish.

### Pricing

| Event | Price | When |
|---|---|---|
| `url-checked` | $0.004 | Each page that returned HTML and was analysed (including unchanged pages in "Only changed URLs" mode) |
| `ai-fix` | $0.02 | Each AI copy suggestion delivered (your own AI key pays the AI provider) |

100 pages cost about $0.40. Fetch errors, robots.txt blocks, non-HTML responses, failed AI calls and sample mode are free. You pay only these event prices; Apify platform usage for the run is included. The run stops cleanly at your **Max cost per run**.

### FAQ

**Is this a screenshot from Facebook or X?** No. We never call or scrape those platforms. The mockups come from our own templates that follow each platform's documented card layout, so real previews can differ slightly. Platforms also cache old previews. After fixing, use their own debuggers (Facebook Sharing Debugger, LinkedIn Post Inspector) to refresh the cache.

**Does it run JavaScript?** No. Social crawlers read the raw HTML too, so tags added only by JavaScript are invisible to them, and this Actor shows you that.

**Why is my WhatsApp preview missing?** Usually the image is too heavy. WhatsApp often drops thumbnails over about 600 KB, so aim for under 300 KB. This is observed behaviour, not a published limit.

### Limits

- Up to 500 URLs per run. Requests to one host are sequential, at most one per second.
- Pages behind logins or bot protection fail and are not charged.
- Platform limits change. The values used are listed below and were checked on 2026-10-11.

### Sources & compliance

- **Data source:** the public HTML, image and oEmbed responses of the URLs you submit. No social platform is contacted or scraped.
- **Platform guidance** (checked 2026-10-11):
  - Facebook sharing best practices, https://developers.facebook.com/docs/sharing/webmasters/images/ (1200×630, 200×200 minimum, 8 MB).
  - X Cards, https://developer.x.com/en/docs/x-for-websites/cards/overview/summary-card-with-large-image (300×157 minimum, 4096×4096, 5 MB, JPG/PNG/WEBP/GIF).
  - LinkedIn, https://www.linkedin.com/help/linkedin/answer/a521928 (1200×627).
  - The Open Graph protocol, https://ogp.me/.
  - oEmbed, https://oembed.com/.
  - The WhatsApp size guidance is observed behaviour, not a published limit.
- **Polite fetching:** honest User-Agent `SiteVerdict/social-preview-checker (+https://apify.com/siteverdict/siteverdict-social-preview-checker)`. robots.txt is respected for pages, images and oEmbed endpoints. An image we may not fetch is reported as "not verified". No bot-protection bypass.
- **Security:** SSRF guard on every request and redirect, size caps and timeouts. The mockups HTML-escape all page content.
- **Personal data (UK GDPR / EU GDPR):** the Actor looks only for preview tags, images and oEmbed data. If a page you submit carries personal data in those fields (for example a person's name in a profile-page title), it is repeated in your results. **You are the controller** of the URLs you submit and of the results, and you should check only pages you own or have a lawful reason to check. This is not legal advice.
- **Independent tool:** platform names only describe compatibility. This tool is not affiliated with or endorsed by Meta, LinkedIn, X, WhatsApp or Slack.

### Your data, storage and retention

- Results go only to **your own Apify account**: the run's dataset and key-value store (`REPORT`, `REPORT_CSV`, `SUMMARY` and the `PREVIEW-…` pages). They are kept for your Apify plan's data-retention period, unless you delete them sooner.
- The monitoring store described above keeps only a tag hash and a timestamp per URL, until you delete it.
- The Actor contacts only the URLs you submit (plus their images and oEmbed endpoints) and, if you turn AI on, your AI provider. It sends nothing to the developer, and the developer receives no copy of your input or results.

# Changelog

This Actor's version history is a separate document: https://apify.com/siteverdict/siteverdict-social-preview-checker/changelog.md

# Actor input Schema

## `executionMode` (type: `string`):

<b>Live</b> checks your URLs. <b>Sample</b> checks two recorded demo pages (one good, one broken) for free, with no network calls.

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

Pages whose link previews you want to check (max 500 per run): blog posts, product pages, landing pages.

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

Download the preview image to check that it loads and to measure its pixel size, aspect ratio, format and file weight against each platform's limits.

## `checkOembed` (type: `boolean`):

If the page advertises an oEmbed endpoint (used by Slack, WordPress, Discord and others), fetch and validate it.

## `savePreviews` (type: `boolean`):

Store an HTML page with the five preview mockups for each URL in the run's key-value store (linked from each row). A combined REPORT is always saved.

## `outputMode` (type: `string`):

'Only changes' outputs a URL only when its tags or image changed since the last run with the same state store; useful on a schedule to catch a CMS or plugin update breaking previews.

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

Named key-value store with the last tag fingerprint of each URL.

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

Requests to the same host are sequential, at most 1 per second.

## `timeoutSecs` (type: `integer`):

Per request.

## `aiEnabled` (type: `boolean`):

Off by default. For pages scoring under 90, your chosen LLM (with YOUR API key) writes a better og:title, og:description, alt text and an image brief from the page's own data. One 'ai-fix' event per successful answer; your provider bills tokens separately.

## `aiProvider` (type: `string`):

Which API your key belongs to.

## `aiApiKey` (type: `string`):

Your Anthropic or OpenAI API key. Stored encrypted by Apify, never logged or written to the output.

## `aiModel` (type: `string`):

Leave empty for the default (Anthropic: claude-sonnet-5-5, OpenAI: gpt-5-mini).

## Actor input object example

```json
{
  "executionMode": "live",
  "urls": [
    {
      "url": "https://www.python.org/"
    }
  ],
  "checkImages": true,
  "checkOembed": true,
  "savePreviews": true,
  "outputMode": "all",
  "stateStoreName": "siteverdict-social-preview-checker",
  "maxConcurrency": 4,
  "timeoutSecs": 30,
  "aiEnabled": false,
  "aiProvider": "anthropic"
}
```

# Actor output Schema

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

No description

## `report` (type: `string`):

No description

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

No description

## `files` (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://www.python.org/"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("siteverdict/siteverdict-social-preview-checker").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://www.python.org/" }] }

# Run the Actor and wait for it to finish
run = client.actor("siteverdict/siteverdict-social-preview-checker").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://www.python.org/"
    }
  ]
}' |
apify call siteverdict/siteverdict-social-preview-checker --silent --output-dataset

```

## MCP server setup

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

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/DuH7pWJjtMDIZ7QIR/builds/OiMDvmRdYh8dhuF3y/openapi.json
