# Ahrefs Scraper (`mlg14/ahrefs-scraper`) Actor

Collect public website rankings, estimated search traffic, Domain Rating, linking websites, keywords, and competitors from AhrefsTop. Browse up to 1,000 ranked websites or look up public domain summaries.

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

## Pricing

$1.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

## Ahrefs Scraper

Scrape public Ahrefs website rankings and domain summaries, then export structured results to JSON, CSV, or a spreadsheet. This Ahrefs data collector covers ranked and trending websites, estimated search traffic, Domain Rating, linking websites, leading countries, keywords, and competitors where a public domain page exists.

The actor reads public ranking and detail pages. It does not require a subscription or a login. A ranking run can return up to 1,000 websites for a country and category combination. Detail enrichment adds a second public page per website and supplies the deeper metrics shown in the output example below.

### What data can you extract from Ahrefs?

The default result is one website per dataset item. Ranked rows are ready for filtering and sorting. When **Include domain details** is enabled, each row also contains the public information from that website's detail page. For a short list of known domains, choose a domain search type and supply the domains directly.

| Field | Description | Example |
|---|---|---|
| `searchType` | Selected search type for the record | `top_websites` |
| `rankingMode` | Main ranking or trending list | `ranking` |
| `rank` | Position in the selected public ranking | `1` |
| `rankChange` | Movement since the previous ranking period; a negative number means a fall | `12` |
| `website` | Ranked domain | `wikipedia.org` |
| `websiteUrl` | Website home URL | `https://wikipedia.org` |
| `detailUrl` | Public domain profile URL | `https://ahrefstop.com/websites/wikipedia.org` |
| `category` | Category displayed in the ranking | `Reference` |
| `searchTraffic` | Estimated monthly organic search visits | `4000000000` |
| `trafficDelta` | Month over month change in estimated visits | `85600000` |
| `countryFilter` | Country page used for the ranking | `worldwide` |
| `categoryFilter` | Category page used for the ranking | `all` |
| `domain` | Domain on a detail result | `wikipedia.org` |
| `name` | Website name displayed on the public profile | `Wikipedia` |
| `description` | Public site description, when present | A short site summary |
| `metricDate` | Month of the displayed estimates | `August 2026` |
| `globalRank` | Worldwide search traffic rank | `1` |
| `countryRank` | Rank in the profile's highlighted country | `1` |
| `categoryRank` | Rank in the profile's category | `1` |
| `trafficValueUsd` | Estimated monthly value of organic traffic in US dollars | `549600000` |
| `trafficValueDeltaUsd` | Monthly change in estimated traffic value | `27500000` |
| `keywords` | Number of ranking keywords shown as a rounded total | `3200` |
| `domainRating` | Public Domain Rating score | `97` |
| `refdomains` | Public count of linking websites | `4000000` |
| `refdomainsDelta` | Monthly change in linking websites | `15200` |
| `topCountries` | Leading country codes, visit estimates, changes, and shares | Five country objects |
| `topKeywords` | Public keywords with volume, traffic, and position | Five keyword objects |
| `competitors` | Competing sites with estimated traffic and page counts | Five competitor objects |
| `similarlyRanked` | Nearby sites in the global ranking | Five website objects |

Counts written as compact labels on the source pages are converted into numbers. For example, a displayed value of `4B` becomes `4000000000`. The resulting number preserves the displayed estimate's precision; it does not imply that the source reported an exact visit count. The country traffic values come from structured data included on the public detail page and can be more precise than the large summary label.

The field `refdomains` uses the site's **Linking websites** total. It describes distinct linking websites, not the number of individual backlinks. The public profile does not reveal a full backlink list, dofollow share, or every keyword. Those fields are deliberately absent from this actor's output.

### How to scrape Ahrefs

1. Select **Top websites** for a ranked list, or select a domain search type for specific websites.
2. For a ranking, enter a country and category slug if needed. Leave `worldwide` and `all` for the overall list. Select **Trending** if you want the sites with the largest visible rank movements instead of the main ranking.
3. Set **Maximum results**. Turn on **Include domain details** when you need authority, traffic value, keyword, country, and competitor information for each ranked website.
4. Run the actor. When it finishes, open the default dataset and download the results in your preferred format.

For a domain lookup, put one domain or URL per line in **Domains**. The actor normalizes a URL to its host and opens that domain's public profile. A domain needs a public profile to yield a result. If one domain has no profile, the run continues with the remaining domains.

### Input

| Parameter | Type | Default | Description |
|---|---|---|---|
| `searchType` | Select | `top_websites` | `top_websites`, `website_details`, `website_authority`, or `traffic_overview` |
| `domains` | List of strings | Prefilled examples | Required for the three domain lookup modes |
| `rankingMode` | Select | `ranking` | Main ranking or the first page's trending lists |
| `country` | String | `worldwide` | Country page slug, such as `united-states` |
| `category` | String | `all` | Category page slug, such as `shopping` |
| `maxItems` | Integer | `100` | Maximum dataset items; zero applies no extra cap |
| `includeDetails` | Boolean | `false` | Enrich ranked rows using their public profile pages |
| `proxyConfiguration` | Object | Default proxy | Override the request proxy settings |

Example ranking input:

```json
{
  "searchType": "top_websites",
  "rankingMode": "ranking",
  "country": "worldwide",
  "category": "all",
  "maxItems": 30,
  "includeDetails": true
}
```

Example direct domain lookup:

```json
{
  "searchType": "website_details",
  "domains": ["ahrefs.com", "wikipedia.org"],
  "maxItems": 2
}
```

The three domain lookup labels read the same public profile source. They are useful when a downstream workflow separates authority checks, traffic summaries, and general profiles by `searchType`. Every available profile field is returned for each label. Selecting `website_authority` does not invent a backlink count, and selecting `traffic_overview` does not unlock private keyword history.

### Output example

This is a shortened item from a successful 30-result run using detail enrichment. Arrays are shortened here for readability; the dataset item contained five top countries, five top keywords, five competitors, and five similarly ranked websites.

```json
{
  "searchType": "top_websites",
  "rankingMode": "ranking",
  "rank": 1,
  "rankChange": null,
  "website": "wikipedia.org",
  "websiteUrl": "https://wikipedia.org",
  "detailUrl": "https://ahrefstop.com/websites/wikipedia.org",
  "category": "Reference",
  "searchTraffic": 4000000000,
  "trafficDelta": 85600000,
  "countryFilter": "worldwide",
  "categoryFilter": "all",
  "domain": "wikipedia.org",
  "name": "Wikipedia",
  "metricDate": "August 2026",
  "globalRank": 1,
  "countryRank": 1,
  "categoryRank": 1,
  "trafficValueUsd": 549600000,
  "trafficValueDeltaUsd": 27500000,
  "keywords": 3200,
  "domainRating": 97,
  "refdomains": 4000000,
  "refdomainsDelta": 15200,
  "topCountries": [
    {"country": "US", "traffic": 909972804, "trafficDelta": 26523740, "share": 22.3}
  ],
  "topKeywords": [
    {"keyword": "wikipedia", "volume": 2000000, "traffic": 1500000, "position": 1}
  ],
  "competitors": [
    {"website": "youtube.com", "traffic": 2600000000, "pages": 37700000}
  ],
  "similarlyRanked": [
    {"website": "wikipedia.org", "traffic": 4000000000, "rank": 1}
  ]
}
```

`description` is also present in the complete item; it is omitted from this shortened example. Some sites have no description. The global, country, and category rank values describe different ranking scopes, so they may differ even when the website appears on the overall list.

### Use cases

- **Market mapping:** Export the first several hundred ranked sites and compare estimated search traffic across categories. A category filter keeps the dataset focused on a market rather than requiring a later manual cleanup.
- **Competitor discovery:** Enrich known domains or ranking rows and review the public competitor list. Each competitor entry carries a traffic estimate and a page count for quick triage.
- **Traffic monitoring:** Schedule repeat runs of a stable country and category selection. Compare `searchTraffic`, `trafficDelta`, and `rank` over time in your own records.
- **Authority screening:** Check `domainRating` and `refdomains` for a list of public domain profiles. Use the numbers as screening signals, then review the original profile before making a decision.
- **Country comparison:** Inspect `topCountries` to see where a domain's search visits are concentrated. The list supplies each leading country's traffic estimate and share.
- **Keyword orientation:** Review the short public `topKeywords` list to identify a domain's visible leading terms. The output is a sample of the public profile, not a full keyword export.

### How much does it cost to scrape Ahrefs?

The configured result price is **$0.001 per dataset item**, or **$1 per 1,000 results**. A 30-result enriched run therefore has a result charge of **$0.03**. A 100-result ranking has a result charge of **$0.10**. Collecting the maximum 1,000 ranking rows has a result charge of **$1.00**. A domain summary is one result per public domain profile that is found.

Including details adds a page request for each ranked website but does not create a second dataset item for that website. The result charge is still based on the number of output records. Run time and any platform resource charges depend on the account and proxy configuration. Check the run's usage panel for the actual total.

The actor stops at `maxItems` or when the platform reports that the spending limit has been reached. Set a small result cap for your first run with a new filter. This is also a quick way to check whether the selected category contains enough public rows for your project.

### Tips for best results

Use the default overall ranking to test the workflow, then narrow it to a country or category. Slugs are the words in the public ranking URL: `united-states`, `united-kingdom`, `shopping`, and `news` are examples. A combination of country and category can return fewer than 100 sites, even when a worldwide category has many more.

Keep **Include domain details** off when you only need rank, category, and traffic. Turning it on fetches one additional profile page for every ranked row. For 30 results, that means roughly 31 public page requests. The extra request is worthwhile when your workflow needs Domain Rating, linking websites, traffic value, or the short competitor and keyword lists.

Use **Website details** for a small, curated domain list. You can paste full URLs, but the host is the lookup key. The actor removes a leading `www.` and visits the matching public domain page. If a particular domain has no public page, it is skipped. If every requested domain is unavailable, the run fails with a clear no-results error.

Export numeric columns as numbers. The source displays broad magnitudes such as `2.4B` or `37.7M`; the actor expands those suffixes before writing a result. Treat them as rounded estimates. Country entries can carry a more detailed value because the public page includes structured country data.

For repeat monitoring, keep the same country, category, ranking mode, and result cap. This avoids comparing different populations of websites. Save the run date with each export; the source's metric month is also included on enriched domain items as `metricDate`.

### Limits

The main ranking exposes ten pages of up to 100 websites, so the public cap is **1,000 ranked sites per filter**. Filtered rankings may end earlier. The actor stops when the next page does not exist. It does not infer missing ranks or pad the dataset to the requested maximum.

The trending section exposes twenty sites on the first page for a filter. Selecting `trending` yields those available records; it does not turn the full 1,000-site ranking into a trend list. The same domain can appear in both the rising and falling sections in unusual source states; the actor deduplicates by domain.

Public profile pages expose a short set of keywords, competitors, countries, and similarly ranked websites. They do not expose a complete keyword database, a complete backlink list, SERP results, CPC, or detailed traffic history. The free metric form on the main site requires a fresh challenge token. This actor uses the public ranking and profile pages and does not promise fields hidden behind that form.

Some detail fields can be empty. A site may have no description or may lack a public profile. A domain with a profile can also have a missing ranking section or a limited country list. The actor writes null for an unavailable scalar and an empty array for an unavailable list. It never substitutes a guessed metric.

There is no claim that `trafficValueUsd` represents revenue or that `searchTraffic` is measured visitor analytics. Both are estimates presented by the source. The data is best used for comparison, discovery, and monitoring trends, with the source page available in `detailUrl` for inspection.

### Automation examples

A scheduled workflow can request the top 100 shopping websites in a chosen country, then compare rank and estimated traffic against its previous export. Another workflow can submit a curated list of domains each week and flag large changes in Domain Rating, linking websites, or traffic value. The stable field names and direct profile URL make both workflows easy to inspect.

When connecting the dataset to another system, use `searchType` to route ranking rows and direct domain summaries. Use `website` for ranked rows and `domain` for direct lookups. When details are enabled on rankings, both keys appear on the same item and identify the same host.

### FAQ

#### Do I need an account on the target site?

No. The actor reads public ranking and profile pages. It cannot retrieve subscription data, private projects, or account-specific reports.

#### Can I request a complete backlink export?

No. The public profile shows Domain Rating and a rounded count of linking websites. It does not provide individual backlink records or a complete referring-domain export.

#### How many websites can I collect?

The overall main ranking has at most 1,000 public rows. A narrower country or category can have fewer. The trending mode currently has up to 20 visible records per filter. Direct domain mode is limited by your input list, public profile availability, and `maxItems`.

#### How fast is a run?

A plain ranking fetches one page per 100 rows. Detail enrichment adds one page per result, so it takes longer. Actual duration depends on response times, the selected filter, proxy routing, and whether pages need retrying. The successful 30-result enriched check completed on the platform with all required metrics filled.

#### Can I export to a spreadsheet?

Yes. Download the default dataset as CSV or a spreadsheet file, or retrieve it through the dataset endpoint. Each result is one row. The country, keyword, competitor, and similarly ranked lists remain arrays in JSON and may need expansion for a fully flat spreadsheet analysis.

#### What happens if a domain has no public profile?

That domain is skipped and a warning is logged. Other domains in the same input continue. A run with no resulting items fails so that a scheduled workflow can detect the problem.

#### Is it legal to use this data?

The actor collects publicly visible website information. Review the source's terms and applicable law for your use case. Respect privacy rules and avoid using scraped data for personal-data misuse.

### Integrations

Use the dataset endpoint, scheduled runs, webhooks, or a workflow connector to send the results into a database, spreadsheet, or reporting process. The output combines a stable website identifier with numeric metrics, source links, and an explicit search type, making it practical to join repeated exports and investigate changes.

### Support

Open an issue on the Issues tab with the run ID, input, and the field or page that needs attention. Include a public profile URL when a particular domain behaves differently. Requests for additional fields can be reviewed against what the public pages actually expose.

# Actor input Schema

## `searchType` (type: `string`):

Choose ranked websites or a public domain summary. The domain modes share one public source but label the result for its use case.

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

Domains or URLs to look up for website details, authority, or traffic. Each domain needs a public detail page.

## `rankingMode` (type: `string`):

For top websites: the main traffic ranking or the twenty trending sites on the first page.

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

Country page slug for rankings, such as united-states or united-kingdom. Use worldwide for all countries.

## `category` (type: `string`):

Category page slug for rankings, such as shopping, news, or finance. Use all for every category.

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

Hard cap on dataset items. Rankings have at most 1,000 public results; trending has at most 20 per filter. Zero means no extra cap.

## `includeDetails` (type: `boolean`):

Fetch each ranked website's public detail page to add Domain Rating, traffic value, keywords, countries, and competitors. One extra page request per website.

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

Proxy settings for public page requests. The default uses the available proxy service.

## Actor input object example

```json
{
  "searchType": "top_websites",
  "domains": [
    "ahrefs.com",
    "wikipedia.org"
  ],
  "rankingMode": "ranking",
  "country": "worldwide",
  "category": "all",
  "maxItems": 100,
  "includeDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Rankings or domain summaries in the default dataset.

# 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": [
        "ahrefs.com",
        "wikipedia.org"
    ],
    "country": "worldwide",
    "category": "all"
};

// Run the Actor and wait for it to finish
const run = await client.actor("mlg14/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 = {
    "domains": [
        "ahrefs.com",
        "wikipedia.org",
    ],
    "country": "worldwide",
    "category": "all",
}

# Run the Actor and wait for it to finish
run = client.actor("mlg14/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 '{
  "domains": [
    "ahrefs.com",
    "wikipedia.org"
  ],
  "country": "worldwide",
  "category": "all"
}' |
apify call mlg14/ahrefs-scraper --silent --output-dataset

```

## MCP server setup

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