# Meta Tags & Open Graph Extractor + Schema Checker — Unfurlwren (`cybermax/meta-tags-extractor`) Actor

Meta tag extractor and Open Graph checker: get each page's title, meta description, canonical, robots, hreflang, OG and Twitter Card tags (og:image verified), schema.org JSON-LD types, favicon and feeds, plus SEO and link-preview issues and a 0-100 score. $2 per 1,000 pages; failed pages free.

- **URL**: https://apify.com/cybermax/meta-tags-extractor.md
- **Developed by:** [CyberMax](https://apify.com/cybermax) (community)
- **Categories:** SEO tools, Developer tools, AI
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 page extracteds

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

## Unfurlwren: Meta Tags & Open Graph Extractor + Schema Checker

#### See exactly how every page looks to Google and in a shared link

Give it URLs; get each page's title, meta description, canonical, robots, hreflang, Open Graph and Twitter Card tags (with the og:image actually loaded and checked), schema.org JSON-LD types, favicon, feeds, a list of SEO and link-preview issues and a 0–100 score. $2 per 1,000 pages; pages that fail to load are free.

**[▶ Try it now with a prefilled input](https://apify.com/cybermax/meta-tags-extractor)** · $0.002 per page (1,000 pages = $2) · no start fee · Apify's free plan includes $5 of credit a month

**Built for:** SEO teams auditing titles, descriptions and structured data · social and content teams checking link previews before a launch · developers building link unfurls and previews · AI agents that need a page's metadata as JSON

**Real output** (real run on Apify, 25 Oct 2026, the prefilled input: 3 pages in 2.7 s, $0.006):

| Page | Score | Title (length) | og:image | Schema types | Issues |
|---|---|---|---|---|---|
| apify.com | 100 | Apify: Marketplace of ready-to-run tools for AI (47) | loads, image/png | Organization, WebSite, SoftwareApplication, Offer +4 | none |
| crawlee.dev | 95 | Crawlee · Build reliable crawlers. Fast. (40) | loads, image/png, 193 KB | none | no schema.org data |
| example.com | 35 | Example Domain (14) | missing | none | no description, no og:image, no canonical, no h1 +5 |

```json
{"urls": ["https://apify.com", "https://crawlee.dev", "https://example.com"]}
```

### Ready-made inputs (one click)

| Job | Input | Result |
|---|---|---|
| **First try** | the prefilled input above | Metadata, issues and score for 3 pages. |
| **Link preview check before a launch** | `{"urls": ["https://yoursite.com/launch"], "checkOgImage": true}` | The exact title, description and image a shared link shows. |
| **Schema.org audit** | `{"urls": ["…product pages…"], "includeJsonLd": true}` | Every JSON-LD block, its types and parse errors. |
| **Watch competitors' titles and offers** | `{"urls": ["…"], "monitor": true, "monitorKey": "rivals"}` | On a schedule: only pages whose title, description, OG tags or schema changed. |

### Use cases

- **On-page SEO audits:** title and description lengths, missing canonicals, noindex by mistake, several H1s, missing lang or viewport.
- **Social link previews:** see what Facebook, LinkedIn, Slack, X and iMessage will show, and catch a broken og:image before the post goes out.
- **Structured data checks:** which schema.org types each page declares (Product, Article, FAQPage, Organization…) and which JSON-LD blocks are broken.
- **Link unfurling for apps:** a clean `preview` object (title, description, image, site name, URL) per link.
- **Change tracking:** monitor competitors' page titles, descriptions and schema on a schedule.

### Why Unfurlwren

| | Unfurlwren | Typical metadata scraper on the Store |
|---|---|---|
| og:image verified | Loaded and checked (status, type, size) | URL only |
| SEO + preview issues and a score | 17 checks, 0–100 score | Raw tags only |
| JSON-LD | Parsed (lenient), @graph walked, types listed, parse errors flagged | Often raw text |
| Extras | hreflang, feeds, icons, manifest, theme colour, microdata types | Varies |
| Changes only | Built-in monitor mode | Not offered |
| Price | $2 per 1,000 pages, failed pages free | $0.99 to $10 per 1,000 (rival median about $3), some with a $0.09 start fee (Store prices on 25 Oct 2026) |

### Input

| Field | What it does |
|---|---|
| `urls` | Page URLs (required). |
| `checkOgImage` | Load the og:image and flag it if broken (default on). |
| `includeJsonLd` | Return the full parsed JSON-LD (default on). |
| `includeAllMeta` | Also return every `<meta>` tag as a map. |
| `timeoutSecs`, `maxConcurrency` | Limits. |
| `monitor`, `monitorKey` | Only pages that are new or changed since the last monitor run. |

### Output

One row per page: `url`, `finalUrl`, `status`, `title`, `titleLength`, `description`, `descriptionLength`, `canonical`, `robots`, `lang`, `h1`, `ogTitle`, `ogDescription`, `ogImage`, `ogImageCheck`, `ogType`, `ogSiteName`, `twitterCard`, `twitterImage`, `favicon`, `icons`, `appleTouchIcon`, `manifest`, `themeColor`, `hreflang`, `feeds`, `schemaTypes`, `microdataTypes`, `jsonLd`, `jsonLdErrors`, `preview`, `issues` (severity, code, message), `score`, and `change`/`changes` in monitor mode. Pages that can't be read get a free row with `ok: false` and the error.

### Pricing

- **$0.002 per page extracted** ($2 per 1,000). No start fee.
- Free: pages that time out or fail, 4xx/5xx pages, non-HTML URLs, unchanged pages in monitor mode.
- Set a maximum charge per run in Apify's run options; Unfurlwren stops cleanly when it is reached.

### Run it on a schedule

Apify Console → **Schedules** → **Create new** → cron `0 8 * * 1` (Mondays) → **Add Actor** → Unfurlwren with your pages and `"monitor": true`. Through the API:

```json
POST https://api.apify.com/v2/schedules?token=YOUR_TOKEN
{
  "name": "unfurlwren-rival-pages",
  "cronExpression": "0 8 * * 1",
  "timezone": "America/New_York",
  "isEnabled": true,
  "actions": [{
    "type": "RUN_ACTOR",
    "actorId": "cybermax/meta-tags-extractor",
    "runInput": {
      "body": "{\"urls\":[\"https://competitor.com/pricing\"],\"monitor\":true,\"monitorKey\":\"rivals\"}",
      "contentType": "application/json"
    }
  }]
}
```

### Integrations

**API (synchronous):** `POST https://api.apify.com/v2/acts/cybermax~meta-tags-extractor/run-sync-get-dataset-items?token=YOUR_TOKEN` with the input JSON returns the rows.

**Make / Zapier:** Apify app → "Run an Actor" (`cybermax/meta-tags-extractor`, run synchronously) → "Get dataset items" → map `title`, `description`, `ogImage`, `score`, `issues` into Google Sheets, Airtable or Notion.

**n8n:** Apify node ("Run an Actor and get dataset"), or HTTP Request:

```
POST https://api.apify.com/v2/acts/cybermax~meta-tags-extractor/run-sync-get-dataset-items?token=YOUR_TOKEN
{"urls": ["https://example.com"], "includeJsonLd": false}
```

**Google Sheets:**

```
=IMPORTDATA("https://api.apify.com/v2/acts/cybermax~meta-tags-extractor/runs/last/dataset/items?format=csv&fields=url,score,title,description,ogImage,canonical&token=YOUR_TOKEN")
```

**Python** (`pip install apify-client`):

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("cybermax/meta-tags-extractor").call(run_input={"urls": ["https://apify.com"]})
page = next(client.dataset(run["defaultDatasetId"]).iterate_items())
print(page["preview"], page["issues"])
```

**AI agents (MCP):** `https://mcp.apify.com/?tools=cybermax/meta-tags-extractor` (Authorization: `Bearer YOUR_TOKEN`). Typical prompts: "What will this link look like when I share it?", "Audit the titles and descriptions of these 50 pages".

### When NOT to use it

- **Pages that build their tags with JavaScript only:** Unfurlwren reads the HTML the server sends, which is also what most link-preview bots read.
- **Sites that block cloud IPs** answer 403; those rows are free.

### FAQ

**Why not the Facebook Sharing Debugger or a browser extension?** They check one URL at a time by hand. Unfurlwren checks hundreds in a run, scores them and runs on a schedule.

**Why not a full SEO crawler?** If you already have the URLs, a crawler is slower and costs more per page. Pair Unfurlwren with [Sitemoss](https://apify.com/cybermax/sitemap-url-extractor) to get every URL first.

**Can an AI agent use it (MCP)?** Yes. Add `https://mcp.apify.com/?tools=cybermax/meta-tags-extractor` as an MCP server in Claude, Cursor, VS Code or any MCP client.

**Does it validate schema.org against Google's rules?** It parses every JSON-LD block, lists the types and flags blocks that don't parse; it doesn't run Google's rich-result rules.

**Is it legal to use?** Unfurlwren reads public page metadata, the same tags link-preview bots and search engines read. This is general information, not legal advice.

### Start now

**[▶ Try Unfurlwren with a prefilled input](https://apify.com/cybermax/meta-tags-extractor)** · $2 per 1,000 pages, failed pages free. Questions? Open an issue on the Store page and it gets answered the same day.

### Also from CyberMax

- [Sitemoss — sitemap URL extractor](https://apify.com/cybermax/sitemap-url-extractor): every URL of a site, ready to audit.
- [Bouncefern — bulk URL status & redirect checker](https://apify.com/cybermax/url-status-checker): status codes, redirect chains and broken links.
- [Logolark — company logo API](https://apify.com/cybermax/logo-finder): each company's own logo and icon from its domain.
- [Capturewren — website screenshot API](https://apify.com/cybermax/website-screenshot): a screenshot and the text of each page.

### Changelog

- 2026-10-25: First release: meta, Open Graph, Twitter Card, JSON-LD and microdata, og:image check, hreflang, feeds, icons, 17 SEO/preview checks and score, monitor mode.

© 2026 CyberMax. All rights reserved.

# Actor input Schema

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

One page per line (https://example.com/page or just example.com). Each page is read once; duplicates are removed.

## `checkOgImage` (type: `boolean`):

Request the og:image and report its status, type and size (a broken share image is flagged as an issue).

## `includeJsonLd` (type: `boolean`):

Return every parsed JSON-LD block (schema.org structured data). Off = only the list of schema types.

## `includeAllMeta` (type: `boolean`):

Also return a map of all <meta> name/property values.

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

Pages that time out are retried once and then reported free.

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

Lower it for a single fragile site.

## `monitor` (type: `boolean`):

For scheduled runs. Remembers each page's title, description, canonical, robots, OG title/description/image and schema types, and returns only pages that are new or changed since the last monitor run (changedFields, changes from/to). Unchanged pages are not returned and not charged.

## `monitorKey` (type: `string`):

Optional name for this watchlist's saved state.

## Actor input object example

```json
{
  "urls": [
    "https://apify.com",
    "https://crawlee.dev",
    "https://example.com"
  ],
  "checkOgImage": true,
  "includeJsonLd": true,
  "includeAllMeta": false,
  "timeoutSecs": 20,
  "maxConcurrency": 8,
  "monitor": false
}
```

# 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 = {
    "urls": [
        "https://apify.com",
        "https://crawlee.dev",
        "https://example.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("cybermax/meta-tags-extractor").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://apify.com",
        "https://crawlee.dev",
        "https://example.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("cybermax/meta-tags-extractor").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://apify.com",
    "https://crawlee.dev",
    "https://example.com"
  ]
}' |
apify call cybermax/meta-tags-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,cybermax/meta-tags-extractor"
        }
    }
}
```

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/3NeMVQoEvivcfywtf/builds/GJtnJaPBT00PnGKHP/openapi.json
