# Meta Tags & Open Graph Extractor: Title, SEO, Twitter Cards (`data-done-right/meta-tags-extractor`) Actor

Meta tags extractor for bulk URLs: get title, meta description, canonical, robots, hreflang, Open Graph, Twitter Cards, JSON-LD types, feeds and H1 as flat rows, with quick SEO checks and an issues list for every page.

- **URL**: https://apify.com/data-done-right/meta-tags-extractor.md
- **Developed by:** [Data Done Right](https://apify.com/data-done-right) (community)
- **Categories:** SEO tools, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 page analyzeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Meta Tags & Open Graph Extractor: Title, SEO, Twitter Cards

This **meta tags extractor** reads a list of URLs and returns one flat row per page with the **title, meta description, canonical, robots, language, Open Graph tags, Twitter Card tags, JSON-LD types, hreflang, favicons, feeds and H1**. It is a **meta tags scraper** and **website metadata** checker in one: bulk input, clean output, no browser, no login, no API key. Every row also carries quick SEO checks and an `issues` list.

### What does this meta tags extractor return

- **Basics:** `title`, `titleLength`, `metaDescription`, `metaDescriptionLength`, `canonical`, `robots`, `xRobotsTag`, `lang`, `viewport`, `charset`, `keywords`, `author`, `generator`, `themeColor`.
- **Open Graph:** every `og:*` tag in `openGraph` (title, description, image, type, url, site_name, ...).
- **Twitter Cards:** every `twitter:*` tag in `twitterCard` (card, site, image, ...).
- **Structured data:** `jsonLdTypes` (Organization, Product, Article, ...). Turn on `includeRawJsonLd` to get the full parsed JSON-LD blocks too.
- **Links in the head:** `hreflang` (language and URL), `icons` (favicon, Apple touch icon), `feeds` (RSS, Atom, JSON Feed).
- **Page and response:** `h1` and `h1Count`, `statusCode`, `finalUrl` after redirects, `redirects`, `responseTimeMs`, `contentType`.
- **Checks:** `issues[]` with codes such as `title-too-long`, `meta-description-missing`, `canonical-missing`, `og-image-missing`, `twitter-card-missing`, `h1-missing`, `noindex`.

### How to extract meta tags from many URLs

1. Paste your page URLs in **Page URLs**, one per line (a bare domain works too).
2. Optional: set **Max URLs**, **Parallel requests** and a **Proxy**.
3. Run it, then download the dataset as JSON, CSV or Excel. The **Meta tags** table view shows the key columns.

### How to check Open Graph and Twitter Card tags

Run your page list and filter on `issues`: rows containing `og-image-missing`, `og-title-missing`, `og-description-missing` or `twitter-card-missing` need a fix before the page is shared on social networks. The `openGraph.image` value is the exact image URL as written in the page (it may be relative).

### Input example

```json
{
  "urls": ["https://example.com", "https://www.python.org", "https://apify.com"],
  "includeRawJsonLd": false,
  "maxUrls": 100,
  "concurrency": 5
}
```

### Output example

```json
{
  "url": "https://apify.com",
  "finalUrl": "https://apify.com/",
  "statusCode": 200,
  "status": "ok",
  "responseTimeMs": 356,
  "redirects": 1,
  "title": "Apify: Marketplace of ready-to-run tools for AI",
  "titleLength": 48,
  "metaDescription": "...",
  "canonical": "https://apify.com/",
  "robots": null,
  "lang": "en",
  "openGraph": {"title": "...", "image": "https://...", "type": "website"},
  "twitterCard": {"card": "summary_large_image"},
  "jsonLdTypes": ["Organization", "WebSite"],
  "hreflang": [],
  "icons": [{"rel": "icon", "href": "https://apify.com/favicon.ico", "sizes": null, "type": null}],
  "feeds": [],
  "h1": "...",
  "h1Count": 1,
  "issues": [],
  "error": null
}
```

`status` is `ok`, `http-error` (for example 404), `not-html`, `parse-error`, `failed` (timeout, DNS, blocked) or `invalid-url`. A bad URL always gives an error row and never stops the run. The `FAILED` record lists them, `NOTES` lists skipped duplicates, and `SUMMARY` has the totals.

### SEO checks and thresholds

Title: missing, over 60 characters, under 30. Meta description: missing, over 160, under 70. Also flagged: no canonical, no `og:image` / `og:title` / `og:description`, no Twitter Card, no or multiple H1, no `lang`, no viewport, `noindex` (meta or header), invalid JSON-LD. These are common SEO rules of thumb, not Google rules.

### How much does it cost to extract meta tags

Pay per event: **$0.0025 per page analyzed** (event `page-analyzed`, $2.50 per 1,000 pages), plus normal Apify platform usage, which is small. Only pages that returned HTML with status 200 are charged. 404s, timeouts, non-HTML files and invalid URLs are free. Set a maximum spending limit and the run stops cleanly when it is reached.

### Use cases

- Bulk SEO audits of titles, descriptions and canonicals across a URL list.
- Checking Open Graph and Twitter Card previews before a launch or newsletter.
- Competitor research: which schema.org types and hreflang setups do they use?
- Finding RSS and Atom feeds, favicons and CMS generators for a list of sites.
- Enriching a lead or link list with website metadata.

### Limits (honest)

- It reads the **raw HTML** the server sends. Tags that JavaScript adds after load are not seen (no browser is run).
- Only the first 5 MB of a page is parsed. Pages that block normal requests (403, bot walls, CAPTCHAs) give an error row; there is no bot-protection evasion. A proxy may help on some sites.
- For a full crawl with broken-link checks use a site audit tool instead; this actor only checks the URLs you give it.
- Duplicate URLs in one run are processed once.

### FAQ

**Does it execute JavaScript?** No. It is fast and cheap because it reads the HTML only. Single-page apps that inject meta tags in the browser may show empty fields.

**Are failed URLs charged?** No. Only analyzed HTML pages with status 200.

**Why is `openGraph.image` relative or missing?** The value is returned as written in the page. Missing means the tag is not there, and the row gets `og-image-missing`.

**Can it follow redirects?** Yes. `finalUrl` is the last URL and `redirects` counts the hops. Meta tags are read from the final page.

**How many URLs per run?** Up to 10,000 (default 100). Use `concurrency` to speed up large lists.

**Is it legal?** It reads publicly available page metadata. Respect each site's terms and robots rules for your use case.

### Related tools

- **SEO Audit Tool & Meta Tag Checker: Crawler, Broken Links** for crawling a whole site and scoring every page.
- **HTTP Status Code Checker: Bulk URL, Website & Redirect Chains** for bulk HTTP status and redirect checks.
- **Sitemap Parser & Extractor: Sitemap to CSV, URLs & New Pages** for tracking sitemap changes.

# Actor input Schema

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

Web pages to extract meta tags from, one per line. A domain without https:// also works. Example: https://example.com/blog/post-1.

## `includeRawJsonLd` (type: `boolean`):

Also return the full parsed JSON-LD blocks (field jsonLd). The JSON-LD types are always returned in jsonLdTypes. Rows get bigger when this is on.

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

Most URLs processed in this run. URLs beyond this are skipped and not charged. Example: 100.

## `concurrency` (type: `integer`):

How many pages are fetched at the same time. Lower it for sites that block fast requests. Default 5.

## `retries` (type: `integer`):

How many times a URL is tried after timeouts, 429 or 5xx errors before it gets an error row. Default 3.

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

Give up on a single request after this many seconds. Default 30.

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

Optional. Fetch pages through Apify Proxy or your own proxies. Usually not needed for public pages.

## Actor input object example

```json
{
  "urls": [
    "https://example.com",
    "https://www.python.org",
    "https://apify.com"
  ],
  "includeRawJsonLd": false,
  "maxUrls": 100,
  "concurrency": 5,
  "retries": 3,
  "timeoutSecs": 30,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

All result items of this run (the default dataset), as JSON, CSV, Excel and more.

## `records` (type: `string`):

Key-value store records: the run summary, notes on any problems, and any files.

# 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://example.com",
        "https://www.python.org",
        "https://apify.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("data-done-right/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://example.com",
        "https://www.python.org",
        "https://apify.com",
    ] }

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,data-done-right/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/msgm5NKYxWBnONyky/builds/oF1WfGlJ0TeUrI9pc/openapi.json
