# Competitor Keyword Research - See Any Site's Ranked Keywords (`doesaiknow/doesaiknow-competitor-keywords-apify`) Actor

See every keyword any competitor ranks for in Google - volume, difficulty, intent & traffic value - plus the keyword gap vs your own domain. Live native SEO data, no scraping, no broken tools. Semrush & Ahrefs alternative - pay per keyword, no subscription.

- **URL**: https://apify.com/doesaiknow/doesaiknow-competitor-keywords-apify.md
- **Developed by:** [Dawid S](https://apify.com/doesaiknow) (community)
- **Categories:** SEO tools, AI, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 per delivered 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Competitor Keyword Research — See Any Site's Ranked Keywords (+ Keyword Gap) · Semrush / Ahrefs Alternative API

**Paste any competitor's domain → get every keyword it ranks for in Google**, each with search
volume, keyword difficulty, search intent, exact ranking position, ranking URL and estimated
traffic value. Then flip to **keyword-gap mode** to see exactly where a competitor ranks and
**you don't** — your content roadmap, ranked by opportunity.

Built on **live native SEO data straight from Google's index** — *not* a scrape of a third-party
SEO tool. That's the whole point: tools that scrape Ahrefs/Semrush dashboards break the moment
the dashboard changes and risk being shut off. This pulls the data natively, so your runs don't
silently die.

**Pay per keyword. No subscription. No seat. No login.** A full 1,000-keyword competitor teardown
costs about the price of a coffee.

---

### ⚡ Quick Start — try in 30 seconds

1. Click **Try for free**.
2. Leave the prefilled input (`target: "ahrefs.com"`), or paste any domain you want to dissect.
3. **Start** → in seconds you get a clean table of the keywords that domain ranks for.

```json
{ "target": "ahrefs.com", "maxKeywords": 100 }
````

Want the gap vs your own site? Add one field:

```json
{ "mode": "gap", "target": "ahrefs.com", "compareToDomain": "yourdomain.com", "maxKeywords": 500 }
```

***

### 🎯 What this actor does

Two jobs, one actor:

#### Mode A — Ranked keywords (default)

Input a domain → every keyword it ranks for in Google organic, with the full picture per keyword:
volume, keyword difficulty (0–100), search intent, the exact position it holds, the page that
ranks, and the estimated traffic that keyword sends. Sort/filter to find a competitor's biggest
organic assets in minutes.

#### Mode B — Keyword gap

Input a competitor **and** your own domain → the shared keyword universe with **both** domains'
positions side by side, plus a `gap_type` on every row:

| `gap_type` | meaning | what to do |
|---|---|---|
| `missing` | they rank, you don't appear | net-new content opportunity |
| `weaker` | you rank, but below them | optimize / build links |
| `stronger` | you outrank them | defend, monitor |
| `tied` | same position bracket | push for the edge |

Filter to `missing` + low difficulty + high volume = a prioritized content roadmap, generated from
real ranking data instead of guesswork.

***

### 💰 Pricing — pay per keyword, no subscription

You're charged **per keyword delivered**, on success only. Empty results and failed runs cost
nothing. Apify automatically discounts the per-keyword price on higher plans (Bronze → Gold).

| What you run | Keywords delivered | Approx. cost (Gold) |
|---|---:|---:|
| Quick competitor peek | 100 | ~$0.25 |
| Standard competitor report | 1,000 | ~$2.50 |
| Deep teardown | 3,000 | ~$7.50 |
| Keyword-gap (you vs them) | 1,000 | ~$2.50 |

Compare that to a Semrush/Ahrefs seat (subscription, from ~$100+/mo, login required). Here there's
no seat and no monthly commitment — run a teardown when you're pitching a client or planning a
quarter, pay for exactly those keywords, done.

> **Cost control:** every run is hard-capped (`maxKeywords`, default 250, max 5,000) so a single
> run can never run away with your credits.

***

### 🆚 How this compares

#### vs. Ahrefs / Semrush / Moz (the SaaS dashboards)

Same core data — the keywords a domain ranks for + the gap vs yours — but **pay-per-scan instead
of a monthly seat**, delivered as **clean JSON over an API** (and MCP), ready to drop into a sheet,
a pipeline, or an AI agent. No login, no per-seat pricing, no UI to click through.

#### vs. other Apify "SEO scraper" actors

Most competing actors **scrape a third-party SEO tool's dashboard**. That's fragile (the scrape
breaks when the dashboard's HTML changes), slow, and on shaky terms-of-service ground. This actor
reads **live native SEO data** instead — so it doesn't break when someone else redesigns a page,
and there's no third-party account in the loop.

#### vs. building it yourself on a raw SEO data API

You *could* wire up a raw data provider — then build pagination, the filter layer, the gap logic,
intent + difficulty enrichment, and a stable output schema yourself. This actor is that work,
finished: ranked + gap modes, difficulty and intent already on every row, traffic value, content
hashing, clean schema, one call.

***

### 🛡️ The reliability moat — native data, not a scrape

The single most important thing about this actor: **it does not scrape a SaaS SEO tool.** It reads
ranking data natively from Google's search surface. Practically, that means:

- **Runs don't silently die** when a third-party dashboard ships a redesign.
- **No third-party account** to get rate-limited or banned.
- **Difficulty + search intent arrive with the ranking data** in one pass — no second lookup.

If you've been burned by an Apify "Ahrefs/Semrush scraper" that worked for a month and then started
returning empty rows, this is the fix.

***

### 📊 What you get — output fields

One dataset item **per ranked keyword**:

| Field | Description |
|---|---|
| `keyword` | the search term the domain ranks for |
| `search_volume` | monthly Google searches (location-specific) |
| `cpc` | cost-per-click signal (commercial value) |
| `competition_level` | LOW / MEDIUM / HIGH |
| `keyword_difficulty` | 0–100 ranking difficulty (see coverage note below) |
| `search_intent` | informational / commercial / transactional / navigational |
| `competitor_domain` | the domain analyzed |
| `competitor_rank` | exact organic position held |
| `competitor_url` | the page that ranks |
| `estimated_traffic_value` | estimated traffic value of that ranking |
| `is_featured_snippet` | whether it holds the featured snippet |
| **Gap mode adds:** | |
| `your_domain` / `your_rank` / `your_url` | your side of the comparison (`your_rank` null = you don't rank) |
| `gap_type` | missing / weaker / stronger / tied |
| **Always:** | |
| `location`, `language`, `content_hash` | locale + a stable dedup hash per keyword |

> **Note on `keyword_difficulty` coverage.** Difficulty data is densest in major markets
> (US / UK / DE / …). For some smaller-market or non-English locales the underlying SEO data has
> sparse difficulty coverage and returns `0` for many keywords — that's a data-availability limit
> of the source, not a scoring error. Every other field (search volume, intent, rank, ranking URL,
> estimated traffic value) is unaffected and fully populated. Tip: run with the target's native
> `location` / `language` for the most relevant volumes, and lean on `search_volume` + `competitor_rank`
> when difficulty is unavailable for your market.

***

### 🚀 Input — what you pass in

| Field | Type | Default | Notes |
|---|---|---|---|
| `target` | string | — | **required.** Competitor domain (e.g. `ahrefs.com`) |
| `mode` | enum | `ranked` | `ranked` or `gap` |
| `compareToDomain` | string | — | required in `gap` mode — your domain |
| `maxKeywords` | int | 250 | 1–5,000 |
| `location` | string | `United States` | any supported location |
| `language` | string | `English` | any supported language |
| `minVolume` | int | 0 | filter |
| `maxKeywordDifficulty` | int | 100 | filter (0–100) |
| `intentFilter` | array | `[]` | subset of the four intents |
| `positionFrom` / `positionTo` | int | 1 / 100 | rank range |

***

### 📦 Sample output

**Ranked mode** (`target: "ahrefs.com"`):

```json
{
  "keyword": "keyword generator",
  "search_volume": 90,
  "competition_level": "LOW",
  "keyword_difficulty": 40,
  "search_intent": "informational",
  "competitor_domain": "ahrefs.com",
  "competitor_rank": 1,
  "competitor_url": "https://ahrefs.com/keyword-generator",
  "estimated_traffic_value": 27.36,
  "is_featured_snippet": false,
  "location": "United States",
  "language": "English",
  "content_hash": "a1b2c3d4e5f60718"
}
```

**Gap mode** (competitor `ahrefs.com` vs your `moz.com`):

```json
{
  "keyword": "googlebot",
  "search_volume": 550000,
  "keyword_difficulty": 26,
  "competitor_domain": "ahrefs.com",
  "competitor_rank": 8,
  "your_domain": "moz.com",
  "your_rank": 29,
  "gap_type": "weaker",
  "location": "United States",
  "language": "English"
}
```

***

### 🧭 Who this is for

- **SEO agencies** — instant competitor teardowns for pitches and audits, no extra seat.
- **Content teams** — a `missing` + low-difficulty gap list is a ready content roadmap.
- **Founders / marketers** — see what's actually winning organic traffic for rivals.
- **Developers / AI agents** — clean JSON + MCP; drop ranked-keyword + gap data into any pipeline.

***

### ⏱️ Scale & speed

A typical 1,000-keyword report returns in seconds. Larger pulls paginate automatically up to the
5,000-keyword cap. Need ongoing monitoring? Schedule the actor — each run is independent and
priced per keyword.

***

### 🛡️ Legal & compliance

Reads **public search-results data** only — the same organic rankings anyone sees in Google. No
logins, no paywalled data, no third-party SEO-tool accounts. You control the domains and locations
you query.

***

### 🧰 FAQ

**How do I see what keywords a competitor ranks for?**
Paste their domain as `target`, run, and you get every keyword they rank for with volume,
difficulty, intent, position and traffic value.

**How do I find the keyword gap between two websites?**
Set `mode: "gap"`, `target` = competitor, `compareToDomain` = your site. Every row shows both
positions and a `gap_type`. Filter to `missing` for net-new opportunities.

**What is a content gap analysis?**
Finding the keywords a competitor ranks for that you don't — exactly what gap mode's `missing`
rows give you, prioritized by volume and difficulty.

**Is this a Semrush / Ahrefs alternative?**
For the competitor-keyword and keyword-gap job: yes — same data, pay-per-scan instead of a monthly
seat, as an API/MCP instead of a dashboard.

**Do I need a subscription?**
No. You pay per keyword delivered, on success only. No subscription, no seat, no login.

**Where does the data come from — is it accurate?**
Live native SEO data from Google's search surface (not a scraped dashboard). Difficulty and intent
come with the ranking data in the same pass.

**Does it work for non-US / non-English domains?**
Yes — set `location` and `language` to any supported market.

**What does a competitor report cost?**
About $2.50 for 1,000 keywords on the Gold tier; ~$0.25 for a 100-keyword peek. You're never
charged for empty or failed runs.

**How do I keep costs predictable?**
Every run is capped by `maxKeywords` (default 250, max 5,000), so one run can't drain your credits.

***

### 🗺️ Roadmap

**Shipped (v1.0):** ranked-keyword mode, keyword-gap mode, difficulty + intent + traffic value on
every row, location/language, volume/difficulty/intent/position filters, pay-per-keyword.

**Coming soon (v0.2):** `onlyNewSinceLastRun` delta feed (only keywords that changed since your
last run) · standalone search-intent + difficulty mode · multi-competitor share-of-voice.

***

### 🏷️ Keywords

competitor keyword research, competitor keyword analysis, ranked keywords, see what keywords a site
ranks for, keyword gap analysis, content gap analysis, competitor analysis seo, find competitor
keywords, semrush alternative, ahrefs alternative, moz alternative, spyfu alternative, similarweb
alternative, ranked keywords api, seo data api, competitor keyword api, keyword research api, domain
keyword research, organic competitor analysis, keyword difficulty api, search intent api, pay per
scan seo, no subscription seo tool, mcp seo, seo data api.

***

### 🤝 Built by doesaiknow

Part of the **doesaiknow** competitive-SEO + market-intelligence suite — runs great on its own,
even better together:

- **[Keyword Metrics API](https://apify.com/doesaiknow/doesaiknow-keyword-metrics-apify)** — bulk Google + Bing search volume, CPC & 12-month trend for any keyword list.
- **[AI Keyword Clustering Tool](https://apify.com/doesaiknow/ai-keyword-clustering-tool-topical-clustering-bulk-serp)** — group keywords into an AI topical map + content clusters, validated with live SERPs.
- **[AI Brand Visibility Tracker](https://apify.com/doesaiknow/ai-brand-visibility-tracker-chatgpt-perplexity-gemini)** — see how your brand shows up across ChatGPT, Perplexity & Gemini answers.
- **[Seeking Alpha API — News & Dividend Data](https://apify.com/doesaiknow/seeking-alpha-api-news-dividend-data)** — news, earnings & dividend data for any ticker.

A natural workflow: pull a competitor's **ranked keywords** here → enrich with **volume/CPC** in
[Keyword Metrics](https://apify.com/doesaiknow/doesaiknow-keyword-metrics-apify) → organize into
**[clusters](https://apify.com/doesaiknow/ai-keyword-clustering-tool-topical-clustering-bulk-serp)**
for your content plan.

No subscription. Pay per scan. API + MCP-ready.

# Actor input Schema

## `target` (type: `string`):

The competitor domain to pull ranked keywords for, e.g. `ahrefs.com`. A full URL works too — the scheme/path are stripped automatically. One domain per run.

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

`ranked` = every keyword the competitor ranks for. `gap` = compare the competitor against your own domain (set `compareToDomain`) to find keyword gaps — keywords they rank for where you rank worse or not at all.

## `compareToDomain` (type: `string`):

Your own domain, e.g. `yoursite.com`. REQUIRED when `mode` = `gap`; ignored in `ranked` mode. Each row then carries both the competitor's rank and yours, plus a gap type (missing / weaker / stronger / tied).

## `maxKeywords` (type: `integer`):

How many keywords to return (you are charged per delivered keyword). 1–5000. Default 250; the demo prefill uses 50 for a fast, low-cost first run.

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

Search market as a full location name. Drives Google search volume + SERP locale. Defaults to United States.

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

Result language as a full language name. Defaults to English. Pair with the matching location (e.g. location `Poland`, language `Polish`).

## `minVolume` (type: `integer`):

Drop keywords with monthly search volume below this. 0 = no minimum (default).

## `maxKeywordDifficulty` (type: `integer`):

Keep only keywords at or below this difficulty (0–100). 100 = no cap (default). Lower it (e.g. 20) to surface easy-to-rank opportunities.

## `intentFilter` (type: `array`):

Keep only these search intents. Allowed values: `informational`, `commercial`, `transactional`, `navigational`. Leave empty for all intents.

## `positionFrom` (type: `integer`):

Lower bound on the competitor's Google rank (1 = top of page 1). Default 1.

## `positionTo` (type: `integer`):

Upper bound on the competitor's Google rank. Default 100. Set to 10 for page-1-only keywords.

## Actor input object example

```json
{
  "target": "ahrefs.com",
  "mode": "ranked",
  "maxKeywords": 50,
  "location": "United States",
  "language": "English",
  "minVolume": 0,
  "maxKeywordDifficulty": 100,
  "intentFilter": [],
  "positionFrom": 1,
  "positionTo": 100
}
```

# Actor output Schema

## `keywords` (type: `string`):

Default dataset link. One item per delivered ranked keyword (see dataset\_schema.json for per-field documentation).

# 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 = {
    "target": "ahrefs.com",
    "maxKeywords": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("doesaiknow/doesaiknow-competitor-keywords-apify").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 = {
    "target": "ahrefs.com",
    "maxKeywords": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("doesaiknow/doesaiknow-competitor-keywords-apify").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "target": "ahrefs.com",
  "maxKeywords": 50
}' |
apify call doesaiknow/doesaiknow-competitor-keywords-apify --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=doesaiknow/doesaiknow-competitor-keywords-apify",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Competitor Keyword Research - See Any Site's Ranked Keywords",
        "description": "See every keyword any competitor ranks for in Google - volume, difficulty, intent & traffic value - plus the keyword gap vs your own domain. Live native SEO data, no scraping, no broken tools. Semrush & Ahrefs alternative - pay per keyword, no subscription.",
        "version": "0.0",
        "x-build-id": "IOzl5eTj4FFuuaTJx"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/doesaiknow~doesaiknow-competitor-keywords-apify/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-doesaiknow-doesaiknow-competitor-keywords-apify",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/doesaiknow~doesaiknow-competitor-keywords-apify/runs": {
            "post": {
                "operationId": "runs-sync-doesaiknow-doesaiknow-competitor-keywords-apify",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/doesaiknow~doesaiknow-competitor-keywords-apify/run-sync": {
            "post": {
                "operationId": "run-sync-doesaiknow-doesaiknow-competitor-keywords-apify",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "target"
                ],
                "properties": {
                    "target": {
                        "title": "Competitor domain",
                        "type": "string",
                        "description": "The competitor domain to pull ranked keywords for, e.g. `ahrefs.com`. A full URL works too — the scheme/path are stripped automatically. One domain per run."
                    },
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "ranked",
                            "gap"
                        ],
                        "type": "string",
                        "description": "`ranked` = every keyword the competitor ranks for. `gap` = compare the competitor against your own domain (set `compareToDomain`) to find keyword gaps — keywords they rank for where you rank worse or not at all.",
                        "default": "ranked"
                    },
                    "compareToDomain": {
                        "title": "Your domain (gap mode only)",
                        "type": "string",
                        "description": "Your own domain, e.g. `yoursite.com`. REQUIRED when `mode` = `gap`; ignored in `ranked` mode. Each row then carries both the competitor's rank and yours, plus a gap type (missing / weaker / stronger / tied)."
                    },
                    "maxKeywords": {
                        "title": "Max keywords",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "How many keywords to return (you are charged per delivered keyword). 1–5000. Default 250; the demo prefill uses 50 for a fast, low-cost first run.",
                        "default": 250
                    },
                    "location": {
                        "title": "Location / market",
                        "enum": [
                            "United States",
                            "United Kingdom",
                            "Canada",
                            "Australia",
                            "Germany",
                            "France",
                            "Spain",
                            "Italy",
                            "Poland",
                            "Netherlands",
                            "Brazil",
                            "India",
                            "Mexico",
                            "Japan",
                            "Sweden"
                        ],
                        "type": "string",
                        "description": "Search market as a full location name. Drives Google search volume + SERP locale. Defaults to United States.",
                        "default": "United States"
                    },
                    "language": {
                        "title": "Language",
                        "enum": [
                            "English",
                            "German",
                            "French",
                            "Spanish",
                            "Italian",
                            "Polish",
                            "Dutch",
                            "Portuguese",
                            "Swedish",
                            "Japanese"
                        ],
                        "type": "string",
                        "description": "Result language as a full language name. Defaults to English. Pair with the matching location (e.g. location `Poland`, language `Polish`).",
                        "default": "English"
                    },
                    "minVolume": {
                        "title": "Minimum search volume",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Drop keywords with monthly search volume below this. 0 = no minimum (default).",
                        "default": 0
                    },
                    "maxKeywordDifficulty": {
                        "title": "Maximum keyword difficulty",
                        "minimum": 0,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Keep only keywords at or below this difficulty (0–100). 100 = no cap (default). Lower it (e.g. 20) to surface easy-to-rank opportunities.",
                        "default": 100
                    },
                    "intentFilter": {
                        "title": "Search intent filter",
                        "type": "array",
                        "description": "Keep only these search intents. Allowed values: `informational`, `commercial`, `transactional`, `navigational`. Leave empty for all intents.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "positionFrom": {
                        "title": "SERP position from",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Lower bound on the competitor's Google rank (1 = top of page 1). Default 1.",
                        "default": 1
                    },
                    "positionTo": {
                        "title": "SERP position to",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Upper bound on the competitor's Google rank. Default 100. Set to 10 for page-1-only keywords.",
                        "default": 100
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
