# Keyword Search Volume & CPC API: Difficulty, AI Overview (`koalabed/keyword-search-volume`) Actor

Analyze keywords or generate keyword ideas with Google search volume, CPC, competition, 12 month trends, keyword difficulty, intent, SERP features and AI Overview presence. Up to 1,000 keywords per run. Pay per keyword processed, no subscription.

- **URL**: https://apify.com/koalabed/keyword-search-volume.md
- **Developed by:** [Sama Alabed](https://apify.com/koalabed) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 keyword results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Keyword Search Volume & CPC API: Difficulty, AI Overview

Find out which keywords are worth targeting. For every keyword you get **Google search volume, CPC, ad competition, a 12-month trend, keyword difficulty, search intent, SERP features, whether Google shows an AI Overview**, and an **opportunity score** that sums it up. Analyze 2 to 1,000 keywords per run, or generate new keyword ideas from a few seed words.

$0.01 per keyword processed. No subscription, no per-request fee, no data-provider account or API key.

### Who it's for

- **SEO agencies and consultants:** size and prioritise keyword lists for many clients.
- **Content teams and bloggers:** pick topics with real demand and a realistic chance to rank.
- **PPC marketers:** check CPC and advertiser competition before building campaigns.
- **Automation builders:** enrich keyword lists inside Make, n8n, Zapier or your own scripts.
- **AI agents:** one call answers "how big is this keyword, how hard is it, and is Google answering it with AI?"

### Two modes

| Mode | You enter | You get |
|---|---|---|
| **Analyze my keywords** | Your own keywords (2 to 1,000 per run) | One row of data per keyword |
| **Generate keyword ideas** | 1 to 20 seed keywords, a maximum number of ideas (at least 2), and an optional minimum search volume | Related keyword ideas, each with the same data |

Pick a **Country** (24 Google markets). **Language** defaults to *Automatic*, the country's main language. Change it only for multilingual markets, such as French in Canada.

### How to use it (no code)

1. Choose **Analyze my keywords**.
2. Paste your keywords into **Keywords to analyze**. **Bulk edit** takes one keyword per line.
3. Pick the **Country** and click **Start**.
4. Sort the results table by **Opportunity** or **Monthly searches**, then export to CSV, Excel or JSON.

To find new topics, choose **Generate keyword ideas**, add a seed such as `podcast equipment`, set **Maximum ideas**, and click **Start**.

### What you get for each keyword

| Field | Meaning |
|---|---|
| `keyword`, `country`, `language` | What was looked up, and where |
| `found`, `data_status` | `true` / `ok` when the keyword has data. `false` / `no_data` when the provider has no search-volume data for it in this market: every metric is then empty (null), nothing is estimated, and the keyword is still billed as processed |
| `search_volume` | Average monthly Google searches |
| `monthly_searches` | The last 12 months, month by month |
| `trend` | Our `rising`, `stable` or `declining` label (from the yearly change), plus the monthly, quarterly and yearly % change |
| `cpc_usd` | Average cost per click in USD |
| `competition`, `competition_level` | Google Ads advertiser competition (0 to 1; LOW / MEDIUM / HIGH) |
| `low_top_of_page_bid_usd`, `high_top_of_page_bid_usd` | Top-of-page bid range |
| `keyword_difficulty` | How hard it is to rank organically (0 to 100) |
| `search_intent` | `informational`, `commercial`, `transactional` or `navigational` |
| `serp_features` | Google result types shown for the keyword: AI Overview, People Also Ask, featured snippet, local pack, video, shopping and more |
| `has_ai_overview` | `true` if Google showed an AI Overview for the keyword |
| `serp_checked_at` | Date of the Google results snapshot behind `serp_features` and `has_ai_overview` |
| `data_month`, `volume_updated_at` | The month the volume data describes, and when it was last refreshed |
| `opportunity_score`, `opportunity_factors` | Our 0 to 100 answer to "should I target this?", calculated by this Actor, with every factor that produced it |
| `request_id`, `generated_at`, `version`, `sources`, `warnings` | Provenance for automation and AI agents |

Each run also writes an `OUTPUT` record: keywords processed (billed), with data, without data, not processed (not billed), the charges Apify recorded for the run, and why a run stopped early.

#### About freshness

- **Search volume, CPC and competition** follow a monthly update cycle. `data_month` shows which month the numbers describe.
- **SERP features and the AI Overview flag** come from the latest available Google results snapshot for that keyword. That snapshot is often one to two months old, and `serp_checked_at` shows its date.
- **Use `has_ai_overview` as a strong signal, not a live check.** It is ideal for spotting which topics Google now answers with AI.

### Opportunity score (version `opp-v1`)

Calculated by this Actor with a simple, deterministic formula. It is not a Google or DataForSEO metric, no AI model is involved, and every factor is returned in `opportunity_factors`.

`opportunity_score = round(100 x volume x ease x intent x value x trend x ai_overview)`, capped at 100.

| Factor | How it is calculated |
|---|---|
| `volume` | min(1, log10(search\_volume + 1) / 5). 1,000 searches = 0.6; 100,000+ = 1.0 |
| `ease` | 1 - keyword\_difficulty / 100 (unknown = 0.5) |
| `intent` | transactional 1.0, commercial 0.9, informational 0.6, navigational 0.3 (unknown 0.6) |
| `value` | 0.9 + 0.2 x min(1, cpc\_usd / 5): higher CPC means more commercial value (unknown = 1.0) |
| `trend` | rising 1.1, stable 1.0, declining 0.85 (unknown 1.0) |
| `ai_overview` | 0.85 when Google shows an AI Overview for an informational query (fewer clicks), 0.95 for other intents, otherwise 1.0 |

### Pricing

**$0.01 per keyword processed** (shown as "Keyword result" on the Pricing tab), minimum 2 keywords per run. A processed keyword is billed even when the provider returns no search-volume data.

- **Processed** means the keyword was sent to the data provider and the request succeeded. You get one row for it, with data or marked `no_data`.
- **Not billed:** duplicates (removed first), keywords too long to send, keywords beyond your run limit or budget, refused runs and failed requests.
- **Minimum 2 keywords per run.** Every data request has a fixed cost, so each run needs at least 2 keywords (in ideas mode, a maximum of at least 2 ideas). Batch your keywords into one run rather than sending them one at a time.
- **Ideas mode:** each idea returned is one processed keyword. If fewer than 2 ideas come back, the 2-keyword minimum is billed.
- **There is no per-request fee or subscription.** Apify's standard Actor start fee, a fraction of a cent, applies to each run.
- **Your maximum cost per run is always respected.** It must cover at least 2 keyword results. The Actor only fetches as many keywords as your remaining budget can pay for, then stops cleanly and says so in `OUTPUT`.
- **Failed runs cost nothing.** If a run fails part way, you pay only for keywords already processed and delivered.
- **Users on Apify's free plan** can test with up to 10 keywords per run.

### Use it from code, automations and AI agents

The input is plain JSON, and every output row has the same flat structure.

**If a run is refused** (fewer than 2 keywords, or a maximum cost below 2 keyword results), it ends straight away with no rows. The reason is in the run's status message and in `OUTPUT.error`, and nothing is fetched or charged. Setting `maxIdeas` below 2 is rejected by Apify before the run starts.

**Analyze keywords (API, synchronous: returns the rows directly):**

```bash
curl -X POST "https://api.apify.com/v2/acts/koalabed~keyword-search-volume/run-sync-get-dataset-items" \
  -H "Authorization: Bearer YOUR_APIFY_TOKEN" -H "Content-Type: application/json" \
  -d '{"mode": "metrics", "keywords": ["keyword research tool", "best running shoes"], "country": "US"}'
```

**Generate keyword ideas:**

```json
{ "mode": "ideas", "seedKeywords": ["podcast equipment"], "maxIdeas": 200, "minSearchVolume": 100, "country": "GB" }
```

**Input reference:**

| Field | Type | Default | Notes |
|---|---|---|---|
| `mode` | `"metrics"` or `"ideas"` | `"metrics"` | |
| `keywords` | array of strings | none | Metrics mode; 2 to 1,000 (duplicates count once); max 80 characters and 10 words each |
| `seedKeywords` | array of strings | none | Ideas mode; up to 20 |
| `maxIdeas` | integer 2 to 1,000 | 100 | Ideas mode |
| `minSearchVolume` | integer | 0 | Ideas mode |
| `country` | two-letter code (US, GB, CA, AU, IN, IE, NZ, SG, ZA, DE, AT, CH, FR, BE, NL, ES, MX, IT, BR, PT, PL, SE, JP, AE) | `"US"` | |
| `language` | `"auto"` or a code offered for the country (en, es, fr, de, nl, it, pt, pl, sv, ja, hi, ar) | `"auto"` | |
| `includeSerpFeatures` | boolean | `true` | SERP features, AI Overview flag and snapshot date |

**Where it plugs in:**

- The official Apify clients for JavaScript and Python, Make, n8n, Zapier, Google Sheets and webhooks.
- Apify's MCP server, so assistants such as Claude or Cursor can call it as a tool (`koalabed--keyword-search-volume`).

A typical agent loop:

1. Draft candidate topics.
2. Call this Actor once in `metrics` mode with all of them (at least 2).
3. Keep rows with `data_status: "ok"` and `opportunity_score` above a threshold.
4. Deprioritise informational queries with `has_ai_overview: true`.

### Use cases

- **Agency client reporting:** refresh volumes and difficulty for every client's target list each month and export to Sheets or Looker Studio.
- **SEO content planning:** expand a seed topic into 200 ideas, filter by `minSearchVolume`, and sort by opportunity.
- **AI Overview risk audit:** check which of your traffic keywords now trigger an AI Overview (`has_ai_overview`, `serp_checked_at`).
- **PPC research:** compare `cpc_usd`, bid ranges and `competition_level` across markets before launching campaigns.
- **Automated pipelines:** enrich every new keyword from a CRM, spreadsheet or content brief tool through the API.
- **AI writing agents:** give an agent a grounded, structured view of demand and difficulty before it writes.

### Data source and accuracy

- **Volume data:** search volume, CPC, competition and bids are based on Google Ads data, provided through DataForSEO Labs.
- **Everything else:** difficulty, intent and SERP features come from the same provider's keyword and SERP database.
- **How to use volumes:** they are monthly averages, best for comparing and prioritising keywords rather than exact traffic forecasts.
- **Search intent labels** are refreshed less often than volumes.
- **New or very rare keywords may have no data.** They are returned with `data_status: "no_data"` and empty metrics, and billed as processed keywords.
- **What this Actor is:** it looks up and scores the keywords you submit, on demand. It is not a bulk keyword database export and not a search engine.

### Limits

- **Analyze my keywords:** 2 to 1,000 keywords per run (max 80 characters and 10 words each).
- **Generate keyword ideas:** up to 20 seeds and 2 to 1,000 ideas.
- **Free Apify plan:** up to 10 keywords per run.

### FAQ

**Is this the same as Google Keyword Planner?**
Volume, CPC, competition and bids are based on Google Ads data. Keyword Planner shows ranges to accounts without active ad spend; this Actor returns the averaged number.

**Why do I need at least 2 keywords?**
Each run makes a data request that has a fixed cost on top of the per-keyword cost. With a single keyword that fixed cost is larger than the keyword charge, so the minimum is 2. Sending many keywords in one run is also faster than one run per keyword.

**Why do some keywords come back with `data_status: "no_data"`?**
The data provider has no search-volume data for them in that market, usually because they are very new, very rare or misspelled. The keyword was still processed, so it is billed like any other. Check spelling and market before large runs.

**Do I pay for failed runs?**
No. If the data provider is unavailable, the run fails and nothing is charged. If it fails part way, you pay only for keyword rows already delivered. Invalid input is explained in the run's status message, and nothing is charged.

**Can I get Bing or YouTube volumes?**
Not yet. Tell us in the Issues tab if you need them.

# Actor input Schema

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

<b>Analyze my keywords</b>: get data for the exact keywords you enter below.<br><b>Generate keyword ideas</b>: start from one or more seed keywords and get related keywords with the same data (settings in the <i>Keyword ideas</i> section).

## `keywords` (type: `array`):

Enter the keywords you want to analyze. Use <b>+ Add</b> for one at a time or <b>Bulk edit</b> to paste many (one per line). Enter 2 to 1,000 per run (up to 10 on Apify's free plan); duplicates are removed automatically and not billed. At least 2 are required because every data request has a fixed cost. Used when <i>Analyze my keywords</i> is selected.

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

Choose the Google market used for search volume, CPC, competition and SERP data.

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

Language of the searches. <b>Automatic</b> uses the main language of the selected country (English for the United States). Pick a specific language only for multilingual markets, such as French in Canada or Spanish in the United States.

## `seedKeywords` (type: `array`):

Enter one or more seed keywords to generate related keyword ideas. Use <b>Bulk edit</b> to paste several (up to 20).

## `maxIdeas` (type: `integer`):

Maximum number of related keyword ideas to return (2 to 1,000). Each idea returned is one processed keyword, with or without search-volume data. If fewer than 2 come back, the 2-keyword minimum is billed.

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

Exclude keyword ideas below this monthly search volume. Leave at 0 to include every idea.

## `includeSerpFeatures` (type: `boolean`):

Adds the Google SERP features for each keyword and whether an AI Overview was present, from the latest available Google results snapshot. Each row shows that snapshot's date in <code>serp\_checked\_at</code>. Search volume and CPC follow their own monthly update cycle (<code>data\_month</code>).

## Actor input object example

```json
{
  "mode": "metrics",
  "keywords": [
    "keyword research tool",
    "best running shoes",
    "how to start a podcast"
  ],
  "country": "US",
  "language": "auto",
  "seedKeywords": [
    "podcast equipment"
  ],
  "maxIdeas": 100,
  "minSearchVolume": 0,
  "includeSerpFeatures": true
}
```

# Actor output Schema

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

One row per processed keyword: search volume, CPC, competition, 12-month trend, keyword difficulty, search intent, SERP features, AI Overview flag and opportunity score. A keyword the provider has no search-volume data for is returned with data\_status "no\_data" and empty metrics, and is billed as processed.

## `runSummary` (type: `string`):

Keywords processed (billed), with and without data, not processed (not billed), any minimum charge, the charges Apify recorded, and why a run stopped early.

# 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 = {
    "keywords": [
        "keyword research tool",
        "best running shoes",
        "how to start a podcast"
    ],
    "seedKeywords": [
        "podcast equipment"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("koalabed/keyword-search-volume").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 = {
    "keywords": [
        "keyword research tool",
        "best running shoes",
        "how to start a podcast",
    ],
    "seedKeywords": ["podcast equipment"],
}

# Run the Actor and wait for it to finish
run = client.actor("koalabed/keyword-search-volume").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 '{
  "keywords": [
    "keyword research tool",
    "best running shoes",
    "how to start a podcast"
  ],
  "seedKeywords": [
    "podcast equipment"
  ]
}' |
apify call koalabed/keyword-search-volume --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,koalabed/keyword-search-volume"
        }
    }
}
```

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/lhB4MUcnV7PHJOQCv/builds/71Jpz9ACqxVuL9igG/openapi.json
