# SEO Meta Tags Extractor (`eichan/seo-meta-tags-extractor`) Actor

Extract HTML title, description, robots and language metadata from up to five supplied pages.

- **URL**: https://apify.com/eichan/seo-meta-tags-extractor.md
- **Developed by:** [Eichan Jolly](https://apify.com/eichan) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 60.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 results

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

## SEO Meta Tags Extractor

Extract HTML title, description, robots and language metadata from up to five supplied pages.

### What it does

Reads each supplied page and extracts its HTML `<title>`, `<meta name="description">`, `<meta name="robots">`, root HTML `lang`, and declared `<meta charset>`. Reports title and description character counts. It does **not** score rankings, crawl linked pages, or parse social cards.

### Who it is for

SEO analysts, content editors, and website owners checking title and description coverage on a few public pages.

### Input example (prefilled in Apify Console)

```json
{
  "urls": ["https://example.com/"]
}
```

One to five URLs. Paste them into the **Page URLs** field. Only HTTP/HTTPS pages on standard ports 80/443 with public domain names are accepted.

### Output example (illustrative, not a claim about example.com)

Each input URL produces exactly one default-dataset item in input order, even if fetching fails. Field names and types are stable; missing values are `null` (lengths are zero when tags are absent on a successfully parsed page).

```json
{
  "url": "https://example.com/",
  "finalUrl": "https://example.com/",
  "httpStatus": 200,
  "title": "Example page",
  "description": "A short example description.",
  "titleLength": 12,
  "descriptionLength": 28,
  "metaRobots": "index,follow",
  "language": "en",
  "charset": "utf-8",
  "status": "ok",
  "error": null
}
```

On failure, `status` is `"error"` and `error` contains a plain-language reason. Fields unavailable due to failure remain `null`. `httpStatus` is `null` for failures before a successful page response.

### Limits and safety

- Only supplied URLs plus their `/robots.txt` files and necessary HTTP redirects are fetched; no discovery, login, or unrestricted crawling. Known search engine result-page URL patterns are explicitly rejected; the tool is not for SERP extraction.
- Robots rules are evaluated using Python's `urllib.robotparser`. Missing robots files (HTTP 404/410) are treated as no rules; robots fetch failures, HTTP restrictions, or explicit disallow rules fail closed. Some crawlers use different robots interpretation details.
- At most 5 pages; 4 redirects per page, 10-second socket timeout per request, 1,000,000 bytes per HTML response, 256,000 bytes per robots response. Redirect destinations get their own robots check.
- Public-host DNS and IP checks are applied before each connection; DNS-selected IP is pinned for the connection (prevents DNS rebinding within the connection). Direct IP URLs, private targets, credential-bearing URLs and nonstandard ports are rejected.
- Static HTML only: client-side JavaScript is not executed. No support for pages requiring cookies, authorization, or deliberately encoded compressed responses.
- Sites can block bot traffic, and redirects across sites are possible; the Actor does not bypass blocks.
- Parsed characters are counted as Unicode code points, not rendered pixel widths. Only the first occurrence of each supported meta tag is used.

### Storage and local run

The Actor uses Python **standard library only**; `requirements.txt` contains no dependencies. On Apify it reads `INPUT` from the default key-value store via the API and appends results to the default dataset via the API (no SDK). For a local run, create `storage/key_value_stores/default/INPUT.json` with the input shown above and execute:

```bash
python src/main.py
```

Local dataset JSON files appear under `storage/datasets/default/`. You can instead set `APIFY_LOCAL_STORAGE_DIR` to a custom storage folder. Running locally again will replace numbered items in that folder; clean the folder between test runs to avoid stale extras.

### Suggested Apify Store categorization

SEO tools, Marketing. These are publisher-suggested categories, **not** fields in `actor.json`. Apify's 2026 Store classification rollout automatically assigns Store categories; the Actor manifest has no documented `categories` setting.

### Suggested pricing

**Pay per event, per run:** start at **US$0.01/run** for up to five URLs, as an initial hypothesis subject to actual cost and demand testing. Configure the synthetic `apify-actor-start` event under Apify Console → Publishing → Monetization; disable any additional priced dataset-item event if you want one charge per run. No custom billing API logic is included. Pricing is a recommendation and is **not** activated by this source bundle.

### Deployment

From this folder, use Apify CLI to deploy (`apify push`), then configure Store publication and pricing in Apify Console. Cloud validation and billing configuration require deployment; this package does not assert that it has been tested on Apify infrastructure.

# Actor input Schema

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

Public http(s) HTML pages. No authentication, search results, or deep crawling.

## Actor input object example

```json
{
  "urls": [
    "https://example.com/"
  ]
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing the Actor's result items

# 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/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("eichan/seo-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/"] }

# Run the Actor and wait for it to finish
run = client.actor("eichan/seo-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/"
  ]
}' |
apify call eichan/seo-meta-tags-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,eichan/seo-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/1wt7FGxoXmaSh5JGk/builds/Q2VMuh93w0FQV5ULy/openapi.json
