# URL Metadata Extractor – Open Graph, JSON-LD, Logo, Favicon (`gazidev/metadata-schema-extractor`) Actor

Extract link-preview and brand metadata from any URL: title, description, Open Graph, Twitter card, JSON-LD (Schema.org), favicon, logo, theme colour, hreflang, oEmbed, feeds, social profiles, author and dates. Flags missing or invalid tags. No browser: fast and cheap.

- **URL**: https://apify.com/gazidev/metadata-schema-extractor.md
- **Developed by:** [Cemal Atakli](https://apify.com/gazidev) (community)
- **Categories:** SEO tools, Developer tools
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 url processeds

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

## URL Metadata & Schema.org Extractor – Open Graph, Twitter Card, JSON-LD, Logo

Give it a list of URLs and get back **everything a link preview, CRM or AI agent needs to know about each page**: title, meta description, canonical, language, robots, **all Open Graph tags**, **Twitter card**, **JSON-LD / Schema.org** (with `@graph` flattened), microdata, **favicon, apple-touch-icon and the site logo**, theme colour, hreflang alternates, oEmbed and RSS/Atom feeds, **social profile links**, site name, author and publish dates. Every row also gets a list of **missing or invalid tags**, so the same run doubles as an SEO / social-sharing check.

Plain HTTP, no browser: **$1 per 1,000 URLs**, failed URLs are free.

**Related Actors (website toolkit):** [Sitemap Extractor](https://apify.com/gazidev/sitemap-url-extractor) to get every URL of a site first, [Website to Markdown](https://apify.com/gazidev/website-to-markdown) for the page content as clean Markdown, [SEO Audit Crawler](https://apify.com/gazidev/seo-audit-crawler) for a full-site crawl with broken links and redirects, [Website Contact Finder](https://apify.com/gazidev/website-contact-finder) for emails and phones, and [Tech Stack Detector](https://apify.com/gazidev/tech-stack-detector) for the software a site runs on.

### What it extracts per URL

- **Basics:** final URL after redirects, HTTP status, response time, `<title>`, meta description, canonical, `<html lang>`, meta robots, `X-Robots-Tag`, viewport, charset, keywords, H1s.
- **Open Graph:** every `og:*`, `article:*`, `product:*`, `fb:*` tag (repeated tags become arrays), plus a structured `ogImages` list with width, height, alt and secure URL.
- **Twitter / X card:** every `twitter:*` tag.
- **JSON-LD:** every block parsed (lenient: trailing commas, HTML comments and CDATA are repaired), `@graph` flattened, `@context` kept. `jsonLdTypes` lists the top-level types and `jsonLdAllTypes` the nested ones. Ready-made summaries:
  - `organization` – name, URL, **logo**, sameAs, email, telephone
  - `product` – name, brand, SKU, GTIN, image, **price, currency, availability**, rating
  - `article` – headline, published/modified dates, authors, image, publisher
  - `breadcrumbs` – position, name, URL
- **Microdata and RDFa (light):** `itemscope`/`itemprop` items with nested properties, and RDFa `typeof` types.
- **Brand assets:** best `favicon` (falls back to `/favicon.ico`), `appleTouchIcon`, every icon with sizes, web manifest, and a **best-guess `logo`** with its source: JSON-LD Organization logo → `og:logo` → microdata → `<img>` with "logo" in the header/nav → large touch icon. `themeColor` from `<meta name="theme-color">`.
- **Link preview fields:** `previewTitle`, `previewDescription`, `image`, `siteName` – the same fallbacks Slack, LinkedIn and iMessage use (OG → Twitter → HTML).
- **Image check (optional, on by default):** reads the first 64 KB of the preview image and the logo and reports HTTP status, content type, **file size and pixel width × height** (PNG, JPEG, GIF, WebP, AVIF, ICO, SVG).
- **Discovery links:** hreflang alternates, oEmbed endpoints, RSS/Atom/JSON feeds.
- **Social profiles:** from JSON-LD `sameAs` and header/footer links – Facebook, X/Twitter, Instagram, LinkedIn, YouTube, TikTok, Pinterest, GitHub, Threads, Bluesky, Mastodon, Discord, Telegram and more. Share buttons and deep links (posts, repos) are filtered out.
- **People and dates:** authors (meta, `article:author`, JSON-LD), author URL, published and modified times.

### Missing / invalid tag checks

Each row has `issues` (`code`, `severity`, `message`), `issueCodes`, `errorCount` and `warningCount`. Checks include:

| Severity | Codes |
|---|---|
| error | `missing-title`, `multiple-canonicals`, `og-image-not-absolute`, `invalid-json-ld`, `invalid-hreflang`, `preview-image-broken` |
| warning | `title-too-long` (>60), `title-too-short`, `missing-meta-description`, `missing-canonical`, `missing-html-lang`, `missing-viewport`, `noindex`, `noindex-header`, `missing-og-title`, `missing-og-image`, `og-image-too-small` / `preview-image-too-small` (<200 px), `invalid-twitter-card`, `json-ld-missing-type`, `json-ld-missing-context`, `hreflang-missing-self-reference`, `logo-broken` |
| info | `meta-description-too-long` (>160) / `-too-short`, `canonical-points-elsewhere`, `missing-og-description` / `-url` / `-type`, `missing-twitter-card`, `no-structured-data`, `product-without-offer-price`, `missing-favicon-link`, `missing-apple-touch-icon`, `hreflang-missing-x-default`, `nofollow` |

### Use cases

- **Link previews / unfurling** in your chat app, CMS, bookmarking tool or newsletter editor.
- **CRM and lead enrichment:** company logo, favicon, brand colour, description and social profiles from a website URL.
- **AI agents:** a cheap "what is this page?" tool that returns structured facts instead of raw HTML.
- **SEO and social-sharing QA:** find pages without OG images, broken or tiny share images, invalid JSON-LD, missing canonicals or hreflang errors – combine with the [Sitemap Extractor](https://apify.com/gazidev/sitemap-url-extractor) to check a whole site.
- **E-commerce monitoring:** product name, price, currency and availability from JSON-LD on any shop.
- **Content research:** article headline, authors and publish dates from news sites and blogs.

### Input

| Field | Description |
|---|---|
| `urls` | Page URLs (bare domains work). One row each |
| `probeImages` | Check the preview image and logo: status, size, dimensions (default on) |
| `includeJsonLd` | Output full JSON-LD objects (default on; summaries are always included) |
| `includeMicrodata` | Also read microdata and RDFa (default on) |
| `maxUrls`, `respectRobotsTxt`, `maxConcurrency`, `maxRequestsPerHost`, `requestTimeoutSecs`, `maxRetries`, `userAgent`, `proxyConfiguration` | Advanced |

```json
{
  "urls": ["https://stripe.com", "https://www.allbirds.com/products/mens-wool-runners", "https://paulgraham.com/greatwork.html"],
  "probeImages": true
}
```

### Output

The Output tab has four tables – **Link preview & brand**, **SEO tag check**, **Structured data** and **Social profiles, feeds, hreflang, oEmbed** – plus the full JSON and a run `SUMMARY`. A real row (stripe.com, shortened):

```json
{
  "url": "https://stripe.com",
  "finalUrl": "https://stripe.com",
  "status": 200,
  "ok": true,
  "title": "Stripe | Financial Infrastructure to Grow Your Revenue",
  "siteName": "Stripe",
  "previewTitle": "Stripe | Financial Infrastructure to Grow Your Revenue",
  "image": "https://b.stripecdn.com/mkt-ssr-statics/assets/_next/static/media/stripe.37119086.jpg",
  "imageProbe": {"status": 206, "ok": true, "contentType": "image/jpeg", "bytes": 312818, "format": "jpeg", "width": 2048, "height": 1024},
  "logo": "https://images.stripeassets.com/fzn2n1nzq965/1hgcBNd12BfT9VLgbId7By/01d91920114b124fb4cf6d448f9f06eb/favicon.svg",
  "logoSource": "json-ld",
  "favicon": "https://assets.stripeassets.com/fzn2n1nzq965/nu0iR4KqmkdJ52fgRts09/c3a10df318e7ffb1f516073daadea625/favicon.ico",
  "jsonLdTypes": ["WebSite", "Organization"],
  "socialProfiles": [
    {"platform": "x", "url": "https://twitter.com/stripe", "source": "json-ld sameAs"},
    {"platform": "linkedin", "url": "https://www.linkedin.com/company/stripe", "source": "json-ld sameAs"}
  ],
  "issueCodes": [],
  "errorCount": 0,
  "warningCount": 0
}
```

A product page adds `product` (`{"name": "Men's Wool Runner", "brand": "Allbirds", "price": "110", "priceCurrency": "USD", "availability": "InStock", ...}`); an article adds `article`, `authors` and `publishedTime`. A page without any Open Graph (paulgraham.com) still returns its title and favicon, with 12 issue codes such as `missing-og-image` and `missing-meta-description`. Failed URLs are rows with `ok: false`, `errorType` (`network`, `http`, `robots`, `not-html`, `no-metadata`) and `error`. See [SAMPLE_OUTPUT.json](SAMPLE_OUTPUT.json) for full real rows.

### Pricing

Pay per event:

| Event | Price |
|---|---|
| URL processed (page fetched and parsed) | **$0.001** ($1 per 1,000 URLs) |
| Actor start | $0.00005 |
| Failed URLs (DNS, timeout, 4xx/5xx, robots.txt, non-HTML, bot challenge) | free |

Compared with other metadata Actors in the Apify Store (listed prices, October 2026):

| Actor | Listed price |
|---|---|
| autofacts/metadata-scraper | $5 / 1,000 URLs |
| njoylab metadata extractor | $10 / 1,000 URLs |
| **This Actor** | **$1 / 1,000 URLs**, image checks included |

Set a **maximum cost per run** in the run options: the Actor processes as many URLs as fit, never fetches a URL it cannot bill, and stops cleanly.

### FAQ

**Does it run JavaScript?**
No. It reads the HTML the server sends, which is exactly what Facebook, LinkedIn, Slack and X read to build link previews – so if a tag is missing here, it is missing for them too. Pure JavaScript apps without server-rendered meta tags come back as `no-metadata` and are not charged.

**Some sites return 403 or time out.**
A few large sites (e.g. Etsy, NYTimes, The Guardian, NPR) block automated clients at their CDN. The Actor sends an honest bot User-Agent with a contact address and respects robots.txt, so these rows fail and are free. You may set your own `userAgent` or a proxy for sites you are allowed to access.

**Does it respect robots.txt?**
Yes by default, including Crawl-delay; disallowed URLs are reported with `errorType: "robots"` and not charged. At most 2 parallel requests per host.

**How is the logo chosen?**
In order: JSON-LD Organization/Brand `logo`, `og:logo`, microdata `logo`, an `<img>` with "logo" in its attributes inside the header/navigation (customer-logo walls are skipped), the image linking to the home page, and finally a touch icon of 120 px or more. `logoSource` tells you which one was used. Inline SVG logos have no URL and cannot be returned.

**Can I get CSV or Excel?**
Yes, every Apify dataset exports to CSV, Excel, JSON or XML. Use the table views for flat columns.

### Use with AI agents / Apify MCP

Connect the Actor through the [Apify MCP server](https://mcp.apify.com) (`https://mcp.apify.com?actors=gazidev/metadata-schema-extractor`) and Claude, ChatGPT, Cursor or any MCP client can call it with prompts like *"get the logo, brand colour and social profiles of these 20 company websites"* or *"check which of our blog posts have no og:image"*. Over the API: `POST https://api.apify.com/v2/acts/gazidev~metadata-schema-extractor/run-sync-get-dataset-items` with `{"urls": ["https://example.com"]}`. Turn `includeJsonLd` off for smaller responses in agent contexts.

### Categories

SEO tools · Developer tools · AI · Lead generation

# Actor input Schema

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

Page URLs to read metadata from: home pages, articles, product pages, anything. A bare domain like `example.com` is turned into `https://example.com`. Duplicates are removed. One dataset row per URL.

## `probeImages` (type: `boolean`):

Download the first 64 KB of the preview image (og:image / twitter:image) and the logo to report HTTP status, content type, file size and pixel width x height. Flags broken or too-small preview images. Included in the price.

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

Output every parsed JSON-LD object (`@graph` flattened) in `jsonLd`. Turn off to keep rows small; `jsonLdTypes`, `organization`, `product`, `article` and `breadcrumbs` summaries are always included.

## `includeMicrodata` (type: `boolean`):

Also read Schema.org microdata (`itemscope`/`itemprop`, nested items) and RDFa `typeof` types. Many older shops and WordPress themes use microdata instead of JSON-LD.

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

Process at most this many URLs from the list (0 = all).

## `respectRobotsTxt` (type: `boolean`):

Skip URLs that the site's robots.txt disallows for crawlers (also honours Crawl-delay). Skipped URLs are reported and not charged. Turn off only for your own sites.

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

How many URLs are processed at the same time overall.

## `maxRequestsPerHost` (type: `integer`):

Politeness limit when many URLs share one host.

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

Per-request timeout. Timeouts, 429 and 5xx responses are retried.

## `maxRetries` (type: `integer`):

Retries per URL on network errors, 429 and 5xx (with backoff).

## `userAgent` (type: `string`):

Optional. By default an honest bot User-Agent with a contact address is sent.

## `proxyConfiguration` (type: `object`):

Optional. Most sites serve metadata to everyone; use a proxy only for sites that block datacenter IPs.

## Actor input object example

```json
{
  "urls": [
    "https://www.theverge.com",
    "https://github.com/apify/crawlee",
    "https://stripe.com",
    "https://example.com"
  ],
  "probeImages": true,
  "includeJsonLd": true,
  "includeMicrodata": true,
  "maxUrls": 0,
  "respectRobotsTxt": true,
  "maxConcurrency": 10,
  "maxRequestsPerHost": 2,
  "requestTimeoutSecs": 20,
  "maxRetries": 2,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `preview` (type: `string`):

No description

## `seo` (type: `string`):

No description

## `schema` (type: `string`):

No description

## `links` (type: `string`):

No description

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

No description

## `summary` (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://www.theverge.com",
        "https://github.com/apify/crawlee",
        "https://stripe.com",
        "https://example.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("gazidev/metadata-schema-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://www.theverge.com",
        "https://github.com/apify/crawlee",
        "https://stripe.com",
        "https://example.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("gazidev/metadata-schema-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://www.theverge.com",
    "https://github.com/apify/crawlee",
    "https://stripe.com",
    "https://example.com"
  ]
}' |
apify call gazidev/metadata-schema-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,gazidev/metadata-schema-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/O8z2wxKZcE6cS1six/builds/ameM419gpbnilOjjC/openapi.json
