# Domain SEO Overview — Organic Keywords & Traffic in Bulk (`saliga/domain-seo-overview`) Actor

Google organic keywords, estimated organic and paid clicks, top-3 and top-10 rankings and traffic value for thousands of domains in one run. 1,000 domains per lookup in bulk mode. No Semrush or Ahrefs account needed.

- **URL**: https://apify.com/saliga/domain-seo-overview.md
- **Developed by:** [Salih Küçükkayış](https://apify.com/saliga) (community)
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.50 / 1,000 domain 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

Get the Google SEO footprint of thousands of domains in one run: **organic keywords, estimated organic and paid clicks**, and in detailed mode **top-3 and top-10 rankings, new and lost keywords and traffic value**. One row per domain and country. No Semrush or Ahrefs account needed.

**Bulk mode: $5 per 1,000 domains plus $0.02 per lookup of up to 1,000 domains**, so about $5.02 per 1,000. **Detailed mode: the same $0.005 per domain plus $0.02 per lookup, one lookup per domain**, so $25 per 1,000. Domains with no data have no domain fee, and failed lookups are free. On the Starter, Scale and Business plans the domain fee is 10 %, 20 % and 30 % lower. No subscription, and platform usage is included. (Plus a tiny $0.00005 start fee per run.)

### What you get

- **Bulk: 1,000 domains per lookup.** Organic keywords and estimated organic clicks a month, paid keywords and estimated paid clicks, for every domain on your list.
- **Detailed: the ranking picture.** Adds keywords at position 1, in the top 3, top 10, top 20 and top 50; keywords that are new, up, down or lost since the last check; the traffic value (what those clicks would cost as ads) and the estimated ad spend.
- **Domains, subdomains and pages.** `asana.com`, `blog.asana.com`, or (bulk mode) a single page like `https://www.asana.com/pricing`.
- **Up to 10 countries.** One row per domain and country, so you can see where each site is strong.
- **Bring domains from anywhere.** Paste a list, link a CSV, or point to another Actor's dataset (fields named `domain`, `url`, `website` or `target` are found automatically).
- **Pay for answers.** A domain with no rankings comes back as a free `no_data` row.

### Typical uses

- **Qualify leads.** Add SEO size to a list of 10,000 company websites before outreach: who has real organic traffic, who has none.
- **Size a market.** Compare every competitor in a niche on one table.
- **Agency prospecting.** Detailed mode on a short list shows who is losing keywords right now.
- **Track a portfolio.** Run the same list monthly and compare.

### Input

```json
{
  "domains": ["asana.com", "monday.com", "clickup.com"],
  "mode": "bulk",
  "countries": ["US", "GB"]
}
```

| Field | Meaning |
|---|---|
| `domains` | Up to 50,000 domains per run. |
| `mode` | `bulk` (default) or `detailed`. |
| `countries` | Up to 10 countries: two-letter codes or names. Default `US`. |
| `language` | Optional language code. Empty means each country's main language. |
| `domainsUrl`, `datasetId`, `domainField` | Other ways to pass domains. |

### Output

Bulk mode, one row per domain and country. A real row from a run on 17 October 2026 (asana.com, monday.com and clickup.com in the United States: three domains, one lookup):

```json
{
  "domain": "asana.com",
  "input": "asana.com",
  "country": "US",
  "language": "en",
  "organicKeywords": 78991,
  "organicEstimatedTraffic": 195762,
  "paidKeywords": 2,
  "paidEstimatedTraffic": 1191,
  "detail": "bulk",
  "status": "ok",
  "charged": true
}
```

Detailed mode adds rankings by position band, traffic value and keyword movement:

```json
{
  "domain": "asana.com",
  "input": "https://www.asana.com/",
  "country": "US",
  "language": "en",
  "organicKeywords": 98400,
  "organicEstimatedTraffic": 1520000,
  "paidKeywords": 2100,
  "paidEstimatedTraffic": 64000,
  "organicTop1": 2900,
  "organicTop3": 6100,
  "organicTop10": 15800,
  "organicTop20": 24300,
  "organicTop50": 51200,
  "organicTrafficValueUsd": 6420000,
  "newKeywords": 3400,
  "upKeywords": 8800,
  "downKeywords": 9100,
  "lostKeywords": 2700,
  "paidTrafficCostUsd": 410000,
  "detail": "detailed",
  "status": "ok",
  "charged": true
}
```

This detailed row shows the shape only; its figures are not real data.

| Field | Meaning |
|---|---|
| `domain`, `input` | The domain looked up, and what you sent |
| `organicKeywords`, `paidKeywords` | Google keywords the domain ranks for in the top 100, and buys ads on |
| `organicEstimatedTraffic`, `paidEstimatedTraffic` | Estimated monthly clicks from those keywords, from positions and search volumes |
| `organicTop1` … `organicTop50` | Detailed: keywords at position 1, and in the top 3, 10, 20 and 50 |
| `newKeywords`, `upKeywords`, `downKeywords`, `lostKeywords` | Detailed: movement since the provider's last check |
| `organicTrafficValueUsd`, `paidTrafficCostUsd` | Detailed: what the organic clicks would cost as ads, and the estimated ad spend, a month |
| `status`, `note`, `charged` | `ok`, or why there is no row; `charged` is `true` only on rows you paid for |

Rows with no domain fee: `no_data` (no rankings in that country), `invalid_domain`, `input_error`, `spending_limit` (the full list is saved as `NOT_LOOKED_UP`), `free_plan_limit`, `skipped` (ten lookups in a row found nothing), `throttled` and `provider_error`.

### What it costs

| Run | Price (no discount) |
|---|---|
| 100 domains, bulk | $0.52 |
| 10,000 domains, bulk | $50.20 |
| 10,000 domains, bulk, 3 countries | $150.60 |
| 100 domains, detailed | $2.50 |

These assume every domain has data.

### Apify free plan

Every lookup costs us real money at the data source, and free-plan runs earn nothing. So on the Apify free plan this Actor gives one lookup a day: the first 20 domains in bulk mode, or the first domain in detailed mode, in the first country. Everything else comes back as uncharged `free_plan_limit` rows. Any paid Apify plan has no such limits.

### Covered countries

The same 92 countries as [Keyword Research](https://apify.com/saliga/keyword-research), including the United States, United Kingdom, Canada, Australia, India, most of Europe and Latin America, Japan, South Korea and Türkiye. Other countries come back as an uncharged `input_error` row.

### Next steps with your domains

- **Which keywords bring that traffic:** [Competitor Keywords](https://apify.com/saliga/competitor-keywords).
- **What each site runs on:** [Tech Stack Detector](https://apify.com/saliga/tech-stack-detector).
- **Join the figures to your lead list:** [Dataset Merge & Dedup Datasets](https://apify.com/saliga/dataset-merge-dedupe).

### Good to know

- Figures come from a licensed SEO data provider that checks Google results at scale. Nothing is scraped from Semrush, Ahrefs or any other tool.
- Clicks and values are estimates from rankings and search volumes, not the site's own analytics, and are best used to compare domains with each other.
- This Actor is not affiliated with, endorsed by or sponsored by Google, Semrush or Ahrefs. Names are trademarks of their owners.
- A run that is moved to another server, or resurrected, continues where it stopped. Nothing is looked up or charged twice.
- Pricing: one `domain-result` charge per domain row with data, one `lookup` charge per request the database answers, plus $0.00005 when a run starts.
- Questions or a missing feature: open an issue on the Actor page.

### FAQ

**Is this Domain Authority?** No. Authority scores are built from backlinks; this Actor measures search visibility: how many keywords a site ranks for and the clicks they bring.

**Bulk or detailed?** Bulk for long lists (it is five times cheaper per domain). Detailed when you need the top-10 count and keyword movement.

### More from this developer

- [Keyword Research](https://apify.com/saliga/keyword-research): keyword ideas, suggestions and related keywords with volume, difficulty and search intent, $2 per 1,000 keywords.
- [Competitor Keywords](https://apify.com/saliga/competitor-keywords): every Google keyword a domain or page ranks for, and its organic competitors, $2 per 1,000 rows.
- [Google SERP Rank Tracker](https://apify.com/saliga/serp-rank-tracker): Google positions for your keywords by country and device, with AI Overview checks, $2 per 1,000 result pages.
- [Google Trends API](https://apify.com/saliga/google-trends): interest over time, by region and related queries for hundreds of keywords, $6 per 1,000 queries.
- [Keyword Search Volume](https://apify.com/saliga/keyword-search-volume): Google Ads search volume, CPC and up to 48 months of trend for a keyword list, $2 per 1,000 keywords.
- [Sitemap Extractor](https://apify.com/saliga/sitemap-extractor): every URL a website lists in its sitemaps, with lastmod, images and hreflang, $0.25 per 1,000 URLs.
- [Broken Link Checker](https://apify.com/saliga/broken-link-checker): crawl a site and find broken links and images, with the pages they are on.
- [Tech Stack Detector](https://apify.com/saliga/tech-stack-detector): which CMS, ecommerce platform, analytics and hosting a website uses, $1.50 per 1,000 websites.
- [Website Screenshot + Change Detection](https://apify.com/saliga/website-screenshot-change-detection): screenshots of many URLs on desktop and mobile, with visual change detection between runs.
- [Dataset Merge & Dedup Datasets](https://apify.com/saliga/dataset-merge-dedupe): merge, dedupe and filter the results of several runs into one dataset.

# Actor input Schema

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

Domains (example.com), subdomains or, in bulk mode, single pages. Up to 50,000 per run.

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

Bulk: organic and paid keyword counts and estimated clicks, 1,000 domains per lookup (cheapest). Detailed: adds top-3/top-10 counts, new and lost keywords and traffic value, one lookup per domain.

## `countries` (type: `array`):

Up to 10 countries: two-letter codes (US, GB, DE) or names. Each domain gets one row per country. Covered countries are listed in the README.

## `language` (type: `string`):

Optional language code such as en, es or de. Leave empty to use each country's main language.

## `domainsUrl` (type: `string`):

Link to a text file (one domain per line), a CSV with a domain or url column, or a JSON list.

## `datasetId` (type: `string`):

Use the output of another Actor. Set the field name below.

## `domainField` (type: `string`):

The column or field that holds the domain or URL. domain, url, website and target are found without setting this.

## Actor input object example

```json
{
  "domains": [
    "asana.com",
    "monday.com",
    "clickup.com"
  ],
  "mode": "bulk",
  "countries": [
    "US"
  ],
  "domainField": "domain"
}
```

# Actor output Schema

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

One row per domain and country.

## `fullResults` (type: `string`):

Every field.

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

Counts for the run and why it stopped.

# 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": [
        "asana.com",
        "monday.com",
        "clickup.com"
    ],
    "countries": [
        "US"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("saliga/domain-seo-overview").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": [
        "asana.com",
        "monday.com",
        "clickup.com",
    ],
    "countries": ["US"],
}

# Run the Actor and wait for it to finish
run = client.actor("saliga/domain-seo-overview").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": [
    "asana.com",
    "monday.com",
    "clickup.com"
  ],
  "countries": [
    "US"
  ]
}' |
apify call saliga/domain-seo-overview --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,saliga/domain-seo-overview"
        }
    }
}
```

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/pPJi1TljOScIOmywW/builds/fcm55Z8b5Ehr3hJMS/openapi.json
