# Bulk Domain Rating Checker: Ahrefs DR, Authority & Backlinks (`quarra/bulk-domain-rating-checker`) Actor

Check Ahrefs Domain Rating (DR), a domain authority score, for thousands of domains or URLs in one run, with backlinks, referring domains and dofollow share on the same row. Duplicates are checked and charged once, invalid inputs are free.

- **URL**: https://apify.com/quarra/bulk-domain-rating-checker.md
- **Developed by:** [Quarra Labs](https://apify.com/quarra) (community)
- **Categories:** SEO tools, Lead generation
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.34 / 1,000 domain rating results

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

## Bulk Domain Rating Checker: Ahrefs DR, Authority & Backlinks

Check the Ahrefs Domain Rating (DR), a domain authority score from 0 to 100, of up to 10,000 domains or URLs in one
run, without an Ahrefs account. Each domain gets one row with its DR, its backlink count, its referring domains and the
dofollow share of both. Export as CSV, Excel or JSON, or read it through the Apify API.

DR is the score of Ahrefs. It is not Moz Domain Authority (DA), and the two numbers differ.

### Quick start

1. Paste your list in **Domains or URLs**, one per line: `stripe.com`, `https://www.notion.so/product`…
2. Click **Start**.
3. Open the **Output** tab: one row per domain.

Like any Apify Actor, it can be run through the Apify API, scheduled, and connected to webhooks, Make, Zapier, n8n or
Apify's MCP server for AI agents.

### What it is used for

- **Link building and outreach**: sort a list of prospect sites by DR and referring domains before writing to them.
- **Guest posts and sponsorships**: check that a site's DR is backed by real referring domains, not a handful of
  links.
- **Expired and dropped domains**: find the domains of a list that still have backlinks, and the ones with none.
- **Lead and company lists**: add an authority score to every company website in a CRM export.
- **Backlink checks at scale**: get the backlink count and the referring domains of a whole list in one export.
- **Monitoring**: schedule the same list every month and compare the `domainRating` of each `resultId`.

### Input

```json
{
  "domains": ["apify.com", "https://www.ahrefs.com/blog/", "WIKIPEDIA.ORG"]
}
```

- **Domains or URLs** (`domains`): bare domains or full links. `https://`, `www.`, the path, the port and capitals
  are removed: `https://www.Apify.com/store?x=1` is checked as `apify.com`. A subdomain other than `www`
  (`blog.example.com`) is checked as itself. International names are accepted (`bücher.de`). A text pasted with
  commas, bullets or several domains on one line is split, and a column copied from a spreadsheet keeps only the
  domain cells.
- **Max results** (`maxItems`): the run stops after this many charged rows.

The same domain written several ways is checked once and charged once; the run summary says how many duplicates it
removed.

### Output

One row per domain:

```json
{
  "type": "result",
  "status": "ok",
  "input": "https://www.ahrefs.com/blog/",
  "domain": "ahrefs.com",
  "domainRating": 91,
  "backlinks": 25009502,
  "referringDomains": 117079,
  "dofollowBacklinksPercent": 57,
  "dofollowReferringDomainsPercent": 85,
  "previousDomainRating": null,
  "drChange": null,
  "previousReferringDomains": null,
  "referringDomainsChange": null,
  "previousCheckedAt": null,
  "note": null,
  "errorCode": null,
  "error": null,
  "retryable": null,
  "resultId": "312defb16a95933d20af",
  "scrapedAt": "2026-10-28T14:02:36Z"
}
```

| Field | What it is |
|---|---|
| `domain` | The domain checked, cleaned (lower case, no `www.`, no path). |
| `input` | What you gave, as you wrote it. |
| `domainRating` | Ahrefs Domain Rating, 0 to 100. |
| `backlinks` | Links pointing to the domain and its subdomains. |
| `referringDomains` | Distinct websites linking to it. |
| `dofollowBacklinksPercent` | Share of those links that are dofollow, in percent. |
| `dofollowReferringDomainsPercent` | Share of the referring domains with at least one dofollow link, in percent. |
| `previousDomainRating`, `drChange` | DR at your previous check of the domain, and the change since (see **Follow DR changes**). |
| `note` | Why a value is missing, when one is. |
| `resultId` | Same id for the same domain in every run, to join runs together. |

Every row has the same columns, so a CSV export opens cleanly in a spreadsheet. The **Overview** table of the Output
tab shows them in that order.

A domain Ahrefs knows no backlinks for (new, unused, expired or misspelled) gets a normal row with `domainRating`,
`backlinks` and `referringDomains` at `0`: Ahrefs answered with a rating, so it is charged like any other. A 0 is
only delivered once Ahrefs has returned real figures for another site after it; if that does not happen before the run
stops, or if Ahrefs gives 0 even for well-known sites, those rows are free errors you can retry, and the run says so.

#### Rows that are never charged

- **No record**: a name Ahrefs returns no record for at all gets `"status": "error"`, `"errorCode": "not_found"`.
- **Not accepted**: a name Ahrefs does not take as a website gets `rejected_by_site`.
- **Not understood**: an e-mail address, a numeric address (`192.168.1.1`), `localhost` or a line that is not a
  website gets `invalid_input`, with `domain` at `null`.
- **Temporary failure**: `temporarily_unavailable` with `"retryable": true`. Run those domains again later.

To keep only the charged rows, filter on `"type": "result"`.

When a run stops early (**Max results**, **Maximum cost per run**, timeout), the domains it did not get to are named
in the run summary and all listed in the OUTPUT record (`notCheckedDomains`). They are not charged: run them again.

### What we measured

On 28 October 2026:

- `apify.com`: DR 83, 3,983,840 backlinks, 16,556 referring domains. `ahrefs.com`: DR 91, 25,009,502 backlinks,
  117,079 referring domains.
- `www.apify.com` gives the same DR as `apify.com`, but the link counts of the `www` subdomain alone (about a fifth of
  them). That is why `www.` is removed: you get the counts of the whole site.
- **No fake zeros**: Ahrefs' free tools show google.com and facebook.com with a DR of 100 and 0 backlinks. For such
  domains the row gives the DR (charged) with the counts at `null` and a note, never 0.

### Pricing

You pay per domain checked, one row with a Domain Rating.

| Apify plan | Per domain | Per 1,000 domains |
|---|---|---|
| Free | $0.00045 | $0.45 |
| Starter (Bronze) | $0.0004 | $0.40 |
| Scale (Silver) | $0.00036 | $0.36 |
| Business (Gold) and above | $0.00034 | $0.34 |

Plus $0.0005 per run start, per GB of memory (the Actor runs in 256 MB, so it is counted once). Check thousands of
domains in one run rather than one domain per run.

Never charged: duplicates, names Ahrefs has no record for or does not accept, inputs not understood, temporary
failures, domains not checked.
Set **Maximum cost per run** in the run options and the run stops before going over it, with the rows delivered so
far.

### Run it in production

The Actor is built for lists and for jobs that run again and again. Put the whole list in one run: the run start is
charged once, so one run of 500 domains costs less than 500 runs of one domain.

**Schedule it.** In Apify Console open **Schedules**, create a schedule with a cron time (`0 6 * * 1` is every Monday
at 06:00 UTC), and add this Actor with your list as input. A monthly list of prospects or clients, or a weekly list of
domains you watch, is the usual setup. Keep the same list: every domain has the same `resultId` in each run, so the
rows of two runs can be joined in a spreadsheet or a database.

**What it costs per month** (Free plan prices, every domain charged, run starts included; Gold prices in brackets):

| Job | Domains per month | Cost per month |
|---|---|---|
| 500 domains every week (4 runs) | 2,000 | $0.90 ($0.68) |
| 100 domains every day (30 runs) | 3,000 | $1.37 ($1.04) |
| 10,000 domains once a month | 10,000 | $4.50 ($3.40) |

Domains that are not charged (duplicates, unknown names, inputs not understood, temporary failures) lower these
figures. Set **Maximum cost per run** and the run stops before going over it.

**Call it from code.** Start a run and wait for the rows in one request (this call waits up to 300 seconds, so use it
for short lists):

```bash
curl -X POST "https://api.apify.com/v2/acts/quarra~bulk-domain-rating-checker/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"domains": ["apify.com", "ahrefs.com", "wikipedia.org"]}'
```

For a long list, start the run, wait for it to end, then read its dataset:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("quarra/bulk-domain-rating-checker").call(run_input={"domains": ["apify.com", "ahrefs.com"]})
rows = [r for r in client.dataset(run["defaultDatasetId"]).iterate_items() if r["type"] == "result"]
```

**Connect it.** Add a webhook on the event `ACTOR.RUN.SUCCEEDED` (Console, **Integrations** tab) to be called when a
run ends, then read the dataset of that run. Make, Zapier and n8n have Apify modules: run the Actor, then fetch the
dataset items and write them to Google Sheets, Airtable or your CRM. AI agents can call it through Apify's MCP
server.

**Run the missing ones again.** Put the dataset ID of the earlier run in **Retry the failed rows of an earlier run**
(`retryFrom`), with or without new domains. Only the domains that run could not check are checked again (rows with
`"retryable": true` and the domains in `notCheckedDomains`); a domain already delivered is not checked or charged
again, even if a scheduled task keeps the same `retryFrom`.

```json
{ "retryFrom": "<DATASET_ID_OF_THE_EARLIER_RUN>" }
```

**Follow DR changes.** With **Compare with the previous check** on (`trackChanges`, the default), each result also has
`previousDomainRating`, `drChange`, `previousReferringDomains`, `referringDomainsChange` and `previousCheckedAt`, from
the last run of your account that delivered that domain (`null` the first time). The history stays in a key-value
store named `domain-rating-history` in your account. These fields are free.

### Limits

- Up to 10,000 domains per run. Split a longer list into several runs.
- **Not every domain is measured in every run.** Ahrefs limits how many answers it gives in a short time. When it
  does, the domains it did not answer come back as free rows with `temporarily_unavailable` and `"retryable": true`,
  and the run summary says so. They are never charged and never filled with a made-up value. Measured on 29 October
  2026 on the same list of 100 domains: 53 measured before an update of the access to Ahrefs, 100 after; a run of
  1,000 domains then measured all 1,000 in 160 seconds. Plan for a second pass with `retryFrom` on long lists, and do
  not read a missing row as a DR of 0.
- A DR of 0 is only delivered when Ahrefs has answered for the domain and has returned real figures for another site
  in the same run.
- The run gives what Ahrefs' free tools publish: Domain Rating, backlinks, referring domains and the dofollow shares.
  It does not give Ahrefs Rank, organic traffic, URL Rating or the list of backlinks.
- Ahrefs updates its data on its own schedule; the same domain can show a slightly different DR or count from one day
  to the next.

### FAQ

**Do I need an Ahrefs account or API key?** No.

**Are duplicates charged?** No. `apify.com`, `https://www.apify.com/` and `APIFY.COM` in the same list are one domain,
checked and charged once.

**Why does a domain show DR 0?** Ahrefs has no backlinks on record for it: new, unused, expired or misspelled. It is
Ahrefs' answer for that domain, so the row is charged like any other.

**Is anything different on Apify's free plan?** No. Every feature works the same on every plan.

**Does the Actor send anything to Quarra?** Only when a run fails or runs out of time: the Actor name, its build, the
type of error, the line of our code where it happened, and the memory and time the run was given. Never your input,
your results or the run's data. A run that succeeds sends nothing.

**Can I schedule it?** Yes. See **Run it in production** above.

**I got fewer rows with a DR than domains. Why?** Some rows are free errors, not results. Check `status`: `not_found`
(no record at Ahrefs), `rejected_by_site`, `invalid_input` (not a website), or `temporarily_unavailable` (Ahrefs
limited the answers; run those again). Filter on `"type": "result"` for the charged rows. A run that stops early lists
the domains it did not reach in `notCheckedDomains`.

**Is this Moz Domain Authority?** No. It is the Ahrefs Domain Rating, a different score on the same 0 to 100 scale.

**Does it list the backlinks themselves?** No, it gives the count of backlinks and of referring domains for each
domain, not the list.

### Related Actors

- [Ahrefs Scraper](https://apify.com/quarra/ahrefs-scraper): DR, backlinks, traffic, keywords and SERP data.
- [Google Keyword Search Volume Checker](https://apify.com/quarra/google-keyword-search-volume): monthly search volume
  and CPC for lists of keywords.

Domain Rating by [Ahrefs](https://ahrefs.com/).

Questions or a domain that looks wrong: open an issue on the Actor's page with the domain and the run ID.

# Actor input Schema

## `domains` (type: `array`):

One per line, up to 10,000 per run. Bare domains or full URLs: https://, www., paths and capitals are removed, and the same domain written several ways is checked and charged once. A column pasted from a spreadsheet works too. Example: apify.com

## `maxItems` (type: `integer`):

The run stops after this many charged results (one per domain).

## `trackChanges` (type: `boolean`):

Adds previousDomainRating, drChange, previousReferringDomains, referringDomainsChange and previousCheckedAt to each result, from the last time your account checked that domain with this Actor. The history is kept in a key-value store named domain-rating-history in your account. Made for scheduled runs; free.

## `retryFrom` (type: `string`):

Dataset ID of an earlier run of this Actor. Only the domains that run could not check are checked again (rows with retryable: true, and the domains it did not get to). Each run notes them in the key-value store domain-rating-history of your account, so a domain already delivered is never charged twice, even if a scheduled task keeps the same retryFrom. Works with or without 'domains'.

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

Connection. Keep the default (automatic). Costs are included in the price.

## Actor input object example

```json
{
  "domains": [
    "apify.com",
    "ahrefs.com",
    "wikipedia.org"
  ],
  "maxItems": 10000,
  "trackChanges": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

A table with one row per domain: DR, backlinks, referring domains, dofollow share.

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

Every record with all its fields, free error records included.

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

Counts, duplicates removed, why the run stopped, domains not checked, inputs not understood, and per domain: results, errors, note.

# 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 = {
    "domains": [
        "apify.com",
        "ahrefs.com",
        "wikipedia.org"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("quarra/bulk-domain-rating-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 = {
    "domains": [
        "apify.com",
        "ahrefs.com",
        "wikipedia.org",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("quarra/bulk-domain-rating-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 '{
  "domains": [
    "apify.com",
    "ahrefs.com",
    "wikipedia.org"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call quarra/bulk-domain-rating-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,quarra/bulk-domain-rating-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/kL8jMXr6gAgmbCO5O/builds/tJpVv7DdJYqhYG1yO/openapi.json
