# Backlink Checker: Referring Domains & Spam Score (`meridianlabs/backlink-checker`) Actor

Backlink checker and backlinks API: full backlink lists, referring domains, domain rank, dofollow share and spam score for up to 1,000 domains or URLs per run. $0.03 per domain + $4 per 1,000 backlinks; failed lookups are free.

- **URL**: https://apify.com/meridianlabs/backlink-checker.md
- **Developed by:** [Meridian Labs](https://apify.com/meridianlabs) (community)
- **Categories:** SEO tools, Marketing, Developer tools
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $30.00 / 1,000 domain summaries

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

**Backlink Checker** returns the **full backlink profile of any domain or page**: a summary per target (**domain rank, backlinks, referring domains, dofollow share, spam score**, broken backlinks, first seen) and, if you want them, **every backlink** (linking page, anchor text, dofollow, domain rank, spam score, first and last seen) or **every referring domain**, strongest first. Check **up to 1,000 domains per run**, and get up to **20,000 backlinks per domain**: real lists, not a capped sample. The input form is pre-filled, so the easiest way to try it is to click **Start**. One domain summary costs $0.03.

![Backlink Checker result: domain rank, backlinks, referring domains, dofollow share and spam score for six domains, from a real run](https://raw.githubusercontent.com/leewilliam200/meridianlabs-apify-assets/main/backlink-checker/backlink-checker-summary-result.jpg)

It's built for **SEO specialists and link builders**, **agencies running backlink audits**, **domain investors** vetting a domain's link profile, and **AI agents** that need backlink data through an API, without a monthly SEO-suite subscription.

### What backlink data do you get?

**One summary row per domain or URL** (`rowType: "summary"`):

- 🏆 **Domain rank** (`rank`, 0–1000): an authority score computed from the link graph, PageRank-style. Roughly: 300+ is an established site, 600+ a major one.
- 🔗 **Backlinks** (`backlinks`) and **referring domains** (`referringDomains`, `referringMainDomains`): how many live links point to the target, and from how many sites.
- ✅ **Dofollow share** (`dofollowReferringDomainsPct`): the share of linking domains that pass at least one dofollow link.
- 🚩 **Spam score** (`spamScore`, 0–100): how spammy the target's backlinks look on average.
- 🧱 **Referring IPs and subnets**, **broken backlinks**, **first seen** and the target's own spam score (in runs of 1–4 targets; see the FAQ).

**Then, if you choose a list mode:**

- 📄 **Backlinks mode**: one row per backlink (`rowType: "backlink"`): linking page URL and title, **anchor text** (or **image alt text** for image links), link type, **dofollow**, rel attributes, **domain rank** and page rank of the linking site, spam score, target URL, first and last seen, broken or lost flags.
- 🌐 **Referring domains mode**: one row per linking domain (`rowType: "referring_domain"`): domain, domain rank, backlinks to your target, linking pages (and how many are dofollow), spam score, first seen, lost date.

Lists come **strongest first** (backlinks by the link's own rank, referring domains by domain rank), so `maxRowsPerTarget: 100` gives you the 100 best.

### Why use this backlink checker?

- 📚 **Complete lists, not samples.** Ask for 5,000 backlinks and you get 5,000 when the index has them (up to 20,000 per target). In our September 2026 test, every request returned exactly the rows asked for.
- 🧮 **Bulk domain checks.** Paste up to 1,000 domains and get rank, backlinks, referring domains, dofollow share and spam score for each: ideal for vetting link prospects, guest-post sites or expired domains.
- 🎯 **Filters that save money.** Dofollow only, minimum domain rank and a spam-score ceiling are applied by the data provider, so you pay only for the rows you want.
- 💸 **Fair billing.** You pay per domain checked and per row returned. Failed lookups, invalid entries and domains that don't exist are free, and the run stops exactly at your maximum spending limit.
- 🤖 **AI-agent ready.** Documented output schema, three table views and stable field names. It works from the Apify API, integrations (Make, Zapier, n8n, Google Sheets) and MCP clients.

### How do I check the backlinks of a website?

1. Enter one or more **domains** (`example.com`, includes subdomains) or **page URLs** (`https://example.com/page`), one per line.
2. Choose **what to return**: *Summary only*, *Backlinks* or *Referring domains*.
3. For the lists, set **Max rows per target** (default 1,000) and any filters: **Dofollow links only**, **Minimum domain rank**, **Exclude spam score above**.
4. Click **Start**. Open the **Summary per target**, **Backlinks** or **Referring domains** view on the Output tab, or export everything as JSON, CSV or Excel.

![Backlink Checker input form: a list of domains, what to return (summary, backlinks or referring domains), max rows per target and the dofollow, domain rank and spam filters](https://raw.githubusercontent.com/leewilliam200/meridianlabs-apify-assets/main/backlink-checker/backlink-checker-input-form.png)

#### How do I find the referring domains of a competitor?

Pick **Referring domains**, enter the competitor's domain and set **Max rows per target** (e.g. 500). Add **Dofollow links only** and a **Minimum domain rank** of 300 to keep only the linking sites worth approaching. Each row is one site linking to them, with how many links and pages it has.

#### How do I check a list of domains for link building?

Keep **Summary only** and paste the list (up to 1,000 domains). You get one row per domain with domain rank, referring domains, dofollow share and spam score: sort by rank, drop anything with a spam score above ~30, and you have a shortlist. 100 domains cost $3.

### How much does it cost to check backlinks?

**$0.03 per domain or URL checked, plus $0.004 per backlink or referring-domain row ($4 per 1,000 rows). Failed lookups are free.**

| Event | Price | Charged when |
|---|---|---|
| Domain summary | $0.03 per target | The lookup for a domain or URL answered, including a clean "no backlinks found" for a site that exists: the lookup ran and answered. |
| Backlink or referring-domain row | $0.004 per row | Each row saved in *Backlinks* or *Referring domains* mode. |

- 🆓 **Free:** errors, invalid entries, **domains that don't exist** (no DNS record and nothing in the index), and targets or rows skipped because the run reached your **maximum spending limit** or its **time limit**.
- **Examples:** 1 domain summary = $0.03. 100 domains, summary only = $3. 1 domain with its top 1,000 backlinks = $4.03. 5 competitors × 200 referring domains = $4.15.
- **Free to try:** Apify's free plan includes $5 of platform usage every month: about **160 domain summaries**, or one domain with about **1,200 backlinks**. Platform usage is included in the price.
- Set a **maximum cost per run** in the run options: the Actor only fetches rows it can charge for and stops exactly there. Targets it didn't reach are listed as `skipped` and not charged.

### Input

| Field | What it does |
|---|---|
| `targets` | Domains or page URLs, one per line (up to 1,000). `https://www.example.com/` counts as the domain `example.com` (subdomains included); a URL with a path checks that page only. Duplicates are removed. |
| `mode` | `summary` (default), `backlinks` or `referring_domains`. |
| `maxRowsPerTarget` | List modes: most rows per target, strongest first (1–20,000; default 1,000). |
| `dofollowOnly` | Backlinks: dofollow links only. Referring domains: only domains with at least one dofollow link. |
| `minDomainRank` | Skip linking sites ranked below this (0–1000). |
| `excludeSpamAbove` | Skip rows with a spam score above this (0–100). Empty = keep everything. |
| `failOnErrors` | Mark the run failed if any lookup errors (for schedules and monitoring). Failed lookups are still free. |

Example:

```json
{
  "targets": ["hubspot.com", "heathceramics.com"],
  "mode": "backlinks",
  "maxRowsPerTarget": 200,
  "dofollowOnly": true,
  "minDomainRank": 300,
  "excludeSpamAbove": 30
}
```

### Output example

Data source: the DataForSEO Backlinks API (DataForSEO's own web crawler and live link index), stated on every row as `dataSource`.

The **Backlinks** view on the Output tab (real run: heathceramics.com, dofollow only, domain rank ≥ 100, spam score ≤ 30):

![Backlink Checker Backlinks view in Apify Console: linking page, anchor, link type, dofollow, domain rank, page rank, spam score, target URL, page title, first and last seen per backlink](https://raw.githubusercontent.com/leewilliam200/meridianlabs-apify-assets/main/backlink-checker/backlink-checker-backlinks-view.png)

A summary row (real output, September 2026, trimmed):

```json
{
  "rowType": "summary",
  "target": "hubspot.com",
  "status": "ok",
  "rank": 680,
  "backlinks": 29299534,
  "referringDomains": 390354,
  "referringMainDomains": 338138,
  "dofollowReferringDomainsPct": 89.4,
  "spamScore": 5,
  "referringIps": 131878,
  "referringSubnets": 57582,
  "brokenBacklinks": 266233,
  "firstSeen": "2019-01-15T22:57:10Z",
  "metricsSource": "summary",
  "charged": true,
  "dataSource": "DataForSEO Backlinks API: DataForSEO's own web crawler and live link index. Rank (0-1000) and spam score (0-100) are DataForSEO's metrics."
}
```

A backlink row (real output, filtered to dofollow, domain rank ≥ 100, spam score ≤ 30):

```json
{
  "rowType": "backlink",
  "target": "heathceramics.com",
  "sourceUrl": "https://www.pinterest.com/heathceramics/",
  "sourceDomain": "www.pinterest.com",
  "anchor": "heathceramics.com; Opens a new tab",
  "altText": null,
  "linkType": "anchor",
  "dofollow": true,
  "rel": [
    "noopener",
    "noreferrer"
  ],
  "domainRank": 877,
  "pageRank": 416,
  "spamScore": 0,
  "targetUrl": "http://www.heathceramics.com/",
  "firstSeen": "2025-09-26T13:56:58Z",
  "lastSeen": "2026-09-18T15:22:48Z",
  "isBroken": false
}
```

Summary `status` is one of:

- `ok`: backlinks found.
- `no_backlinks`: the site exists but the index has no links to it. Charged: the lookup ran and answered.
- `error`: the lookup failed, the entry isn't a valid domain or URL, or the domain doesn't exist (`DOMAIN_NOT_FOUND`). Not charged.
- `skipped`: not checked because the run hit its spending, time or data-cost limit. Not charged.

In the list modes, each summary row also says how many rows you got (`rowsReturned`), how many match your filters in the index (`matchingRows`) and, if you got fewer, why (`rowsLimitedBy`). For each target, its list rows come first and the summary row last.

### How to read the numbers

- **Domain rank is 0–1000**, not 0–100: it's computed from the whole link graph, and a few hundred points separate a small shop (200–350) from a major publisher (650+).
- **Referring domains beat backlinks.** One site can link thousands of times (sidebars, footers); `referringDomains` counts sites, `referringMainDomains` counts root domains.
- **Image links have no anchor text.** Their `anchor` is empty and `altText` holds the image's alt text; redirects and canonicals (`linkType`) have neither.
- **Counts differ between tools.** Every backlink index crawls differently; compare trends and rankings within one source rather than exact counts across sources.

### How do I monitor backlinks every month?

1. Fill in the input (your domains, *Referring domains* mode, a row limit) and click **Save as a new task**.
2. Open **Schedules** → **Create new**, pick the task and choose **monthly**.
3. Compare months on `firstSeen` (new linking domains) and `lostDate` (lost ones), or send the dataset to a spreadsheet (next section).

### How do I send backlink data to Google Sheets, Make, Zapier, n8n or an AI agent?

- **Google Sheets and Drive:** on the Actor's or task's **Integrations** tab, add the Google Drive integration, or use Make, Zapier or n8n with a Google Sheets "add rows" step.
- **Make, Zapier and n8n:** each has an official Apify app or node. Trigger on "Actor run finished", then get the dataset items; ask for the `summary`, `backlinks` or `referringDomains` view to get those table columns.
- **Webhooks:** Integrations → **HTTP webhook** on "Run succeeded" sends the run details to your URL.
- **AI agents (MCP):** add `https://mcp.apify.com?actors=meridianlabs/backlink-checker` to your MCP client (Claude, Cursor, VS Code and others).
- **Code:** see the Python example in the FAQ.

### Limitations

- **Summaries for 5+ targets are bulk metrics:** rank, backlinks, referring domains (root and nofollow counts), dofollow share and spam score. Referring IPs/subnets, broken backlinks, crawled pages and first seen come from the detailed summary, used for runs of 1–4 targets. In list modes every target still gets its full list.
- **Up to 20,000 rows per target** per run (the index pages by offset up to 20,000).
- **Filters apply to the list rows**; the summary row always describes the whole profile.

### FAQ

#### Where does the backlink data come from?

From the **DataForSEO Backlinks API**, which runs its own web crawler and keeps a live index of about 1.8 trillion backlinks across 185 billion pages (September 2026). Domain rank and spam score are DataForSEO's metrics. This Actor queries the index live on every run; it isn't a scraper of any SEO tool's website, so it doesn't break when a website changes.

#### Why does a run of 1–4 domains show more summary fields than a bigger run?

Runs of 1–4 targets use one detailed summary lookup per target. From 5 targets the Actor switches to bulk lookups that return the core metrics for up to 1,000 domains at once, which is what keeps big domain lists fast. The price is the same either way.

#### Can I use it with the API, AI agents or MCP?

Yes. Run it through the Apify API or client libraries, schedule it, connect it to Make, Zapier, n8n or Google Sheets, or call it from MCP clients.

Python (`pip install apify-client`):

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("meridianlabs/backlink-checker").call(run_input={
    "targets": ["hubspot.com"], "mode": "referring_domains", "maxRowsPerTarget": 100, "dofollowOnly": True,
})
for row in client.dataset(run.default_dataset_id).iterate_items():
    if row["rowType"] == "referring_domain":
        print(row["referringDomain"], row["domainRank"], row["backlinks"])
```

#### Does it collect personal data?

No personal data is collected on purpose. Rows contain public web-page URLs, titles and link text from pages that link to your target, as published by those sites. The Actor doesn't store anything in your account beyond the run's own dataset.

#### What happens if a run times out or restarts?

If a run approaches its timeout, the Actor stops starting new lookups: targets it didn't reach are listed as `skipped` (not charged), and a target cut short keeps the rows already delivered, with `rowsLimitedBy: "RUN_TIME_LIMIT"`. If the platform restarts a run, it picks up where it left off without charging twice.

### More from Meridian Labs

- **[Keyword Search Volume & CPC API + Google Trends](https://apify.com/meridianlabs/keyword-search-volume)**: monthly search volume, CPC, competition, difficulty and intent for keyword lists, plus a Google Trends summary per keyword. From $3 per 1,000 keywords.
- **[Google Trends Scraper & API](https://apify.com/meridianlabs/google-trends-scraper)**: interest over time, by region and rising related searches for hundreds of keywords, as a maintained pytrends alternative. $5 per 1,000 keyword lookups.
- **[Greenhouse, Lever & Ashby Jobs Scraper](https://apify.com/meridianlabs/greenhouse-lever-ashby-jobs-scraper)**: open jobs from companies on six hiring systems, with salary normalised to min, max, currency and period. $2 per 1,000 jobs.

### Support

Something looks wrong, or you need a field we don't return? Open an issue on the **Issues** tab with the input you used. We read every one.

If this saved you time, a rating helps others find it; if something's off, open an issue and we'll fix it fast.

# Actor input Schema

## `targets` (type: `array`):

Domains (example.com, includes subdomains) or page URLs (https://example.com/page), one per line, up to 1,000 per run. Duplicates are removed.

## `mode` (type: `string`):

Summary is one row per target. The other two modes add one row per backlink or per referring domain, strongest first (backlinks by link rank, referring domains by domain rank).

## `maxRowsPerTarget` (type: `integer`):

Backlinks / referring domains mode only: the most rows to return for each target (strongest first). Your cost cap: rows are charged individually.

## `dofollowOnly` (type: `boolean`):

Backlinks mode: only dofollow links. Referring domains mode: only domains with at least one dofollow link to the target.

## `minDomainRank` (type: `integer`):

Skip linking domains ranked below this. Rank is DataForSEO's 0-1000 authority score (roughly: 300+ = an established site, 600+ = a major one).

## `excludeSpamAbove` (type: `integer`):

Optional. Leave empty to keep everything; 30 is a common cut-off for link audits.

## `failOnErrors` (type: `boolean`):

Useful for schedules and monitoring: the run is marked failed if any target errors. Failed lookups are still not charged.

## Actor input object example

```json
{
  "targets": [
    "hubspot.com"
  ],
  "mode": "summary",
  "maxRowsPerTarget": 1000,
  "dofollowOnly": false,
  "minDomainRank": 0,
  "failOnErrors": false
}
```

# Actor output Schema

## `summary` (type: `string`):

One row per target: rank, backlinks, referring domains, dofollow share, spam score (dataset view 'summary').

## `backlinks` (type: `string`):

Backlinks mode: one row per backlink (dataset view 'backlinks').

## `referringDomains` (type: `string`):

Referring domains mode: one row per linking domain (dataset view 'referringDomains').

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

Every field of every row.

# 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 = {
    "targets": [
        "hubspot.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("meridianlabs/backlink-checker").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 = { "targets": ["hubspot.com"] }

# Run the Actor and wait for it to finish
run = client.actor("meridianlabs/backlink-checker").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 '{
  "targets": [
    "hubspot.com"
  ]
}' |
apify call meridianlabs/backlink-checker --silent --output-dataset

```

## MCP server setup

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

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/JthTGcZd3ZHLrKOl6/builds/SgUQppNbYcoPCBinm/openapi.json
