# Ahrefs Scraper: DR, Backlinks, Traffic, Keywords & SERP (`quarra/ahrefs-scraper`) Actor

Ahrefs SEO data in bulk, no Ahrefs account: Domain Rating, backlinks and top backlinks, organic traffic and its value, keyword ideas, keyword difficulty, SERP top 10 with metrics, rank check, AI Overviews and AI Mode mentions, broken backlinks.

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

## Pricing

from $3.80 / 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.
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

## Ahrefs Scraper: DR, Backlinks, Traffic, Keywords & SERP

Get Ahrefs SEO data in bulk, without an Ahrefs account or subscription: Domain Rating, backlink counts and top
backlinks, organic traffic, keyword difficulty, keyword ideas, the Google results page with Ahrefs metrics for each
result, rank checks, broken backlinks and AI search visibility. Paste a list of websites or keywords, pick the tools,
and get one clean record per tool and target. Export as JSON, CSV or Excel, or read it through the Apify API.

### Quick start

1. Pick one or more **Tools** (Domain Rating is selected by default).
2. Paste **Websites** (`stripe.com`, `https://www.notion.so/product`…) and/or **Keywords** (`best crm`).
3. Click **Start** and read the results in the run's **Output** tab.

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 1,000 prospect sites by Domain Rating in one run.
- **Competitor research**: traffic, top pages, top countries, top keywords and best backlinks of any site.
- **Keyword research**: difficulty, ideas, questions, and who ranks on page one with their DR and backlinks.
- **Rank tracking**: the position of your site for a list of keywords, by country.
- **AI search visibility**: how often a brand is cited in Google AI Overviews and AI Mode, and on which topics.

### Tools

| Tool | Input | What you get |
|---|---|---|
| `domainRating` | websites | Domain Rating, backlinks, referring domains, dofollow shares |
| `backlinks` | websites | the same counts plus the top 20 backlinks (source URL, target, anchor, title, DR) |
| `traffic` | websites | monthly organic traffic and its value in USD, 6-month history, top pages, countries, keywords |
| `brokenLinks` | websites | broken backlinks pointing to the site (source, broken target, anchor) and their total |
| `aiOverviews`, `aiMode` | websites | mentions in Google AI answers, trend, top topics, top cited domains and pages, timelines |
| `keywordDifficulty` | keywords | KD (0–100), referring domains needed for the top 10, page one with metrics, AI Overview text |
| `keywordIdeas` | keywords | up to 20 related keywords and 20 questions, with difficulty and volume range, and the totals |
| `serp` | keywords | page one of Google with DR, UR, backlinks, traffic and top keyword of each result |
| `rankCheck` | keywords + **Rank domain** | the position and ranking URL of your domain, with page one |

Each tool and target pair is one result. Two tools on 50 websites = up to 100 results. One run takes up to 5,000
lookups (for example 1,000 websites with up to 5 website tools: raise **Max results** above its default of 1,000 for
that); split bigger jobs into several runs.

### Inputs

- **Tools**: one or more of the tools above.
- **Websites**: domains or full links, up to 1,000. A link is reduced to its host (`https://www.apify.com/store` reads
  `www.apify.com`); the same target given more than once is read once. International names work in either form
  (`bücher.de` and `xn--bcher-kva.de` are one target). Ahrefs treats `www.apify.com` and `apify.com` as two different
  targets with their own counts (824,905 and 4,036,720 backlinks on 19 October 2026), so give the one you mean. An
  e-mail address is refused, with the domain to give instead.
- **Check the spelling of each website**: Ahrefs answers a domain it does not know (a typo, a made-up name) like a
  real site with no links: Domain Rating 0, 0 backlinks, 0 traffic. That record is a real answer and is charged like
  any other; a keyword Ahrefs does not know gives a free `not_found` record instead.
- **Keywords**: up to 1,000, for the keyword tools. Ahrefs reads the first 200 characters of a keyword.
- **Country**: two-letter code for the keyword tools (default `us`; `uk` is read as `gb`). The 188 countries of
  Ahrefs' keyword database are accepted; any other code stops the run before anything is looked up.
- **Rank domain**: the site whose position `rankCheck` looks for (`www.` or not, it is the same site; any other
  subdomain is a site of its own: `apify.com` does not match pages on `blog.apify.com`, give `blog.apify.com` for them).
- **Backlinks mode**: `subdomains` (default, the whole domain) or `exact` (only the exact URL you give, path
  included). In `exact`, `http://` and `https://` give the same numbers and are read once, but a trailing slash makes
  another URL for Ahrefs: `https://apify.com/store` had 3,410 backlinks and `https://apify.com/store/` 13.
- **Max results**: counted exactly.

```json
{
  "tools": ["domainRating", "keywordDifficulty"],
  "websites": ["apify.com", "notion.so"],
  "keywords": ["web scraping"],
  "country": "us"
}
```

### Output

One record per tool and target. Two shortened examples from a real run:

```json
{
  "type": "result",
  "status": "ok",
  "tool": "domainRating",
  "input": "notion.so",
  "target": "notion.so",
  "domainRating": 92,
  "backlinks": 24207779,
  "referringDomains": 140379,
  "dofollowBacklinksPercent": 95,
  "dofollowReferringDomainsPercent": 83,
  "resultId": "9bd8d7366b2fc34178c1",
  "scrapedAt": "2026-10-18T20:42:56Z"
}
```

```json
{
  "type": "result",
  "status": "ok",
  "tool": "keywordDifficulty",
  "input": "seo tools",
  "country": "us",
  "keywordDifficulty": 78,
  "referringDomainsToRankTop10": 310,
  "serpResults": [
    {"position": 2, "title": "100% Free SEO Tools - SmallSEOTools.com", "url": "https://smallseotools.com/",
     "domainRating": 81, "urlRating": 23, "backlinks": 77121, "referringDomains": 4715, "traffic": 69210,
     "topKeyword": "seo tools", "topKeywordVolume": 319000}
  ],
  "aiOverviewText": "Top SEO tools are categorized by their primary function…"
}
```

- Every record has the same fields, error records included; a field a tool does not fill is `null`, never missing.
- `status`: `ok` (delivered, charged) or `error` (free). `errorCode` and `error` say why, `retryable` says whether a
  later run may work: `invalid_input` (not a website, or an input the run cannot use), `not_found` (Ahrefs has no
  data for that keyword or site, including an answer where every value is empty), `rejected_by_site`,
  `temporarily_unavailable`.
- `resultId` is stable for the same tool, target and options: use it to deduplicate between runs.

The run summary (counts, why it stopped, notes on your input) is the `OUTPUT` record of the run's key-value store.

### What we measured

On Apify (256 MB):

- **Default input** (18 October 2026; 2 Domain Ratings and 1 keyword difficulty): 3 results in 3.8 seconds.
- **All ten tools at once** (19 October 2026) on 8 large sites and 3 keywords, one of them made up: 60 lookups, 55
  results in 100 seconds. The 5 lookups left without a result each got a free error record: four lookups of the
  made-up keyword, which Ahrefs has no data for, and the broken backlinks of google.com, which Ahrefs answered with
  a server error.
- **No fake zeros**: Ahrefs' free tools show google.com with a Domain Rating of 100 and 0 backlinks. When Ahrefs
  gives no counts for a domain, `domainRating` gives them as `null` with a note and `backlinks` a free record to
  retry, never 0.
- **Duplicates**: `apify.com` and `APIFY.COM` in the same list are read and charged once.

### Pricing

You pay per result: one tool on one website or keyword.

| Apify plan | Per result | Per 1,000 results |
|---|---|---|
| Free | $0.009 | $9.00 |
| Starter (Bronze) | $0.0048 | $4.80 |
| Scale (Silver) | $0.0043 | $4.30 |
| Business (Gold) and above | $0.0038 | $3.80 |

Plus $0.001 per run start (memory is capped at 256 MB, so the start is always counted once). The Free
plan gets every tool.

Never charged: error records (invalid input, no data, a temporary failure), records where Ahrefs returns no value at
all, and repeats. Set **Maximum cost per run** in the run options and the run stops before going over it, with the
results delivered so far.

### Limits

- **Keyword ideas** give a difficulty label and a volume range (`MoreThanOneThousand`…), as Ahrefs' free tool does, not
  exact search volumes.
- **Top backlinks** are the 20 best Ahrefs shows for free; the backlink and referring domain counts are the full ones.
- **Very large domains** (google.com, facebook.com…): Ahrefs can answer for a while with a Domain Rating but no
  backlink counts, then with the counts a few minutes later. The run asks again before giving up. If the counts still
  are not there, `domainRating` gives the Domain Rating with the counts at `null` and a note (charged: the rating is
  there), and `backlinks` gives a free `temporarily_unavailable` record to retry. Broken links of such domains can take
  too long for Ahrefs to answer: free `temporarily_unavailable` record.
- **`domainRating` and `backlinks` can give different totals for a very large domain** (amazon.com: about 2.0 billion
  and 2.4 billion backlinks): each comes from its own Ahrefs page, as Ahrefs shows them. For most sites they match.
- **Backlinks pace**: Ahrefs limits how fast its backlinks overview can be read: depending on the connection, a few
  websites per minute, or a few dozen in a row followed by a pause of several minutes. The run waits for Ahrefs (up to
  5 minutes without an answer), then gives the websites left a free `temporarily_unavailable` record to run again
  later. For a long list, `domainRating` gives the same counts for most sites without this limit (except the very large
  domains it has to ask again, see above); keep `backlinks` for
  the sites whose top backlinks you need.
- **Organic traffic**: `organicTrafficMonthly` is the "Organic traffic" figure of Ahrefs' Traffic Checker (its latest
  monthly estimate) and `trafficHistory` the monthly points of its chart; on a site whose traffic is changing fast,
  the latest estimate can be below or above every month of the history.
- Data is what Ahrefs publishes at the time of the run; Ahrefs updates it on its own schedule.
- If Ahrefs cannot be reached for a while, the affected inputs get free `temporarily_unavailable` records; nothing is
  charged for them.

# Actor input Schema

## `tools` (type: `array`):

What to get. Several tools can run together: one record per tool and per website or keyword.

## `websites` (type: `array`):

Domains or URLs, for Domain Rating, backlinks, traffic, AI Overviews, AI Mode and broken backlinks. Example: apify.com

## `keywords` (type: `array`):

For keyword ideas, keyword difficulty, SERP and rank check.

## `country` (type: `string`):

Two-letter country code for the keyword tools (us, gb, de, fr, in…). The 188 countries of Ahrefs' keyword database are accepted.

## `rankDomain` (type: `string`):

The website whose position you want for each keyword. Needed only by the rank check tool. Example: apify.com

## `backlinksMode` (type: `string`):

Whole site (all subdomains) or only the exact URL given, path included (a trailing slash makes another URL).

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

The run stops after this many results (each record is one result).

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

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

## Actor input object example

```json
{
  "tools": [
    "domainRating",
    "keywordDifficulty"
  ],
  "websites": [
    "apify.com",
    "ahrefs.com"
  ],
  "keywords": [
    "web scraping"
  ],
  "country": "us",
  "backlinksMode": "subdomains",
  "maxItems": 1000,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Every result with all its fields, and free error records.

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

A table with one row per result.

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

Results per input, notes, why the run stopped, and errors.

# 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 = {
    "tools": [
        "domainRating",
        "keywordDifficulty"
    ],
    "websites": [
        "apify.com",
        "ahrefs.com"
    ],
    "keywords": [
        "web scraping"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("quarra/ahrefs-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 = {
    "tools": [
        "domainRating",
        "keywordDifficulty",
    ],
    "websites": [
        "apify.com",
        "ahrefs.com",
    ],
    "keywords": ["web scraping"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("quarra/ahrefs-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 '{
  "tools": [
    "domainRating",
    "keywordDifficulty"
  ],
  "websites": [
    "apify.com",
    "ahrefs.com"
  ],
  "keywords": [
    "web scraping"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call quarra/ahrefs-scraper --silent --output-dataset

```

## MCP server setup

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