# Google Keyword Planner MCP (`khadinakbar/google-keyword-planner-mcp`) Actor

Generate bounded Google Ads keyword ideas or historical metrics through DataForSEO. Returns normalized rows with source, targeting, monthly volume, competition, bid ranges, trend, timestamp, and terminal outcome records.

- **URL**: https://apify.com/khadinakbar/google-keyword-planner-mcp.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** SEO tools, MCP servers, Automation
- **Stats:** 1 total users, 0 monthly users, 50.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $450.00 / 1,000 google ads provider requests

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Google Keyword Planner MCP

Get bounded Google Ads keyword ideas or historical keyword metrics as structured, MCP-ready Apify dataset rows. The Actor uses the current DataForSEO Google Ads Live endpoints, which are based on Google Ads data. Each returned row preserves the requested targeting, monthly volume, competition, CPC and top-of-page bid fields, monthly trend, source, provider task ID, and timestamp.

Use it when an SEO, PPC, content, or product-marketing workflow needs a reproducible keyword-research snapshot rather than browser automation of Google Keyword Planner. For an observed SERP result rather than planning metrics, use the public [Google SERP All-in-One Scraper](https://apify.com/khadinakbar/google-serp-all-in-one-scraper) in the next step.

### What this Actor does

Choose one focused operation:

- `keyword_ideas` expands 1–20 seed terms into related Google Ads keyword ideas.
- `historical_metrics` checks 1–1000 known terms and returns their available historical metrics.

Both operations accept one optional geographic selector, language, search-partner setting, adult-keyword flag, and an output cap of 1–1000 rows. `keyword_ideas` accepts an upstream sort order. This is deliberately a narrow metrics-and-ideas tool: it does not create campaigns, change bids, access an advertiser account, or claim first-party Search Console traffic.

### How one workflow works

A B2B SaaS marketer starts with five product-language phrases. They run `keyword_ideas` in US English with a 200-row cap, sort by `search_volume`, and group the returned rows by the `keyword`, `searchVolume`, `competitionIndex`, and `cpcUsd` fields. They shortlist phrases with viable intent, then run `historical_metrics` on that shortlist before committing a content brief or PPC test.

Each dataset row captures its target location, language, search-network setting, `checkedAt`, `providerTaskId`, and source. That lets the marketer distinguish a real metric snapshot from a generic estimate when the research is reviewed later.

### Credentials and input

Set `DATAFORSEO_LOGIN` and `DATAFORSEO_PASSWORD` as encrypted Actor environment variables using the buyer-authorized credentials from [DataForSEO API access](https://app.dataforseo.com/api-access). The credentials are used only for the HTTPS Authorization header; they are never accepted as visible input or written to datasets, `OUTPUT`, or `RUN_SUMMARY`.

DataForSEO's Google Ads Live endpoints permit up to 20 idea seeds or 1000 metric terms per request and are rate limited by the provider. The Actor makes one bounded provider request per run, so a request remains auditable and does not conceal a fan-out of provider calls.

#### Example: keyword ideas

```json
{
  "operation": "keyword_ideas",
  "keywords": ["project management software", "team collaboration tool"],
  "locationCode": 2840,
  "languageCode": "en",
  "searchPartners": false,
  "includeAdultKeywords": false,
  "sortBy": "search_volume",
  "maxResults": 200
}
```

#### Example: historical metrics

```json
{
  "operation": "historical_metrics",
  "keywords": ["project management software", "team collaboration software"],
  "locationCode": 2840,
  "languageCode": "en",
  "dateFrom": "2025-08-01",
  "dateTo": "2026-07-31",
  "maxResults": 100
}
```

Set at most one of `locationCode`, `locationName`, or `locationCoordinate`; omit all three for worldwide targeting. `2840` is the DataForSEO location code for the United States. Dates use `YYYY-MM-DD`; the provider determines the actual available Google Ads data period. The upstream source may group near-exact variants or omit terms with no eligible data, so interpret a missing requested term as unmeasured rather than zero-volume.

### Dataset output

One dataset row represents one Google Ads keyword idea or known-term metrics response. Numeric fields can be `null` when Google Ads did not supply a value; null is preserved rather than turned into zero.

| Field | Meaning |
| --- | --- |
| `keyword` | Keyword returned by the Google Ads data source. |
| `searchVolume` | Available average monthly search volume, or `null`. |
| `competition` / `competitionIndex` | Google Ads competition level and available 0–100 index. |
| `cpcUsd` | Available provider-reported CPC in USD. |
| `lowTopOfPageBidUsd` / `highTopOfPageBidUsd` | Available top-of-page bid range in USD. |
| `monthlySearches` | Provider-reported monthly history for the requested period. |
| `closeVariants` | Related near-exact variants reported for known terms. |
| `locationCode`, `languageCode`, `searchPartners` | Exact targeting supplied to the provider. |
| `providerTaskId`, `providerCostUsd`, `source`, `checkedAt` | Provenance and cost boundary. |

Illustrative schema-valid row:

```json
{
  "runId": "example-run-id",
  "checkedAt": "2026-08-10T12:00:00.000Z",
  "operation": "keyword_ideas",
  "keyword": "project management tool",
  "locationCode": 2840,
  "locationName": null,
  "locationCoordinate": null,
  "languageCode": "en",
  "searchPartners": false,
  "searchVolume": 1300,
  "competition": "MEDIUM",
  "competitionIndex": 42,
  "cpcUsd": 8.71,
  "lowTopOfPageBidUsd": 4.2,
  "highTopOfPageBidUsd": 13.5,
  "monthlySearches": [{ "year": 2026, "month": 7, "searchVolume": 1200 }],
  "closeVariants": [],
  "categories": [],
  "provider": "dataforseo_google_ads",
  "providerTaskId": "example-provider-task-id",
  "providerCostUsd": 0.075,
  "source": "Google Ads data via DataForSEO",
  "warnings": []
}
```

The `keyword_metrics` dataset view is for the decision fields. `trend_and_provenance` keeps monthly history, close variants, provider task ID, cost, source, and warnings together for audit.

### Terminal outcomes

Every terminal run writes `OUTPUT`, `RUN_SUMMARY`, and `LAST_RUN_SUMMARY` before it exits.

- `COMPLETE`: every bounded returned row was persisted.
- `PARTIAL`: some provider rows were persisted and another row could not be written.
- `VALID_EMPTY`: the provider completed but returned no rows for the supplied targeting.
- `INVALID_INPUT`: fix the operation, keyword count/shape, location selector, language, or date range.
- `CONFIG_ERROR`: encrypted DataForSEO credentials are missing or unusable.
- `UPSTREAM_FAILED`: a valid request received no usable provider response, such as a credential rejection or rate limit.

`resultsTruncated: true` means the provider returned more rows than `maxResults`; this is an intentional output boundary. Inspect `providerResultCount` and the terminal outcome before summarizing results for an agent or stakeholder.

### Pricing and provider usage

The Actor uses Apify Pay per event with platform usage passed through to the user. A completed `google-ads-request` costs $0.45 after DataForSEO returns a response, including a valid empty response. Each persisted `keyword-result` costs $0.005, and Actor start costs $0.00005. The maximum event charge is `$0.45005 + ($0.005 × maxResults)` before separate platform usage; the live Apify Pricing tab is the source of truth.

DataForSEO usage is a separate provider charge billed to the configured DataForSEO account. The Actor records the provider-reported request cost in `RUN_SUMMARY.providerCostUsd` and on the first returned row, while subsequent rows carry `0` so that summing a dataset never multiplies a one-request provider charge. Check the DataForSEO account for the authoritative charge.

### API and MCP prompt

```bash
curl -X POST "https://api.apify.com/v2/acts/khadinakbar~google-keyword-planner-mcp/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "keyword_ideas",
    "keywords": ["project management software"],
    "locationCode": 2840,
    "languageCode": "en",
    "maxResults": 100
  }'
```

For an Apify MCP workflow, use this prompt card:

> Run `khadinakbar/google-keyword-planner-mcp` with `operation: keyword_ideas` for these seed terms in US English. Return the top bounded dataset rows with `keyword`, `searchVolume`, `competition`, `competitionIndex`, `cpcUsd`, bid range, monthly trend, `checkedAt`, and `source`. Read `OUTPUT` first, distinguish `VALID_EMPTY`, `PARTIAL`, and `UPSTREAM_FAILED`, and preserve null metrics as unavailable values.

Read the completed default dataset through the Actor output or Apify dataset API, then read `OUTPUT` and `RUN_SUMMARY` from the default key-value store. Paginate a large dataset instead of assuming the first page includes every row.

### Best-results guidance

- Use a precise location selector and language when the decision is market-specific; keep them unchanged across comparison runs.
- Start with a small, meaningfully different seed set. Idea expansion uses a maximum of 20 seeds because that is the current upstream boundary.
- Use `historical_metrics` for a preselected shortlist; it is the right operation for comparing known terms, not creating a keyword universe.
- Treat `searchVolume: null` as unavailable data, not a claim of no demand.
- Keep `maxResults` realistic. A higher cap can create more `keyword-result` charges and a larger dataset; every completed provider request also carries the documented $0.45 request event.
- Preserve `providerTaskId`, `source`, and `checkedAt` in reports so claims stay tied to their data source and date.

### Scope and responsible use

This Actor does not impersonate Google, create or modify ad campaigns, or expose a user's credentials. It reports the DataForSEO response derived from Google Ads data under the requested targeting. Google Ads and Keyword Planner may vary by account, policy, target, and data freshness; use this output as a dated planning input, not as a traffic or conversion guarantee. Use credentials you are authorized to operate and comply with applicable provider terms, advertising policies, and law.

### Source documentation

- [Google Ads API: generate keyword ideas](https://developers.google.com/google-ads/api/docs/keyword-planning/generate-keyword-ideas)
- [Google Ads API: generate historical metrics](https://developers.google.com/google-ads/api/docs/keyword-planning/generate-historical-metrics)
- [DataForSEO Google Ads Keywords Data overview](https://docs.dataforseo.com/v3/keywords_data-google_ads-overview/)
- [DataForSEO Google Ads Keywords For Keywords Live](https://docs.dataforseo.com/v3/keywords_data-google_ads-keywords_for_keywords-live/)
- [DataForSEO Google Ads Search Volume Live](https://docs.dataforseo.com/v3/keywords_data-google_ads-search_volume-live/)

### Builder's note

I built the provider request as one operation and one bounded call, then separated row normalization from runtime orchestration. That lets agents consume the same semantic fields for ideas and historical metrics, while preserving the things that change interpretation: targeting, null metrics, truncation, source, provider task ID, provider cost, and terminal outcome. It is a more reliable boundary than automating the Keyword Planner browser interface.

# Actor input Schema

## `operation` (type: `string`):

Choose `keyword_ideas` to expand up to 20 seed terms, or `historical_metrics` to retrieve metrics for up to 1000 known terms. Both use current Google Ads keyword data through DataForSEO.

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

For `keyword_ideas`, provide 1–20 seed terms. For `historical_metrics`, provide 1–1000 known terms. Each term must be 1–80 characters and at most 10 words. Near-exact variants can be combined by the upstream Google Ads data source.

## `locationCode` (type: `integer`):

Optional DataForSEO Google Ads location code. For example, 2840 is the United States. Leave blank for worldwide targeting. Set only one location selector.

## `locationName` (type: `string`):

Optional full DataForSEO Google Ads location name, such as `London,England,United Kingdom`. Set only one location selector.

## `locationCoordinate` (type: `string`):

Optional latitude,longitude location selector. Set only one location selector; the provider uses the containing country.

## `languageCode` (type: `string`):

DataForSEO Google Ads language code, such as `en` or `es`. Defaults to `en`. This is not a country selector.

## `searchPartners` (type: `boolean`):

Include Google search partners in the provider request. Defaults to false, which targets Google Search.

## `includeAdultKeywords` (type: `boolean`):

Request adult-associated terms from the provider. Google Ads may still return no data for restricted terms. Defaults to false.

## `sortBy` (type: `string`):

Used only for `keyword_ideas`. Sorts the upstream ideas before this Actor returns the bounded result set.

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

Maximum normalized rows written to the dataset. Defaults to 100 and caps at 1000. The provider can find more ideas; `providerResultCount` and `resultsTruncated` preserve that boundary.

## `dateFrom` (type: `string`):

Optional `YYYY-MM-DD` start date for Google Ads historical metrics, up to four years back. Omit for the provider's default period. Applies to both operations.

## `dateTo` (type: `string`):

Optional `YYYY-MM-DD` end date for Google Ads historical metrics. It cannot be later than yesterday; omit for the provider's default period. Applies to both operations.

## Actor input object example

```json
{
  "operation": "keyword_ideas",
  "keywords": [
    "project management software",
    "team collaboration tool"
  ],
  "locationCode": 2840,
  "locationCoordinate": "40.7128,-74.0060",
  "languageCode": "en",
  "searchPartners": false,
  "includeAdultKeywords": false,
  "sortBy": "relevance",
  "maxResults": 100
}
```

# Actor output Schema

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

One normalized Google Ads keyword idea or historical metric row.

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

Detailed terminal outcome, targeting, provider counts, errors, and cost.

## `compactOutput` (type: `string`):

Stable terminal output for agents and automations.

## `lastRunSummary` (type: `string`):

Compatibility alias for the detailed terminal record.

# 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 = {
    "operation": "keyword_ideas",
    "keywords": [
        "project management software",
        "team collaboration tool"
    ],
    "locationCode": 2840,
    "languageCode": "en",
    "searchPartners": false,
    "includeAdultKeywords": false,
    "sortBy": "relevance",
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/google-keyword-planner-mcp").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 = {
    "operation": "keyword_ideas",
    "keywords": [
        "project management software",
        "team collaboration tool",
    ],
    "locationCode": 2840,
    "languageCode": "en",
    "searchPartners": False,
    "includeAdultKeywords": False,
    "sortBy": "relevance",
    "maxResults": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/google-keyword-planner-mcp").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 '{
  "operation": "keyword_ideas",
  "keywords": [
    "project management software",
    "team collaboration tool"
  ],
  "locationCode": 2840,
  "languageCode": "en",
  "searchPartners": false,
  "includeAdultKeywords": false,
  "sortBy": "relevance",
  "maxResults": 100
}' |
apify call khadinakbar/google-keyword-planner-mcp --silent --output-dataset

```

## MCP server setup

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

```

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/877tiVYtcLdUai1rO/builds/Yn3fV1A7h0GY5K706/openapi.json
