# MOZ Scraper (SEO Health Score) (`simpleapi/moz-scraper`) Actor

🔍 MOZ Scraper (moz-scraper) automates extracting SEO data from Moz for faster insights. ✅ Gather key metrics, track visibility & optimize strategy. 📈 Perfect for SEO teams, agencies & analysts. 🚀 Save time, boost performance.

- **URL**: https://apify.com/simpleapi/moz-scraper.md
- **Developed by:** [SimpleAPI](https://apify.com/simpleapi) (community)
- **Categories:** SEO tools, Automation, Developer tools
- **Stats:** 4 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### MOZ SEO Health Scorer — Domain Authority and Backlinks

MOZ SEO Health Scorer turns MOZ's free Domain Analysis tool into a single composite SEO Health Score (0-100) plus letter grade per domain, computed transparently from only the genuinely-scraped signals — Domain Authority, Page Authority, Spam Score, Linking Root Domains, RDAP domain age, and ranking-keyword count — alongside the full domain overview MOZ itself publishes. It's built for SEO agencies triaging a client or prospect list by real domain health, link-building teams screening potential partners before outreach, and analysts who want a reproducible score they can audit component-by-component, not a black-box number. No MOZ account or API key is required. Every section below documents an input, an output field, and — critically — which fields are genuinely scraped versus derived estimates.

### What is MOZ SEO Health Scorer?

This Actor scrapes MOZ's public Domain Analysis page for a domain and returns both the raw overview data (Domain Authority, Page Authority, Spam Score, top pages, top linking domains, ranking and branded keywords, top questions, top competitors) and a composite SEO Health Score computed from a documented, reproducible weighting formula.

Key capabilities, read from the source:

- **A fully transparent, reproducible score.** `compute_seo_health()` in `src/main.py` builds `scoreBreakdown` with the raw value, normalized 0-1 value, base weight, effective weight, and exact point contribution for every component — the contributions sum exactly to `seoHealthScore`, so the number is independently verifiable from the row itself, not a black box.
- **Real-signals-only scoring, with the exclusion explicit.** The module's own docstring lists what's deliberately kept out of the score: `total_backlinks`, `quality_backlinks`, the do-follow/no-follow percentages, `trust_score`, `offpage_seo_score_percentage`, and any authority-history month not backed by a real Wayback Machine snapshot — because the base tool estimates rather than independently scrapes those values.
- **A missing-components list, not a silently lower score.** `scoreBreakdownMissingComponents` names any weight component that couldn't be computed (e.g. Domain Overview disabled), and the remaining components' weights are renormalized to still sum to 100 rather than silently under-scoring a domain for data you chose not to collect.
- **Automatic proxy escalation.** `ProxyLadder` starts with no proxy, escalates to a datacenter proxy on a block, then to a sticky residential proxy — staying there for the rest of the run once reached.
- **A minimum-score gate that never drops the unscoreable.** `minHealthScore` filters out domains scoring below your threshold, but a domain for which no score could be computed at all (e.g. with Domain Overview turned off) is never filtered — only a domain with a real, low score is excluded.

### What data can I extract with MOZ SEO Health Scorer?

Every field below is read directly from `scrape_domain()` and `compute_seo_health()` in `src/main.py`.

#### Real, directly-scraped fields (feed the health score)

| Field | Example Value | Source |
| --- | --- | --- |
| `authority_score` | `72` | MOZ's own Domain Authority card |
| `page_authority_score` | `65` | Page Authority of the top-linked page (MOZ's own table) |
| `spam_score` | `3` | MOZ's own Spam Score card |
| `total_linking_root_domains` | `12500` | MOZ's own Linking Root Domains card |
| `domain_age_years` | `14.2` | Real domain registration date via RDAP lookup |
| `top_ranking_keywords` / `top_pages` / `top_linking_domains` / `top_branded_keywords` / `top_questions` / `top_competitors` | arrays | MOZ's own listed tables, parsed directly |
| `keywords_ranking_distribution` / `backlinks_discovered_lost_history` | arrays | Parsed from MOZ's inline chart data |

#### The SEO Health Score

| Field | Example Value | Notes |
| --- | --- | --- |
| `seoHealthScore` | `78` | 0-100 composite, computed only from the real fields above |
| `seoHealthGrade` | `"B"` | A ≥90, B ≥75, C ≥60, D ≥45, F below |
| `scoreBreakdown` | object per component | `raw_value`, `normalized`, `base_weight`, `effective_weight`, `contribution` — sums to `seoHealthScore` |
| `scoreBreakdownMissingComponents` | `[]` | Weight components that couldn't be computed for this domain |
| `strengths` / `weaknesses` | text arrays | Threshold-based, fired only from real scraped values — never from an estimated field |

#### Derived/estimated fields — not independently scraped

| Field | Example Value | How it's derived |
| --- | --- | --- |
| `total_backlinks` | `222500` | `total_linking_root_domains × 17.8`, a fixed multiplier — an estimate, not a MOZ-reported count |
| `quality_backlinks` / `quality_backlinks_percentage` | derived from `total_backlinks` and `authority_score` | Formula-based estimate |
| `trust_score` | `da / 10` | A simple derived ratio, not a distinct MOZ metric |
| `offpage_seo_score_percentage` | derived from `authority_score`/`page_authority_score` | Formula-based estimate |
| `do_follow_backlinks_percentage` / `no_follow_backlinks_percentage` | derived from `authority_score` | Formula-based estimate |
| `authority_score_history` months without a real Wayback snapshot | a bounded, deterministic per-domain walk | Only months matched to a real archived MOZ snapshot (via the Wayback Machine's CDX index) carry a verified value; the rest fill a tight, domain-seeded band around the current score so the timeline has no gaps — treat unmatched months as illustrative trend shape, not measured history |

These estimated fields are included because they mirror MOZ's own overview page presentation, but — as the source itself documents — none of them are independently scraped values, which is exactly why the SEO Health Score excludes all of them.

### Why not build this yourself?

MOZ's Domain Analysis tool has no public API for the free tier, and its per-IP rate limit means a naive scraper gets blocked quickly at any real volume — this Actor's automatic proxy escalation (direct → datacenter → sticky residential) exists specifically to handle that. Getting genuine historical Domain Authority data is harder still: MOZ doesn't publish a history endpoint at all, so the only source of a real past DA value is an archived snapshot of the MOZ page itself via the Wayback Machine's CDX index — a research path most scrapers skip entirely in favor of guessing. This Actor does the real lookup where possible and is explicit — both in the field-level documentation above and in `scoreBreakdownMissingComponents`/the excluded-fields list — about exactly which numbers are real MOZ data and which are formula-based estimates, so you're not stuck reverse-engineering that distinction yourself.

### How to use data extracted from MOZ SEO Health Scorer?

#### SEO agencies triaging client or prospect lists

Run a batch of domains with `minHealthScore` set to your quality bar, and use `scoreBreakdown` to show a prospective client exactly which factors are dragging their score down — a transparent, component-by-component explanation beats a bare number in a sales conversation.

#### Link-building and outreach teams

Screen potential link partners by `authority_score` and `spam_score` before reaching out, using `strengths`/`weaknesses` as a quick pre-outreach gut check on a domain's real link-profile health.

#### Competitive SEO research

Compare `top_ranking_keywords`, `top_competitors`, and `keywords_ranking_distribution` across a set of competitor domains to see where your own site's ranking-keyword footprint is thin by comparison.

#### AI agents and reporting pipelines

Because `scoreBreakdown` and `scoreBreakdownMissingComponents` make the score's inputs and gaps fully explicit, an agent can generate an accurate, defensible SEO summary without re-deriving which fields are real versus estimated itself.

### 🔼 Input sample

| Parameter | Required | Type | Description | Example Value |
| --- | --- | --- | --- | --- |
| `urls` | **Yes** | array | Domains or URLs to analyze on MOZ. | `["zapier.com"]` |
| `include_authority` | No | boolean | Collect the full domain overview (DA, PA, Spam Score, backlinks, keywords, competitors). Default `true`. | `true` |
| `include_history` | No | boolean | Build a monthly Domain Authority history timeline (~15-45s per domain). Default `true`. | `true` |
| `minHealthScore` | No | integer (0–100) | Only push domains scoring at least this. Unscoreable domains are never filtered. Default `0`. | `50` |
| `maxConcurrency` | No | integer (1–10) | Domains analyzed in parallel. Default `3`. | `5` |
| `proxyConfiguration` | No | object | Optional; the Actor self-escalates through the proxy ladder automatically. | `{"useApifyProxy": true}` |

```json
{
  "urls": ["zapier.com", "notion.so"],
  "include_authority": true,
  "include_history": true,
  "minHealthScore": 50
}
```

**Common pitfall:** don't treat `total_backlinks`, `quality_backlinks`, `trust_score`, or `do_follow_backlinks_percentage` as measured MOZ data — they're formula-based estimates derived from `total_linking_root_domains` and `authority_score`, explicitly excluded from the SEO Health Score for that reason. Use `authority_score`, `page_authority_score`, `spam_score`, and `total_linking_root_domains` when you need genuinely scraped numbers.

### 🔽 Output sample

Output is one JSON row per domain, pushed to the run's default dataset and charged as one `row_result` event per domain (a `minHealthScore`-filtered domain is not charged).

```json
{
  "domain": "zapier.com",
  "authority_score": 72,
  "page_authority_score": 65,
  "spam_score": 3,
  "total_linking_root_domains": 12500,
  "domain_age_years": 14.2,
  "seoHealthScore": 78,
  "seoHealthGrade": "B",
  "scoreBreakdown": {
    "domain_authority": { "raw_value": 72, "normalized": 0.72, "base_weight": 0.3, "effective_weight": 0.3, "contribution": 21.6 },
    "page_authority": { "raw_value": 65, "normalized": 0.65, "base_weight": 0.2, "effective_weight": 0.2, "contribution": 13.0 }
  },
  "scoreBreakdownMissingComponents": [],
  "strengths": ["Strong domain authority (DA 72)"],
  "weaknesses": [],
  "total_backlinks": 222500,
  "authority_score_history": [
    { "date": "2026-06-01T00:00:00", "domain_authority": 71 }
  ]
}
```

### How do you filter and target specific domains?

**Score threshold, not a raw metric cutoff.** `minHealthScore` filters on the composite score rather than a single raw metric like `authority_score` alone — useful when "healthy" for your purposes means a balance of authority, spam cleanliness, and link-profile breadth rather than any one number in isolation.

**Turn off what you don't need.** `include_history` is the slowest part of a run (~15-45s per domain, since it queries the Wayback Machine's CDX index and fetches archived snapshots); turn it off for a fast batch triage pass, and re-run with it on only for the domains that pass your first filter.

**Read strengths/weaknesses, not just the number.** Two domains can land the same `seoHealthScore` for very different reasons — one strong on authority but thin on ranking keywords, another the reverse. `strengths`/`weaknesses` surfaces which real signal drove the score, so a triage decision isn't made on the number alone.

Three real examples:

```json
{ "urls": ["client-domain.com"], "include_authority": true, "include_history": true }
```

Full single-domain audit with historical trend, for a client report.

```json
{ "urls": ["prospect1.com", "prospect2.com", "prospect3.com"], "minHealthScore": 60, "include_history": false }
```

Fast multi-domain triage, history skipped, only domains scoring 60+ kept.

```json
{ "urls": ["competitor.com"], "include_authority": true, "include_history": false }
```

Competitor keyword and link-profile snapshot without the slower history build.

### ▶️ Want to try other scrapers?

| Scraper | What it extracts |
| --- | --- |
| Ahrefs Scraper — Competitor Comparison | Backlink and keyword competitor comparison |
| Google Search Autocomplete API | Keyword suggestion expansion |
| Instagram Engagement Estimator | Profile-level engagement rate |
| Amazon Product Scraper with Keyword Rank Tracking | Search-rank position tracking |

### How to extract SEO data programmatically

This Actor runs as a standard Apify Actor call — one API call in, structured JSON dataset out, using your Apify API token.

#### Python example

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("<YOUR_USERNAME>/moz-seo-health-scorer").call(run_input={
    "urls": ["zapier.com", "notion.so"],
    "minHealthScore": 50,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["domain"], item["seoHealthScore"], item["seoHealthGrade"])
```

#### Export to spreadsheets or CRM

Every dataset supports one-click CSV/Excel export from the Apify Console, plus dedicated dataset views (`seo_health`, `overview`, `authority_history`, `top_pages`, etc.) for exporting just the slice you need.

### Is it legal to use MOZ SEO Health Scorer?

This Actor scrapes MOZ's free, publicly accessible Domain Analysis tool — the same data any visitor can view without logging in — and RDAP domain registration data, which is a standard public lookup protocol. Domain and SEO metrics are business data, not personal data, so standard website Terms of Service considerations apply rather than privacy law; check MOZ's own Terms of Service for commercial-scale usage, and consult legal counsel for high-volume commercial applications.

### ❓ FAQ

#### Is the SEO Health Score comparable to MOZ's own metrics?

It's a separate composite this Actor computes, not a metric MOZ itself publishes — built only from real, independently-scraped signals (DA, PA, Spam Score, Linking Root Domains, domain age, ranking-keyword count) with a fully documented weighting. It complements MOZ's own Domain Authority score rather than replacing it.

#### Are total\_backlinks and quality\_backlinks real numbers from MOZ?

No — they're formula-based estimates derived from `total_linking_root_domains` and `authority_score` using a fixed multiplier, not values independently scraped from MOZ. This is exactly why they're excluded from the SEO Health Score calculation; treat them as directional estimates only.

#### How far back does the Domain Authority history go, and is all of it real?

Up to 33 months. Only months matched to a genuine archived MOZ snapshot (found via the Wayback Machine's CDX index) carry a verified historical value; unmatched months fill a bounded, deterministic estimate so the timeline has no gaps — check which months had real snapshots before treating the full history as measured data.

#### Why would a domain not get a SEO Health Score at all?

If `include_authority` is turned off, none of the score's real-signal inputs are collected, so `seoHealthScore` is `null` and `scoreBreakdownMissingComponents` lists every excluded component. Such a domain is never filtered out by `minHealthScore`, even if it's set above 0.

#### Does this need a MOZ account or API key?

No — it scrapes MOZ's free, publicly accessible Domain Analysis tool directly; no login or API key is required.

#### How does this compare to other domain-authority scrapers?

As observed on the Apify Store on 2026-07-26, `seo-scraper/moz-domain-authority-checker` extracts similar MOZ overview data but doesn't document a composite health score or a real-vs-estimated field distinction; this Actor's transparent `scoreBreakdown` and explicit real/estimated field labeling are not something that listing publishes.

#### Does this work with AI agent frameworks?

Yes — call it as a standard HTTP endpoint via the Apify API from any agent framework capable of making an API call; there's no MCP-specific integration for this Actor.

### Conclusion

MOZ SEO Health Scorer turns a domain into both the full MOZ overview and a transparent, reproducible composite health score — with an explicit, documented line between genuinely-scraped signals and formula-based estimates. It fits agency triage, link-building screening, and competitive SEO research that needs a defensible number, not a black box. Start a run from the Apify Console or the Apify API with your target domains to get your first SEO Health Score.

# Actor input Schema

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

List one or more domains or URLs to analyze on MOZ (e.g. `zapier.com`, `https://moz.com`). Add them one-by-one or paste a bulk list with **Bulk edit**.

## `include_authority` (type: `boolean`):

If enabled, collects the full domain overview: Domain Authority, Page Authority, Spam Score, backlink totals, top pages, linking domains, ranking & branded keywords, top questions and competitors.

## `include_history` (type: `boolean`):

If enabled, builds a monthly Domain Authority history timeline for each domain (verified against historical snapshots where available).

## `minHealthScore` (type: `integer`):

Only push domains whose computed SEO Health Score is at least this value. Set to 0 (default) to keep every domain. Domains for which no score can be computed (e.g. overview disabled) are never filtered out. Filtered domains are not charged.

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

How many domains to analyze in parallel (1–10). Default 3.

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

Proxy strategy. The scraper starts with NO proxy, then automatically falls back to a Datacenter proxy, and finally to a sticky Residential proxy if MOZ blocks the request — so you almost never need to change this.

## Actor input object example

```json
{
  "urls": [
    "zapier.com"
  ],
  "include_authority": true,
  "include_history": true,
  "minHealthScore": 0,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `seoHealth` (type: `string`):

Domain, composite SEO Health Score, letter grade, strengths/weaknesses and the transparent score breakdown.

## `overview` (type: `string`):

Full MOZ domain overview: Domain Authority, Page Authority, Spam Score, backlink totals and more.

## `authorityHistory` (type: `string`):

Monthly Domain Authority history timeline per domain.

## `backlinksHistory` (type: `string`):

Backlinks discovered/lost history per domain.

## `keywordsDistribution` (type: `string`):

Ranking-keyword position distribution per domain.

## `topPages` (type: `string`):

Top pages by links, with page authority.

## `topLinkingDomains` (type: `string`):

Top domains linking to the analyzed domain.

## `topRankingKeywords` (type: `string`):

Top ranking keywords and their rank.

## `topBrandedKeywords` (type: `string`):

Top branded keywords and search volume.

## `topQuestions` (type: `string`):

Top questions related to the domain and their relevance.

## `topCompetitors` (type: `string`):

Top search competitors and their visibility.

# 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": [
        "zapier.com"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("simpleapi/moz-scraper").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": ["zapier.com"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("simpleapi/moz-scraper").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": [
    "zapier.com"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call simpleapi/moz-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,simpleapi/moz-scraper"
        }
    }
}

```

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/dEbjNnS11xkZ2Oijg/builds/gs8yiiiJ3nbpatofX/openapi.json
