# Keyword Search Volume & Ideas — Google Ads Data API (`tiger19935/keyword-search-volume-api`) Actor

Keyword research API: bulk Google search volume, CPC, competition and 24-month trends for up to 10,000 keywords, plus keyword ideas and seasonality. Bring your own DataForSEO account (BYOK): $0.50 per 1,000 keywords on top of your own DataForSEO usage.

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

## Pricing

from $0.40 / 1,000 keyword processed (own dataforseo account)s

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

## Keyword Search Volume & Ideas - Google Ads Data API

Get **Google search volume, CPC, competition and 24 months of history for up to 10,000 keywords in one run** - without a Google Ads account. Every keyword comes back with **computed trend metrics** (12-month average, 3-month momentum, year-over-year change, seasonality, peak month, rising / flat / falling) so you can sort, filter and decide straight away. Switch to **Ideas mode** to expand a few seed keywords into thousands of related keywords with the same data.

Data: Google Ads keyword data (the numbers behind Keyword Planner), delivered through **your own DataForSEO account** (you pay DataForSEO directly, about $0.09 per 1,000 keywords). You pay this Actor only $0.50 per 1,000 keywords with data. No subscription.

### Who is it for?

- **SEO and content teams** - size a topic, prioritise articles by volume and trend, find seasonal windows to publish in.
- **PPC and e-commerce managers** - compare CPC, top-of-page bids and competition before you bid; plan campaigns around the peak month.
- **Agencies and freelancers** - build keyword reports for many clients in different countries and languages without Keyword Planner limits.
- **AI agents and automations** - ask "which of these keywords is rising?" and get typed JSON back (works through the Apify MCP server, API, Make, Zapier or n8n).

### What data do you get?

| Field | Example | Meaning |
|---|---|---|
| `keyword`, `inputKeyword` | `crm software` / `CRM Software` | normalized keyword and the spelling you typed first |
| `seed` | `["crm software"]` | Ideas mode: the seed keyword(s) that produced the idea |
| `mode`, `location`, `locationCode`, `language` | `volume`, `United States`, `2840`, `en` | what was asked |
| `hasData` | `true` | `false` when Google has no data for the keyword (these rows are free) |
| `searchVolume` | `135000` | Google's average monthly searches (latest 12 months) |
| `cpc`, `lowBid`, `highBid` | `14.21`, `5.8`, `22.9` | average CPC and low/high top-of-page bid, USD |
| `competition`, `competitionIndex` | `HIGH`, `87` | Google Ads advertiser competition: LOW / MEDIUM / HIGH and 0-100 |
| `monthly[]` | `[{"month":"2024-11","volume":110000}, ...]` | up to 24 months, oldest first |
| `avg12` | `128750` | average of the last 12 months |
| `trend3m` | `0.0842` | last 3 months vs. the 3 months before (`0.0842` = +8.4%) |
| `yoy` | `0.1176` | latest month vs. the same month a year earlier |
| `seasonalityIndex` | `0.4218` | (highest - lowest month) / average over the last 12 months; `0` = flat all year |
| `peakMonth` | `November` | calendar month with the most searches in the last 12 months |
| `direction` | `rising` | `rising` if year-over-year (or, if missing, 3-month) change is at least +15%, `falling` at -15% or lower, otherwise `flat` |
| `fromCache`, `fetchedAt`, `source` | `false`, ISO time, `dataforseo:google_ads` | freshness and origin |

Ratios are rounded to 4 decimals. A metric is `null` when it cannot be computed (not enough months, zero baseline) - never `NaN`, never a guess.

### How to use it

1. Enter your **DataForSEO login** and **API password** (see *What you need* below).
2. Choose **Mode**: *Volume* (metrics for your keywords) or *Ideas* (expand seeds into related keywords).
3. Paste **keywords** - up to 10,000 in Volume mode, up to 200 seeds in Ideas mode.
4. Pick the **country** (48 Google geo targets, from the United States to Ukraine and Japan) and the **language**.
5. Optional: **minimum monthly search volume**, **max ideas** (Ideas mode), whether to **keep keywords without data**, and for how many days data may be **reused from your cache**.
6. Click **Start**, then download JSON, CSV or Excel - or call it from code.

Keywords are normalized (trimmed, lower-cased, wrapping quotes and duplicate spaces removed) and de-duplicated. Keywords Google does not accept (empty, longer than 80 characters, more than 10 words, emoji or symbols) are not sent anywhere and are listed with the reason in the run summary - you are never charged for them.

#### Example input - volume and trends for three keywords in the UK

```json
{
  "mode": "volume",
  "keywords": ["crm software", "email marketing", "project management tool"],
  "location": "2826",
  "language": "en",
  "cacheDays": 30,
  "dfsLogin": "you@example.com",
  "dfsPassword": "<your DataForSEO API password>"
}
```

#### Example input - 500 keyword ideas around two seeds in Germany

```json
{
  "mode": "ideas",
  "keywords": ["projektmanagement software", "crm system"],
  "location": "2276",
  "language": "de",
  "maxIdeas": 500,
  "minSearchVolume": 100,
  "dfsLogin": "you@example.com",
  "dfsPassword": "<your DataForSEO API password>"
}
```

#### Example output (one keyword, shortened history)

```json
{
  "keyword": "christmas lights",
  "inputKeyword": "Christmas Lights",
  "seed": null,
  "mode": "volume",
  "location": "United States",
  "locationCode": 2840,
  "language": "en",
  "hasData": true,
  "searchVolume": 450000,
  "cpc": 0.92,
  "lowBid": 0.35,
  "highBid": 1.74,
  "competition": "HIGH",
  "competitionIndex": 91,
  "monthly": [
    { "month": "2024-11", "volume": 1500000 },
    { "month": "2024-12", "volume": 1900000 },
    { "month": "2025-11", "volume": 1650000 },
    { "month": "2025-12", "volume": 2000000 }
  ],
  "avg12": 450000,
  "trend3m": 0.0812,
  "yoy": 0.0526,
  "seasonalityIndex": 4.2105,
  "peakMonth": "December",
  "direction": "flat",
  "fromCache": false,
  "fetchedAt": "2026-10-05T12:00:00.000Z",
  "source": "dataforseo:google_ads"
}
```

The run summary (`OUTPUT`) lists input and valid keyword counts, invalid keywords with reasons, duplicates, how many rows came from your cache, provider batches bought, failed batches, rows delivered, rows without data, charged events, why the run stopped early (if it did) and warnings. A short `RESULTS_MD` is saved next to it.

### Volume mode and Ideas mode

- **Volume** - one row per valid keyword you submit. Keywords are sent to Google Ads in batches of up to 1,000.
- **Ideas** - seeds are sent in groups of up to 20; each group can return up to 20,000 suggestions. The Actor merges and de-duplicates them across groups, drops anything under *Minimum monthly search volume*, sorts by volume and keeps the top *Max ideas* (up to 5,000). Each idea carries the `seed` that produced it. Ideas are stored in your cache too, so a follow-up Volume run on the same keywords costs no new batch.

### Your personal cache

Results are kept in a named key-value store called `kw-cache` **in your own Apify account** - nobody else can see it. Within *Reuse cached data for (days)* (default 30, `0` = always fresh) a repeated keyword for the same location and language is served from the cache: **no new batch is bought, no batch fee is charged**, and the row is marked `fromCache: true`. You still pay the per-keyword price because you receive the data. Delete the store any time to start fresh.

### Pricing

Pay per event - you pay only for results:

| Event | Price | When |
|---|---|---|
| `keyword-byok` | **$0.0005** ($0.50 per 1,000) | one row with data delivered (cache hits included) |

Keywords without data, invalid, duplicate, failed or filtered keywords are free. **Maximum cost per run** is always respected: the Actor stops with a clear note (`stoppedReason: "budget"`) instead of failing. Platform usage is included. DataForSEO charges you separately (about $0.09 per batch of up to 1,000 keywords); repeats within your cache window are not bought again.

Examples: 1,000 keywords with data = $0.50 here + about $0.09 at DataForSEO. 10,000 keywords = $5 + about $0.90.

### Demo mode

Run it without entering a DataForSEO login/password and you get up to 3 **illustrative sample rows** (`source: "demo-sample"`, warning "DEMO MODE") so you can see the output format. Nothing is billed. Enter your own DataForSEO account to get real Google Ads data.

### What you need: a DataForSEO account

This Actor works with **your own DataForSEO account**. Sign up at dataforseo.com, then enter your **login** and **API password** (from the DataForSEO dashboard; both stored as secrets and never logged or saved) in the input.

- you pay DataForSEO directly for the data (about $0.09 per batch of up to 1,000 keywords),
- this Actor charges only **$0.50 per 1,000 rows with data** (`keyword-byok`), with no batch fee,
- your keywords are cached, normalized and enriched with all computed trend metrics.

### Integrations and API

Send results to **Google Sheets, Airtable, BigQuery, Looker Studio, Slack or your SEO tool** via Make, Zapier or n8n, or call the Actor from code and AI agents (Apify API, Apify MCP server).

```bash
curl -X POST "https://api.apify.com/v2/acts/<USERNAME>~keyword-search-volume-api/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"keywords":["crm software","email marketing"],"location":"2840","language":"en"}'
```

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

const client = new ApifyClient({ token: '<YOUR_TOKEN>' });
const run = await client.actor('<USERNAME>/keyword-search-volume-api').call({ "mode": "ideas", "keywords": ["standing desk"], "maxIdeas": 300 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((k) => k.direction === 'rising').map((k) => `${k.keyword}: ${k.searchVolume}`));
```

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_TOKEN>")
run = client.actor("<USERNAME>/keyword-search-volume-api").call(run_input={"keywords": ["crm software"], "location": "2840", "language": "en"})
for k in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(k["keyword"], k["searchVolume"], k["direction"], k["peakMonth"])
```

#### Use it from an AI agent (MCP)

Add the Actor to the Apify MCP server and ask in plain language:

> Use the Keyword Search Volume Actor to check "crm software", "email marketing" and "project management tool" in the UK. Tell me which one is rising, which is most seasonal, and which has the highest CPC.

The input schema documents every field, so agents can fill it in without examples.

### FAQ

**Where does the data come from?** Google Ads keyword data - the same source as Google Keyword Planner - provided through the DataForSEO API. This Actor is not affiliated with Google, Google Ads or DataForSEO.

**Why are volumes round numbers?** Google reports *rounded average monthly searches*, not exact counts. Small keywords show as 10, 20, 30... and very large ones in coarse steps. Use the monthly history and the trend fields to compare keywords, not to count individual searches.

**Why does a keyword have no data?** Google has no volume for it in that location and language (new, very rare or restricted terms). These rows have `hasData: false`, all metrics `null`, and are free. Turn off *Keep keywords without data* to drop them.

**Are the numbers the same as in my Google Ads account?** They come from the same source but without your account's ranges: Keyword Planner shows buckets (for example "1K-10K") for accounts with little spend, while this API returns the average value.

**How fresh is it?** Google updates monthly data in the first weeks of each month. A fresh batch always asks for the last 24 months. Cached rows show their `fetchedAt` time; set *Reuse cached data for (days)* to `0` to force fresh data.

**What happens when I run out of budget or a batch fails?** Delivered rows are kept and charged correctly; the run summary tells you how many keywords were not processed (`notProcessed`) and why (`stoppedReason`, and `errors` with the affected keywords of a failed batch), and you are not charged for them. Re-run later - everything already fetched comes from your cache.

**Something is missing?** Open an issue in the *Issues* tab - extra locations, languages and data fields are welcome.

### More tools by the same author

- [Keyword Autocomplete Explorer](https://apify.com/tiger19935/keyword-autocomplete-explorer): Google, YouTube, Amazon and Bing suggestions
- [Google Ads Transparency Monitor](https://apify.com/tiger19935/google-ads-transparency-monitor): Track which ads advertisers run on Google
- [Website Screenshot API](https://apify.com/tiger19935/website-screenshot-api): Full-page, mobile and WebP screenshots

# Changelog

This Actor's version history is a separate document: https://apify.com/tiger19935/keyword-search-volume-api/changelog.md

# Actor input Schema

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

'Volume' returns metrics for exactly the keywords you list (up to 10,000). 'Ideas' takes up to 200 seed keywords and returns the best related keywords with their metrics, sorted by search volume.

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

One keyword or phrase per row. Volume mode: up to 10,000 keywords. Ideas mode: up to 200 seed keywords. Each keyword may have up to 80 characters and 10 words, and no emoji or symbols; invalid and duplicate entries are skipped and listed in the run summary (OUTPUT). Case does not matter.

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

Country whose Google searches are counted (Google geo-target country code).

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

Language of the searches (language code, e.g. en, de, fr, uk).

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

Ideas mode only: the maximum number of keyword ideas in the whole run (highest search volume first). You pay only for ideas you receive.

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

Skip keywords with a lower average monthly search volume (they are not saved and not charged). 0 keeps everything.

## `includeNoData` (type: `boolean`):

Volume mode only: also save a row (hasData = false) for keywords Google has no volume for. These rows are free. Turn off to save only keywords with data.

## `cacheDays` (type: `integer`):

Keywords you fetched earlier are served from your personal cache (a key-value store in your account) when the data is younger than this - no new batch fee. 0 = always fetch fresh data. Maximum 30.

## `dfsLogin` (type: `string`):

Your DataForSEO API login (usually your account e-mail). Needed for real data (together with the API password); leave both empty to get 3 sample demo rows. Stored encrypted.

## `dfsPassword` (type: `string`):

Your DataForSEO API password (from the DataForSEO dashboard, not your account password). Needed for real data. Stored encrypted.

## Actor input object example

```json
{
  "mode": "volume",
  "keywords": [
    "crm software",
    "email marketing",
    "project management tool"
  ],
  "location": "2840",
  "language": "en",
  "maxIdeas": 200,
  "minSearchVolume": 0,
  "includeNoData": true,
  "cacheDays": 30
}
```

# Actor output Schema

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

One row per keyword: search volume, CPC, competition, 24-month history and trend metrics.

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

Counts (rows, cache hits, purchased batches), invalid keywords with reasons, failed batches, charged events, stop reason and warnings.

## `markdown` (type: `string`):

Short Markdown summary of the run with the top keywords - convenient for AI agents.

# 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": [
        "crm software",
        "email marketing",
        "project management tool"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tiger19935/keyword-search-volume-api").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": [
        "crm software",
        "email marketing",
        "project management tool",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("tiger19935/keyword-search-volume-api").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": [
    "crm software",
    "email marketing",
    "project management tool"
  ]
}' |
apify call tiger19935/keyword-search-volume-api --silent --output-dataset

```

## MCP server setup

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

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/hOdTqknMBoREdGaTN/builds/NwFV3rmjY7u1v0BSd/openapi.json
