# Competitor Keywords, Ranked Keywords & Keyword Gap (`precisionlabs/competitor-keywords`) Actor

Get the organic Google keywords any domain ranks for, its SEO competitors, and your keyword gap (content gap): keywords competitors rank for and you don't. With position, URL, traffic, search volume, CPC, keyword difficulty and intent. Semrush and Ahrefs alternative on an official API, 50 countries.

- **URL**: https://apify.com/precisionlabs/competitor-keywords.md
- **Developed by:** [Precision Labs](https://apify.com/precisionlabs) (community)
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 ranked keywords

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

**See which Google keywords any website ranks for, who its real competitors are, and which keywords your competitors get traffic from that you don't.** Every keyword comes with its position, ranking page, estimated traffic, search volume, CPC, keyword difficulty and intent. No Semrush or Ahrefs subscription needed. Built by Precision Labs.

### What it does

Pick one of three modes:

- **Ranked keywords**: every keyword a domain ranks for in Google's top results, highest estimated traffic first. Use it to see where a competitor's traffic comes from, or to audit your own site.
- **Competitors**: the domains that rank for the same keywords as yours, with how many keywords you share and how big they are. Often these aren't the companies you'd name as competitors.
- **Keyword gap**: keywords your competitors rank for and your domain doesn't, with which competitor ranks best and with which page. This is the content gap: a ready list of topics to write about. Leave the competitor list empty and the Actor uses your top organic competitors.

The data covers 50 countries and their main languages. It comes from DataForSEO Labs, which tracks Google rankings for hundreds of millions of keywords and refreshes weekly.

### Who it's for

- **SEOs and content teams** planning what to write next, from what already works for competitors.
- **Agencies** pitching or auditing clients without paying for another seat.
- **AI agents and automations** (n8n, Make, Zapier, MCP clients) that need competitor and keyword data through an API, as clean rows.

### How to use it

1. Choose **What to find**.
2. Enter the **Domains**, such as `example.com`. For a keyword gap, also enter **Your domain**.
3. Pick the **Country**. The language defaults to the country's main one.
4. Click **Start**. Most runs finish in under a minute. Download the results as JSON, CSV or Excel, or get them through the API.

### Pricing

You pay only for data you get, with no subscription, and prices drop on Apify's paid plans. For example, the top 1,000 keywords of a domain cost $1.02 (52¢ on the Business plan).

| Event               | Free   | Starter | Scale   | Business | When                                                                                                      |
| ------------------- | ------ | ------- | ------- | -------- | --------------------------------------------------------------------------------------------------------- |
| `keyword-result`    | $0.001 | $0.0009 | $0.0008 | $0.0005  | Each ranked keyword, or each missing keyword in a keyword gap.                                            |
| `data-request`      | $0.02  | $0.02   | $0.02   | $0.02    | One lookup of up to 1,000 keywords or competitors for one domain. A keyword gap makes one per competitor. |
| `competitor-result` | $0.003 | $0.0027 | $0.0024 | $0.002   | Each competitor.                                                                                          |

| Example                                           | Free  | Starter | Scale | Business |
| ------------------------------------------------- | ----- | ------- | ----- | -------- |
| Top 100 keywords of one domain                    | $0.12 | $0.11   | $0.10 | $0.07    |
| Top 1,000 keywords of one domain                  | $1.02 | $0.92   | $0.82 | $0.52    |
| 10 competitors of one domain                      | $0.05 | $0.05   | $0.04 | $0.04    |
| Keyword gap against 5 competitors, 1,000 keywords | $1.10 | $1.00   | $0.90 | $0.60    |

**Never charged:** domains that aren't valid, and domains with no data. **No request fee** when you repeat a lookup (same domain and settings) within the same week: the results come from your own Apify storage. Set **Maximum cost per run** and the Actor never fetches more than that budget can pay for.

### Input

| Field                             | What it does                                                                                      |
| --------------------------------- | ------------------------------------------------------------------------------------------------- |
| **What to find**                  | Ranked keywords, competitors, or keyword gap.                                                     |
| **Domains**                       | Domains to look up, one per line. In keyword gap mode, the competitors to compare with.           |
| **Your domain**                   | Keyword gap only: the site to find missing keywords for.                                          |
| **Country** / **Language**        | Which Google to measure.                                                                          |
| **Max keywords per domain**       | Ranked keywords per domain, or missing keywords in total for a keyword gap. Default 1,000.        |
| **Max competitors**               | Competitors per domain, or how many to compare with in a keyword gap. Default 10.                 |
| **Top positions only**            | Only count rankings in the top N. Default 20, the first two pages.                                |
| **Min monthly searches**          | Skip rarely searched keywords.                                                                    |
| **Include close variants**        | List plurals and spelling variants separately. Off by default.                                    |
| **Leave out giant sites**         | Keep Wikipedia, YouTube, Amazon and similar out of competitor lists. On by default.               |
| **Include navigational keywords** | Keyword gap only: include searches for a specific site, such as "facebook login". Off by default. |

Example input for a keyword gap through the API:

```json
{
    "mode": "gap",
    "yourDomain": "budgetbytes.com",
    "domains": ["seriouseats.com", "allrecipes.com"],
    "location": "2840",
    "maxResults": 500
}
```

### Output

Each row has a `type`: `ranked`, `competitor`, `gap`, or `error`. A ranked keyword (real data, October 2026):

```json
{
    "type": "ranked",
    "domain": "backlinko.com",
    "keyword": "google trends",
    "position": 9,
    "url": "https://backlinko.com/hub/content/google-trends",
    "title": "Google Trends: What Is It & How to Use It for SEO",
    "rankChange": "up",
    "estimatedTraffic": 3178,
    "trafficValueUsd": 25773.02,
    "searchVolume": 368000,
    "cpcUsd": 8.11,
    "competition": "low",
    "keywordDifficulty": 54,
    "intent": "informational",
    "trendYearOverYearPct": -18,
    "location": "United States",
    "language": "English",
    "fetchedAt": "2026-10-26T12:00:00.000Z"
}
```

A competitor:

```json
{
    "type": "competitor",
    "domain": "backlinko.com",
    "competitor": "semrush.com",
    "sharedKeywords": 4816,
    "avgPositionShared": 6.1,
    "competitorKeywords": 98888,
    "competitorTop3": 13821,
    "competitorTop10": 39054,
    "competitorEstimatedTraffic": 978907,
    "competitorTrafficValueUsd": 3493721.07,
    "location": "United States",
    "language": "English",
    "fetchedAt": "2026-10-26T12:00:00.000Z"
}
```

A keyword gap row lists every competitor that ranks for the keyword (here, a keyword Serious Eats ranks for and Budget Bytes doesn't):

```json
{
    "type": "gap",
    "yourDomain": "budgetbytes.com",
    "keyword": "tiramisu",
    "searchVolume": 450000,
    "cpcUsd": 0.34,
    "competition": "low",
    "keywordDifficulty": 35,
    "intent": "informational",
    "trendYearOverYearPct": 0,
    "competitorCount": 1,
    "bestPosition": 5,
    "bestCompetitor": "seriouseats.com",
    "bestUrl": "https://www.seriouseats.com/best-tiramisu-recipe",
    "competitors": [
        {
            "domain": "seriouseats.com",
            "position": 5,
            "url": "https://www.seriouseats.com/best-tiramisu-recipe",
            "estimatedTraffic": 5206
        }
    ],
    "location": "United States",
    "language": "English",
    "fetchedAt": "2026-10-26T12:00:00.000Z"
}
```

The dataset has a view for each mode, so the table shows the right columns.

### FAQ

#### Where does the data come from?

From DataForSEO Labs, through the DataForSEO API. DataForSEO checks Google results for hundreds of millions of keywords and refreshes the database weekly; search volume and CPC are Google Ads data. This Actor isn't affiliated with, or endorsed by, Google, DataForSEO, Semrush, Ahrefs, or any site named in the examples. Those examples are real output for public websites, used only to show what the data looks like.

#### How accurate is the estimated traffic?

It's an estimate: the keyword's search volume times the typical click-through rate for that position. It's good for comparing keywords and domains with each other, not for predicting exact visits. Semrush and Ahrefs estimate traffic the same way, and their numbers differ from each other too.

#### Why does a big site's keyword gap include other brands' names?

Some sites, especially SEO tools, publish a page about every website, so they rank for searches like "kisskh". Google often labels these as informational searches, so the navigational filter doesn't catch them. Compare with competitors in your own market, or raise **Min monthly searches** and sort by keyword difficulty.

#### Why does my site have no keywords?

The database covers keywords with measurable search volume where you rank in the top 100. A new or small site may not have any yet, or may rank in another country. Error rows are free.

#### Do I need a Semrush, Ahrefs or DataForSEO account?

No. You only need an Apify account.

#### Why is there a new storage in my account?

The Actor keeps this week's lookups in a key-value store called `precisionlabs-competitor-keywords-cache` in your own account, so repeating a lookup skips the request fee. You can delete it at any time.

#### Something looks wrong?

Open an issue on the **Issues** tab with the domain and settings, and we'll look into it.

### More from Precision Labs

- [Keyword Search Volume & CPC](https://apify.com/precisionlabs/keyword-search-volume): Google Keyword Planner search volume, CPC and trends for up to 100,000 keywords per run.
- [Backlink Checker, Domain Rank & Link Gap](https://apify.com/precisionlabs/backlink-checker): backlinks, referring domains and domain rank for any site, in bulk, plus sites that link to your competitors but not to you.
- [Poland Company Check](https://apify.com/precisionlabs/poland-company-check): check Polish companies by NIP, KRS or REGON, with the VAT whitelist.

# Actor input Schema

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

<b>Ranked keywords</b>: the Google keywords each domain ranks for, with position, URL and estimated traffic. <b>Competitors</b>: the domains that rank for the same keywords. <b>Keyword gap</b>: keywords your competitors rank for and <b>Your domain</b> doesn't.

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

One domain per line, such as <code>example.com</code>. Full URLs and <code>www.</code> are fine. For <b>Keyword gap</b>, these are the competitors to compare with; leave empty to use the domain's top organic competitors.

## `yourDomain` (type: `string`):

The site to find missing keywords for, such as <code>example.com</code>. Only used in <b>Keyword gap</b> mode.

## `location` (type: `string`):

Which Google to measure: rankings and search volumes differ by country. Use the Google Ads location code, such as 2840 (United States), 2826 (United Kingdom) or 2276 (Germany).

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

Search language. Each country has data for its main languages only, for example English or Spanish in the United States; the run tells you which if you pick another.

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

For <b>Ranked keywords</b>, the most keywords per domain, highest estimated traffic first. For <b>Keyword gap</b>, the most missing keywords in total (up to 1,000 from each competitor).

## `maxCompetitors` (type: `integer`):

For <b>Competitors</b>, how many to return per domain. For <b>Keyword gap</b> without a competitor list, how many top competitors to compare with (up to 20; each one is a data request).

## `maxPosition` (type: `integer`):

Only count rankings in Google's top N. 20 covers the first two pages; 100 includes everything DataForSEO tracks.

## `minSearchVolume` (type: `integer`):

Skip keywords searched less often than this.

## `includeCloseVariants` (type: `boolean`):

Off: near-duplicates such as plurals and spelling variants are folded into one keyword. On: list every variant.

## `excludeBigSites` (type: `boolean`):

Leave sites like Wikipedia, YouTube and Amazon out of competitor lists. They rank for almost everything, so they're rarely useful competitors.

## `includeNavigational` (type: `boolean`):

Off: the keyword gap skips searches for a specific site or brand, such as "facebook login", which you usually can't win.

## Actor input object example

```json
{
  "mode": "ranked",
  "domains": [
    "backlinko.com"
  ],
  "location": "2840",
  "language": "auto",
  "maxResults": 20,
  "maxCompetitors": 10,
  "maxPosition": 20,
  "minSearchVolume": 0,
  "includeCloseVariants": false,
  "excludeBigSites": true,
  "includeNavigational": false
}
```

# Actor output Schema

## `results` (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": [
        "backlinko.com"
    ],
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("precisionlabs/competitor-keywords").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": ["backlinko.com"],
    "maxResults": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("precisionlabs/competitor-keywords").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": [
    "backlinko.com"
  ],
  "maxResults": 20
}' |
apify call precisionlabs/competitor-keywords --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,precisionlabs/competitor-keywords"
        }
    }
}
```

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/UJ0ieUHiKXhOJSEAU/builds/ndSeWP0wqnO8bTanX/openapi.json
