# Backlink Checker — Backlinks, Domains & Anchors (`cheapapi/backlink-checker`) Actor

Check backlinks, referring domains, anchor texts, top pages, link competitors, new & lost links and authority scores for any domain or URL.

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

## Pricing

Pay per event + usage

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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

## Backlink Checker — Backlinks, Referring Domains & Anchors

Check the backlink profile of any website: authority score, every backlink, referring domains, anchor texts, top linked pages, link-building competitors, link gap, new & lost links over time and bulk authority / spam metrics for up to 10,000 domains. No account, no API key, no subscription. Enter a domain and click **Start**.

### Why this Actor

- **12 report types in one Actor**: overview, backlinks, referring domains, anchors, top pages, competitors, referring IPs/subnets, new & lost links, profile growth, link gap by domain, link gap by page and bulk metrics.
- **Pay per result, no subscription**: **$1.50 per 1,000 rows** (backlinks, referring domains, anchors, …) plus $0.035 per domain report. A full profile overview costs **$0.035 per domain**. Typical backlink tools start at $100+ per month.
- **Bulk metrics at $1.20 per 1,000 domains**: authority, backlinks, referring domains, spam scores and new/lost counts for up to **10,000 domains per run**, sent in batches of **1,000 domains per request** (plus $0.035 per metric group and batch).
- **Rich rows**: up to **47 fields per backlink** (anchor, dofollow, link type, linking page & domain authority, first/last seen, text around the link, redirect path…) and **34 fields per domain overview** with breakdowns by link type, attribute, TLD, country, platform and position on the page.
- **Up to 50,000 rows per domain and report**, with 13 filter options (plus custom filter expressions), custom sorting and grouping (e.g. one link per linking domain for outreach lists).
- **Budget-safe**: set a maximum cost per run and the Actor plans the work so it never exceeds it. Invalid input is rejected before anything is fetched or charged.

Enter a bare domain to analyze the whole site, or a page URL to analyze one page. **Top pages, competitors and link gap by domain always work on whole domains: a page URL entered there is converted to its domain automatically** (e.g. `https://example.com/pricing` → `example.com`, with a warning in the log).

This Actor is about links only: it does **not** return keyword rankings, organic traffic or on-page audits (see [Not included](#not-included) for the Actors that do).

### Compared with alternatives

Typical runs: **1,000 backlinks of one domain**, **authority metrics for 1,000 domains**, and a **domain overview of 1 domain**. Prices are shown as **Free plan / Gold plan** (this Actor costs the same on every plan). Prices are the listed pay-per-event fees. This Actor also bills Apify platform usage separately (at the default 256 MB a small run typically uses about $0.001–$0.005), shown as "+ usage" in our row.

| Alternative | 1,000 backlinks of one domain (Free / Gold) | Metrics for 1,000 domains (Free / Gold) | Domain overview, 1 domain (Free / Gold) | Backlinks per domain | Link gap report | Keyword & traffic data | Free plan |
|---|---|---|---|---|---|---|---|
| Most-used all-in-one SEO scraper, Ahrefs-style data (~2,100 users) | not possible (a top-backlinks list inside one result per domain) | not on Free / $4.00 ($0.004 per domain on Gold, + $0.00005 start) | not on Free / **$0.004** | top backlinks only | ✗ | ✓ | ✗ (its listing says it does not run on the Apify Free plan) |
| Ahrefs-style SEO scraper (~2,000 users) | not possible (up to 100 top backlinks per domain, returned as one result: $0.01 / $0.005 + $0.001 start per GB of memory) | not on Free (1 domain per run) / $5.00 (+ start fee) | **$0.011 / $0.006** (incl. start fee) | up to 100 | ✗ | ✓ | ✓ limited, as listed (10 runs per 30 days, 1 domain per run, up to 3 data types) |
| Semrush-style SEO scraper (~1,700 users) | not possible (backlink data returned as one result per domain) | not on Free (1 URL per run) / $17.50 ($0.0175 per result on Gold, + $0.01 start per GB; announced from 11 Oct 2026: $0.025 Free, $0.001 start) | $0.0375 / **$0.0275** (incl. $0.01 start) | one result per domain | ✗ | ✓ | ✓ limited, as listed (5 runs per 30 days, 1 URL per run) |
| Most-used Actor named "Backlink Checker" (~530 users) | not possible (a few hundred links per domain) | $10.00 / $10.00 ($0.01 per domain; $25.00 from 9 Oct 2026 with the announced $0.015 per-domain fee) | link list only (no overview) | a few hundred | ✗ | ✗ | ✓ as listed |
| Per-backlink checker (~175 users) | $3.03 / $2.424 ($0.03 / $0.024 per run + $0.003 / $0.0024 per link) | $4.50 / $3.60 (max. 20 domains per run: 50 runs + 1,000 summary rows) | link list only (no overview) | up to 1,000 | ✗ | ✗ | ✓ as listed |
| Bulk domain-rating checker (~46 users) | not possible (rating only, no links) | **$0.50 / $0.375** ($0.0005 / $0.000375 per domain) | rating only: $0.0005 / $0.000375 | none | ✗ | ✗ | ✓ as listed |
| **This Actor** | **$1.535 / $1.535** + usage | **$1.235 / $1.235** + usage | $0.035 / $0.035 + usage (34 fields) | **up to 50,000** | **✓** | ✗ | ✓ (up to $0.25 of results per month) |

Prices from public Apify Store listings (Platinum and Diamond prices equal Gold for all rows), checked September 2026. Free-plan limits are as shown on each listing. Where we are **not** cheaper:

- **Domain overview of a single domain:** our overview costs $0.035 per domain on every plan. The two Ahrefs-style scrapers return a domain summary for about $0.011 on Free (where available) and $0.004–$0.006 on Gold, and the Semrush-style scraper for $0.0275 on Gold, so for plain overviews they are cheaper. Our overview adds 34 fields with breakdowns by link type, attribute, TLD, country and platform; for authority and link counts of many domains, our bulk metrics cost $0.0012 per domain.
- **Only a domain rating for many domains?** The bulk domain-rating checker costs $0.50 / $0.375 per 1,000 domains, less than our $1.235. Our bulk metrics add backlinks, referring domains, spam score and more per domain.
- **Only a top-100 backlink sample for a few domains?** The Ahrefs-style scraper returns up to 100 links as one result for $0.01 / $0.005 plus its start fee, vs. $0.185 here for 100 links. The all-in-one scrapers also cover keywords and traffic.
- **Very small link lists on a high Apify plan:** our $0.035 report fee is a little above the per-backlink checker's $0.03 / $0.024 per-run fee, but each link costs $0.0015 here instead of $0.003 / $0.0024, so we are cheaper from 4 links (Free plan) or 13 links (Gold plan) upwards.

This Actor is cheaper as soon as you need full lists, referring domains, link gap, history or rich metrics for many domains, and you get filters, grouping and a hard budget cap on top.

### Not included

- **Keyword rankings and organic traffic estimates** — use our [Domain SEO Analyzer](https://apify.com/cheapapi/domain-seo-analyzer) (ranked keywords, traffic, SEO competitors for any domain).
- **Keyword research (search volume, difficulty, ideas)** — use our [Keyword Research Tool](https://apify.com/cheapapi/keyword-research-tool).
- **Live Google results / rank checks for a keyword** — use our [Google SERP Scraper](https://apify.com/cheapapi/google-serp-scraper).
- **Visibility in AI answers (ChatGPT, Gemini, AI Overviews…)** — use our [AI Search Visibility Tracker](https://apify.com/cheapapi/ai-search-visibility-tracker).
- **On-page / technical site audits** (broken pages, meta tags, speed) — use our [SEO Site Audit](https://apify.com/cheapapi/seo-site-audit).
- **Page-level top pages, competitors or domain link gap** — these three reports work on whole domains only; page URLs given to them are converted to their domain automatically (use the backlinks, referring domains, anchors or page link gap reports for a single page).
- **Moz DA or other tools' own scores** — authority and spam scores here come from our own link index and are not comparable one-to-one with other tools' numbers.

### What data you get

One row per natural entity (domain, backlink, referring domain, anchor, page, period…). The most important fields:

| Field | Type | Example | Reports |
|---|---|---|---|
| `id` | string | `"3e789dfb3468632a76638996"` | all (stable across runs, see [Monitoring](#monitoring-only-new-links)) |
| `target` | string | `"example.com"` | all except link gap |
| `report` | string | `"backlinks"` | all |
| `authorityScore` | number | `51` | overview, lists, bulk |
| `backlinks` | number | `332721` | overview, lists, bulk |
| `referringDomains` | number | `2940` | overview, lists, bulk |
| `referringMainDomains` | number | `2791` | overview, lists, bulk |
| `referringPages` / `referringIps` / `referringSubnets` | number | `329215` / `2307` / `1403` | overview, lists, bulk |
| `linkSpamScore` | number | `15` | overview, lists, bulk |
| `siteSpamScore` | number | `0` | overview, bulk |
| `brokenBacklinks` / `brokenPages` | number | `1130` / `130` | overview, lists, bulk |
| `firstSeen` / `lostDate` | string (ISO date) | `"2019-01-15T23:54:14.000Z"` | overview, lists, bulk |
| `linkTypes` / `linkAttributes` / `linkingCountries` / `linkingTlds` | object | `{"anchor": 64150, "image": 237276}` | overview, aggregated lists |
| `sourceUrl` / `sourceDomain` | string | `"https://www.textilwerbung-edenfeld.de/index.html"` | backlinks, page link gap |
| `targetUrl` | string | `"https://example.com/"` | backlinks |
| `anchorText` | string | `"Gütsel Webcube CMS"` | backlinks, anchors |
| `isDofollow` | boolean | `true` | backlinks |
| `linkType` | string | `"anchor"` | backlinks |
| `sourceDomainScore` / `sourcePageScore` | number | `65` / `81` | backlinks |
| `isNew` / `isLost` / `isBroken` | boolean | `false` | backlinks |
| `lastSeen` | string (ISO date) | `"2025-11-16T18:51:04.000Z"` | backlinks |
| `textBefore` / `textAfter` | string | `"2023 Textilwerbung Edenfeld,"` | backlinks |
| `referringDomain` | string | `"github.com"` | referring domains |
| `pageUrl` / `pageTitle` / `wordCount` | string / string / number | `"https://example.com/blog"` | top pages |
| `competitorDomain` / `sharedReferringDomains` | string / number | `"rival.com"` / `412` | competitors |
| `date` / `newBacklinks` / `lostBacklinks` | string / number / number | `"2026-08-01"` / `1520` / `980` | new & lost, growth |
| `linkingDomain` / `linksTo` / `missingFrom` | string / array / array | `"blog.io"` / `["rival.com"]` / `["you.com"]` | link gap |
| `scoreScale` | number | `100` | all with scores |
| `scrapedAt` | string (ISO date) | `"2026-09-28T09:00:00.000Z"` | all |

Every field is declared with its type in the dataset schema. The backlinks list adds 25+ more fields (`linkScore`, `previousSeen`, `sourcePageTitle`, `sourceCountry`, `sourceTld`, `sourceIp`, `linkPosition`, `imageUrl`, `imageAlt`, `isIndirect`, `indirectPath`, `targetStatusCode`, `sourceRankingKeywordsTop10`…). The dataset has three ready table views: **Profile overview**, **Backlinks** and **Bulk domain metrics**.

### How to use

#### In Apify Console

1. Open the Actor and click **Try for free**.
2. In **Websites to analyze**, enter one domain or URL per line (e.g. `example.com`).
3. In **What do you want?**, pick a report (the default is the backlink profile overview).
4. For list reports, set **Max rows per domain** (you pay per saved row, so this is also your cost cap).
5. Optional: open the **Advanced** sections for filters, sorting and report options.
6. Click **Start**. Rows appear in the **Output** tab; download them as JSON, CSV, Excel, XML or HTML.

#### Ready-to-paste input

```json
{
    "domains": ["example.com"],
    "report": "backlinks",
    "maxResults": 500,
    "groupLinks": "onePerDomain",
    "dofollowOnly": true,
    "maxLinkSpamScore": 30
}
```

More inputs:

```json
{ "domains": ["site1.com", "site2.com", "site3.com"], "report": "bulkMetrics", "bulkMetrics": ["profile", "siteSpamScore"] }
```

```json
{ "domains": ["competitor1.com", "competitor2.com"], "report": "linkGap", "gapMode": "anyOverlap", "excludeLinkingTo": ["mysite.com"] }
```

Domains are analyzed as a whole (`www.` and the protocol are removed). A page URL such as `https://example.com/pricing` is analyzed as that single page. Exception: top pages, competitors and link gap by domain convert a page URL to its domain automatically.

#### API: curl

```bash
curl -X POST "https://api.apify.com/v2/acts/cheapapi~backlink-checker/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"domains": ["example.com"], "report": "referringDomains", "maxResults": 200}'
```

#### API: JavaScript (`apify-client`)

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_TOKEN>' });
const run = await client.actor('cheapapi/backlink-checker').call({
    domains: ['example.com'],
    report: 'backlinks',
    maxResults: 1000,
    groupLinks: 'onePerDomain',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`${items.length} backlinks`, items[0]);
```

#### API: Python (`apify-client`)

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_TOKEN>")
run = client.actor("cheapapi/backlink-checker").call(run_input={
    "domains": ["site1.com", "site2.com", "site3.com"],
    "report": "bulkMetrics",
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(row["target"], row.get("authorityScore"), row.get("referringDomains"))
```

### Use cases

- **Link prospecting and outreach**: link gap reports list sites that link to your competitors but not to you (`missingFrom`), ready for outreach.
- **SEO audits**: check authority, spam scores, broken backlinks, anchor text distribution and nofollow ratio of a site in one run.
- **Domain due diligence**: vet expired domains, acquisition targets or guest-post sites with bulk authority and spam metrics for thousands of domains.
- **Link monitoring**: schedule the new & lost report weekly and get alerted when a site gains or loses many links.
- **Competitor research**: find link-building competitors and their most-linked pages.
- **Negative SEO checks**: filter backlinks by high spam score or group referring IPs/subnets to spot link networks.

### Advanced options

All advanced options are optional. Empty fields mean "no filter".

| Option (input field) | Default | Meaning |
|---|---|---|
| Max rows per domain (`maxResults`) | `100` | Rows saved per domain and list report (1–50,000). You pay per saved row, so this is also your cost cap. |
| Link status (`linkStatus`) | `active` | Count active links, lost links or both (`all`). |
| Include subdomains (`includeSubdomains`) | `true` | Also count links to subdomains of the domain. |
| Include indirect links (`includeIndirectLinks`) | `true` | Also count links reaching the site through a redirect or canonical. |
| Exclude links from the site itself (`excludeInternalLinks`) | `true` | Ignore links from the domain's own subdomains. |
| Dofollow links only (`dofollowOnly`) | `false` | Only dofollow links. |
| Exclude broken links (`excludeBrokenLinks`) | `false` | Ignore links to pages that no longer work. |
| New links only (`newLinksOnly`) | `false` | Only links found in the latest crawl. |
| Min. authority of linking site (`minSourceAuthority`) | empty (no filter) | Only links from sites with at least this authority score. |
| Max. link spam score (`maxLinkSpamScore`) | empty (no filter) | Only links with spam score at or below this value (0–100). |
| Linking site countries (`sourceCountries`) | empty (all) | Two-letter ISO codes, e.g. `US`, `DE`. |
| Anchor text contains (`anchorContains`) | empty | Only links whose anchor contains this text. |
| Custom link filters (`linkFilters`) | empty | Expert conditions on links, e.g. `[["sourceDomainScore", ">=", 40], "and", ["linkType", "=", "anchor"]]`. Operators `=`, `<>`, `<`, `<=`, `>`, `>=`, `in`, `not_in`, `like`, `not_like`, `regex`, `not_regex`. Max 8 conditions in total. Via the API you may also send the expression as a JSON string; invalid JSON, unknown operators or wrong shapes stop the run before anything is charged, with a message that says what to fix. |
| Sort by (`sortBy`) | `auto` | Order of list rows (authority, backlinks, first seen, …). |
| Sort direction (`sortDirection`) | `desc` | Highest/newest first or lowest/oldest first. |
| Custom sort (`customSort`) | empty | Up to 3 rules like `backlinks,desc`; overrides the automatic order. |
| Custom result filters (`resultFilters`) | empty | Conditions on the report rows, e.g. `[["authorityScore", ">", 30]]`; link gap: `"2.backlinks"` for the 2nd domain. |
| Skip first rows (`startOffset`) | `0` | Continue a previous run (0–1,000,000). |
| Score scale (`scoreScale`) | `100` | Authority scores on 0–100 or 0–1,000. |
| Breakdown size (`breakdownLimit`) | `10` | Entries per breakdown (top TLDs, countries…), 1–1,000. |
| Backlinks: group links (`groupLinks`) | `none` | Every link, one per linking domain, one per anchor or custom. |
| Backlinks: custom group field (`customGroupField`) | `sourceDomain` | Field used for custom grouping. |
| Backlinks: links per group (`customGroupLimit`) | `1` | Max links per custom group (1–1,000). |
| Top pages: detail level (`pagesDetail`) | `full` | Page details + link metrics, or link metrics only (includes removed pages). |
| Competitors: main domains only (`mainDomainsOnly`) | `true` | Group competitor subdomains under their main domain. |
| Competitors: exclude large sites (`excludeLargeSites`) | `true` | Leave out search engines, social networks and marketplaces. |
| Networks: group by (`networkType`) | `ip` | IP address or C-class subnet. |
| Link gap: match (`gapMode`) | `sharedByAll` | Sites linking to ALL listed domains, or to at least one (`anyOverlap`). |
| Link gap: exclude sites that link to (`excludeLinkingTo`) | empty | Up to 10 domains, e.g. your own site. |
| History: from (`dateFrom`) | 12 months ago | Start date (earliest 2019-01-30). |
| History: to (`dateTo`) | today | End date. |
| History: group by (`groupInterval`) | `month` | Day, week, month or year. |
| Bulk: metrics (`bulkMetrics`) | `["profile"]` | Link profile, site spam score, new & lost backlinks, new & lost referring domains, or single counts. |
| Bulk: new & lost since (`newLostSince`) | last month | Start date for bulk new & lost counts. |

### Output example

The Output tab has ready-made table views for each report: **Profile overview**, **Backlinks**, **Referring domains**, **Anchors**, **Link gap**, **New & lost links** and **Bulk domain metrics** (all fields are in the JSON/CSV export).

Backlink profile overview (breakdowns shortened):

```json
{
    "id": "0dbc7d0192bfa9c2e0fed435",
    "target": "example.com",
    "report": "overview",
    "authorityScore": 51,
    "backlinks": 332721,
    "referringDomains": 2940,
    "referringMainDomains": 2791,
    "nofollowReferringDomains": 0,
    "referringPages": 329215,
    "referringIps": 2307,
    "referringSubnets": 1403,
    "linkSpamScore": 15,
    "brokenBacklinks": 1130,
    "brokenPages": 130,
    "firstSeen": "2019-01-15T23:54:14.000Z",
    "lostDate": null,
    "siteSpamScore": 0,
    "crawledPages": 114346,
    "server": "nginx/1.24.0 (Ubuntu)",
    "cms": "wordpress",
    "platformTypes": ["organization"],
    "hostingCountry": "US",
    "linkingTlds": { "jetzt": 231921, "de": 83185, "com": 5390 },
    "linkTypes": { "image": 237276, "anchor": 64150, "redirect": 27786, "canonical": 3 },
    "linkAttributes": { "noopener": 4340, "noreferrer": 2265, "sponsored": 38, "ugc": 5 },
    "linkingCountries": { "unspecified": 238255, "DE": 83663, "US": 1563 },
    "scoreScale": 100,
    "scrapedAt": "2026-09-29T05:08:24.620Z"
}
```

Backlinks list row (one link per linking domain, some fields omitted):

```json
{
    "id": "3e789dfb3468632a76638996",
    "target": "example.com",
    "report": "backlinks",
    "sourceUrl": "https://www.textilwerbung-edenfeld.de/index.html",
    "sourceDomain": "www.textilwerbung-edenfeld.de",
    "targetUrl": "https://example.com/",
    "anchorText": "Gütsel Webcube CMS",
    "isDofollow": true,
    "linkType": "anchor",
    "linkScore": 70,
    "sourcePageScore": 81,
    "sourceDomainScore": 65,
    "linkSpamScore": 0,
    "isNew": false,
    "isLost": false,
    "isBroken": false,
    "firstSeen": "2024-02-12T03:09:59.000Z",
    "previousSeen": "2025-09-06T14:31:21.000Z",
    "lastSeen": "2025-11-16T18:51:04.000Z",
    "sourcePageTitle": "Textilwerbung Edenfeld Ostwestfalen Lippe (OWL), Kreis Gütersloh",
    "sourceCountry": "DE",
    "sourceTld": "de",
    "sourcePageStatusCode": 200,
    "textBefore": "2023 Textilwerbung Edenfeld,",
    "linksOnPage": 1,
    "similarLinks": 62,
    "targetStatusCode": 301,
    "isIndirect": true,
    "indirectPath": [{ "type": "redirect", "statusCode": 302, "url": "https://www.guetsel.de/" }],
    "sourceRankingKeywordsTop100": 5,
    "scoreScale": 100,
    "scrapedAt": "2026-09-29T05:08:24.620Z"
}
```

Each run also writes a `RUN_SUMMARY` record to the key-value store:

```json
{ "report": "backlinks", "targetsRequested": 1, "targetsWithData": 1, "targetsWithoutData": 0, "targetsFailed": 0, "rowsSaved": 1, "reportsCharged": 1, "extraPagesCharged": 0, "stoppedByBudget": false, "problems": [] }
```

### Pricing

**Apify Free plan:** Apify does not pay developers for usage on its Free plan, so on the Free plan this Actor can be used for up to **$0.25 of results per calendar month** — enough to try it on a small input. When the allowance is used up, the run ends with a clear message (not an error). Any paid Apify plan removes the limit; prices are the same.

Pay per report and per saved row. No monthly fee, no start fee. Apify platform usage is billed separately by Apify (at the default 256 MB a small run typically uses about $0.001–$0.005); the prices and examples below are event fees only. **Same prices on every Apify plan (Free, Bronze, Silver, Gold and above):**

- **Domain report: $0.035** — once per domain and report requested, **even if nothing is found** (the data lookup itself is paid; the overview has no other charge). Link gap: once per comparison. Bulk: once per metric group per batch of up to 1,000 domains.
- **Result row: $0.0015 ($1.50 per 1,000)** — per saved row in list and history reports (backlinks, referring domains, anchors, pages, competitors, networks, link gap rows, time-series points).
- **Bulk domain metrics: $0.0012 ($1.20 per 1,000)** — per domain row in the bulk metrics report.
- **Low-yield extra page: $0.0303** — only in reports longer than 1,000 rows: rows are fetched in pages of 1,000, and a follow-up page that brings fewer than 21 saved rows (for example the last 5 rows of a 1,005-row request, or a list that ends just after a full page) is charged this fee on top of its rows. Reports of up to 1,000 rows never pay it.

Worked examples:

- **Overview of 100 domains**: 100 × $0.035 = **$3.50**. For plain overviews the Ahrefs-style scrapers are cheaper (about $0.40–$0.50 on Gold); for authority and link counts only, bulk metrics cost $0.035 + 100 × $0.0012 = **$0.155**.
- **1,000 backlinks of one domain**: $0.035 + 1,000 × $0.0015 = **$1.535**.
- **Bulk link-profile metrics for 1,000 domains**: $0.035 + 1,000 × $0.0012 = **$1.235**. For 10,000 domains: 10 × $0.035 + 10,000 × $0.0012 = **$12.35**.
- **Link gap of 3 competitors, 500 rows**: $0.035 + 500 × $0.0015 = **$0.785**.
- **New & lost links for the last 12 months (13 monthly rows)**: $0.035 + 13 × $0.0015 = **$0.0545**.
- **Referring domains of a brand-new site that has no links yet**: 1 × $0.035 = **$0.035** (the lookup was made, nothing was found).
- **1,005 backlinks of one domain**: $0.035 + 1,005 × $0.0015 + 1 × $0.0303 (second page with only 5 rows) = **$1.5728**. Setting Max rows to 1,000 avoids the fee.

A report is charged per report requested, even if nothing is found. A request that times out after being sent is still charged (as an empty report or page), because it may already have been processed. Requests that fail on our side (service errors) and invalid input are not charged. Set **Maximum cost per run** in the run options; the Actor reserves budget before each domain and stops cleanly before the limit.

### Monitoring: only new links

Every row has a stable `id` (a hash of the report and the row's natural key: linking page + target URL + link type + anchor for backlinks, the domain for referring domains and overviews, the period for history rows). The same link gets the same `id` in every run, while its changing metrics (scores, last seen) do not affect it. Recipe for a weekly "new backlinks" alert:

1. Create a task with `"report": "backlinks"`, `"newLinksOnly": true` (links found in the latest crawl) and a sensible **Max rows per domain**.
2. Schedule it weekly.
3. In your webhook, Make/Zapier scenario or script, keep the `id`s you have already seen and forward only rows with a new `id`.

For counts only, schedule the **New & lost backlinks** report (13 monthly rows cost $0.0545) or **Bulk metrics** with "new & lost since". The Actor does not skip repeats itself: every returned row is looked up fresh, so filtering happens on your side at no extra cost.

### Integrations

- **Make and Zapier**: use the Apify app to start the Actor and pass the dataset rows to the next step (e.g. a CRM for outreach prospects).
- **Google Sheets**: export the dataset directly, or use the Google Sheets integration to append rows after each run.
- **Webhooks**: call your own endpoint when a run succeeds or fails; the payload links to the dataset and `RUN_SUMMARY`.
- **Schedules**: run the new & lost or bulk report daily, weekly or monthly to monitor link profiles.
- **API and MCP**: call it from any language with the Apify API or `apify-client`, or let AI agents use it through the Apify MCP server.

### FAQ

**Is there a limit on the Apify Free plan?** Yes: up to $0.25 of this Actor's results per calendar month, enough to try it. Apify pays developers nothing for Free-plan usage while our data costs are real, so this keeps the Actor sustainable. Runs that reach the allowance stop cleanly and keep everything collected so far; the allowance resets on the 1st of the month. Any paid Apify plan has no limit.

**Is it legal to use this Actor?** Yes. It returns public link data about websites (which pages link to which pages) from our own continuously crawled link index. You are responsible for how you use the results, e.g. in outreach campaigns.

**Is Apify platform usage included?** No. Apify platform usage (compute) is billed separately by Apify, on top of the event fees. At the default 256 MB memory a small run typically uses about $0.001–$0.005; large bulk runs use more. You can see each run's usage in Apify Console.

**How fresh is the data?** The link index is recrawled continuously. `lastSeen` shows when each link was last confirmed, `isNew` flags links from the most recent crawl and `lostDate` shows when a link disappeared.

**Why did I get fewer results than expected?** Your filters (link status, dofollow only, min. authority, max. spam score, countries) may exclude links, "Max rows per domain" may be lower than the available rows, grouping (one link per domain) reduces rows, or your maximum cost per run was reached (see `stoppedByBudget` in `RUN_SUMMARY`). Very new or small sites may have few or no known links.

**What is the authority score?** A 0–100 score (or 0–1,000 with the finer scale) based on the number and strength of links pointing to a page or domain. Scores are comparable with each other, not with other tools' numbers.

**What happens if my custom filter has a typo?** The run stops immediately with a message such as `"Custom link filters" is not valid JSON near character 23` or `Unknown operator "=>"`, before any data is fetched, so nothing is charged.

**What is the difference between link spam score and site spam score?** Link spam score rates how spammy the incoming links are; site spam score rates the site itself.

**How do I control my budget?** Set "Max rows per domain" and the run option "Maximum cost per run". The Actor plans each domain within the remaining budget (report fee, rows and a possible extra-page fee) and never exceeds it.

**Why was I charged $0.035 for a domain with no results?** The report is charged per report requested, even if nothing is found: looking up a domain in the link index costs the same whether it has links or not. Check the domain spelling and your filters before large runs; `targetsWithoutData` in `RUN_SUMMARY` lists how many domains returned nothing.

**Why was I charged for a request that timed out?** A request that was sent but got no answer is never resent and is charged like an empty report (or page), because the data service may already have processed it. Rerun the domain later.

**Why was I charged a $0.0303 extra-page fee?** Your report asked for more than 1,000 rows, so a second (or later) page was fetched, and it brought fewer than 21 rows. Each page is a separate paid lookup that the row price alone can't cover below 21 rows. Choose Max rows of 1,000 or a multiple of 1,000 plus at least 21 to avoid it.

**How many domains can I check?** Up to 10,000 per run. For many domains use **Bulk metrics** ($1.20 per 1,000 domains) instead of one overview per domain.

**Can I monitor backlinks over time?** Yes. Schedule the **New & lost backlinks** report (or bulk metrics with "new & lost since"), or schedule a backlinks run with "New links only" and deduplicate by the stable `id` field — see [Monitoring](#monitoring-only-new-links).

**Which export formats are supported?** JSON, CSV, Excel, XML, HTML table and RSS from the Output tab or the dataset API.

**I need help or a new feature.** Open an issue on the Actor's **Issues** tab and describe your input and what you expected.

### Limitations

- No link index covers the whole web; counts differ from other SEO tools and are best compared within this Actor.
- History reports start on 2019-01-30.
- Link gap reports compare 2–20 domains at a time; excluded domains are limited to 10.
- Custom filters accept at most 8 conditions per report (simple filters count toward the limit); custom sort accepts 3 rules.
- Top pages, competitors and link gap by domain work on whole domains; page URLs are converted to their domain (with a warning).
- Up to 50,000 rows per domain and report per run; use "Skip first rows" to continue.

### Privacy

The Actor collects link data about websites, not personal data. Linking pages may occasionally contain names in titles or anchor texts; if you process such data, make sure you have a legitimate purpose under GDPR and similar laws.

# Actor input Schema

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

Domains, subdomains or page URLs, one per line, e.g. <code>example.com</code>, <code>blog.example.com</code> or <code>https://example.com/pricing</code>. Domains are analyzed as a whole (without <code>www.</code>); page URLs are analyzed as a single page. For the link gap reports enter 2–20 domains; for bulk metrics up to 10,000 (sent in batches of 1,000).

## `report` (type: `string`):

<b>Overview</b>: authority score, backlink and referring-domain totals, spam score, link type / country / TLD breakdowns. <b>Lists</b>: individual backlinks, referring domains, anchors, top pages, competitors or networks. <b>Over time</b>: new & lost links or profile growth by day/week/month/year. <b>Bulk metrics</b>: one row per domain for up to 10,000 domains at a fraction of the cost. <b>Link gap</b>: sites that link to the other domains in your list but not (or also) to the first one.

## `maxResults` (type: `integer`):

For list reports (backlinks, referring domains, anchors, pages, competitors, networks, link gap): how many rows to save per domain. You pay per saved row plus $0.035 per report (charged even if nothing is found). Rows are fetched in pages of 1,000; above 1,000, a follow-up page that brings fewer than 21 rows adds a $0.0303 extra-page fee, so 1,000 (or a multiple of 1,000 plus at least 21) is the most economical choice.

## `linkStatus` (type: `string`):

Count only links that currently exist, only links that were removed, or both. Not used by competitors and history reports.

## `includeSubdomains` (type: `boolean`):

Also count links pointing to subdomains of the domain (e.g. <code>blog.example.com</code> for <code>example.com</code>).

## `includeIndirectLinks` (type: `boolean`):

Also count links that reach the site through a redirect or canonical tag.

## `excludeInternalLinks` (type: `boolean`):

Ignore links coming from the domain's own subdomains.

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

Count only dofollow links.

## `excludeBrokenLinks` (type: `boolean`):

Ignore links that point to pages that no longer work.

## `newLinksOnly` (type: `boolean`):

Count only links found in the most recent crawl.

## `minSourceAuthority` (type: `integer`):

Only links from sites with at least this authority score (on the score scale chosen under "Score scale"; 0–100 by default). <b>Default: empty = no filter</b> (links from sites of any authority are included). Example: <code>30</code> keeps links from reasonably strong sites only.

## `maxLinkSpamScore` (type: `integer`):

Only links with a spam score at or below this value (0 = clean, 100 = very spammy). <b>Default: empty = no filter</b> (links of any spam score are included). Example: <code>30</code> removes the spammiest links.

## `sourceCountries` (type: `array`):

Only links from sites in these countries (two-letter ISO codes, e.g. <code>US</code>, <code>DE</code>).

## `anchorContains` (type: `string`):

Only links whose anchor text contains this text.

## `linkFilters` (type: `array`):

Extra conditions on individual links, using the output field names of the backlinks list. Example: <code>\[\["sourceDomainScore", ">=", 40], "and", \["linkType", "=", "anchor"]]</code>. Operators: =, <>, <, <=, >, >=, in, not\_in, like, not\_like, regex, not\_regex. Max 8 conditions including the filters above.

## `sortBy` (type: `string`):

How list rows are ordered. "Automatic" uses the most useful order per report (strongest links, most-linked pages, most shared domains…).

## `sortDirection` (type: `string`):

Direction for "Sort by".

## `customSort` (type: `array`):

Up to 3 rules like <code>backlinks,desc</code> using output field names. Overrides the automatic order.

## `resultFilters` (type: `array`):

Conditions on the rows of the report itself, using its output field names. Example for referring domains: <code>\[\["authorityScore", ">", 30], "and", \["backlinks", ">=", 5]]</code>. For link gap reports prefix a field with the position of the domain in your list, e.g. <code>"2.backlinks"</code>. Max 8 conditions.

## `startOffset` (type: `integer`):

Skip this many rows before saving (to continue a previous run).

## `scoreScale` (type: `string`):

Scale of the authority scores in the output.

## `breakdownLimit` (type: `integer`):

How many entries the breakdowns (top TLDs, countries, link types…) contain per row.

## `groupLinks` (type: `string`):

Backlinks list only. "One link per linking domain" is ideal for outreach lists.

## `customGroupField` (type: `string`):

Used when "Group links" is Custom.

## `customGroupLimit` (type: `integer`):

Used when "Group links" is Custom: max links kept per group.

## `pagesDetail` (type: `string`):

Top pages report only.

## `mainDomainsOnly` (type: `boolean`):

Group competitors by main domain instead of listing subdomains separately.

## `excludeLargeSites` (type: `boolean`):

Leave out huge sites (search engines, social networks, marketplaces) that share links with everyone.

## `networkType` (type: `string`):

Referring IPs / subnets report only.

## `gapMode` (type: `string`):

Link gap reports only. Each row shows which of your domains the site links to and which it is missing from.

## `excludeLinkingTo` (type: `array`):

Up to 10 domains (e.g. your own). Sites linking to any of them are left out — perfect to find link opportunities you do not have yet.

## `dateFrom` (type: `string`):

Start date for the over-time reports (YYYY-MM-DD). Default: 12 months ago. Earliest: 2019-01-30.

## `dateTo` (type: `string`):

End date for the over-time reports. Default: today.

## `groupInterval` (type: `string`):

One row per period. You pay per row, so "month" is the most economical.

## `bulkMetrics` (type: `array`):

Bulk metrics report only. Each selected group adds one domain report fee per 1,000 domains; the per-domain price stays the same. "Link profile" already contains the three "only" metrics.

## `newLostSince` (type: `string`):

Start date for the bulk new & lost counts (YYYY-MM-DD). Default: last month.

## Actor input object example

```json
{
  "domains": [
    "apify.com"
  ],
  "report": "overview",
  "maxResults": 100,
  "linkStatus": "active",
  "includeSubdomains": true,
  "includeIndirectLinks": true,
  "excludeInternalLinks": true,
  "dofollowOnly": false,
  "excludeBrokenLinks": false,
  "newLinksOnly": false,
  "sortBy": "auto",
  "sortDirection": "desc",
  "startOffset": 0,
  "scoreScale": "100",
  "breakdownLimit": 10,
  "groupLinks": "none",
  "customGroupField": "sourceDomain",
  "customGroupLimit": 1,
  "pagesDetail": "full",
  "mainDomainsOnly": true,
  "excludeLargeSites": true,
  "networkType": "ip",
  "gapMode": "sharedByAll",
  "groupInterval": "month",
  "bulkMetrics": [
    "profile"
  ]
}
```

# Actor output Schema

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

No description

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

No description

# 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"
    ],
    "report": "overview",
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("cheapapi/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 = {
    "domains": ["apify.com"],
    "report": "overview",
    "maxResults": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("cheapapi/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 '{
  "domains": [
    "apify.com"
  ],
  "report": "overview",
  "maxResults": 100
}' |
apify call cheapapi/backlink-checker --silent --output-dataset

```

## MCP server setup

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