# Keyword Search Volume — Bulk Google Metrics (CPC & Trend) (`insights_data/keyword-search-volume`) Actor

Get Google search volume, CPC, ad competition and a 12-month trend for thousands of keywords in one run. Expand seed keywords into related ideas, target any country, and get intent, opportunity score and click estimates. No Google Ads account or API key needed.

- **URL**: https://apify.com/insights_data/keyword-search-volume.md
- **Developed by:** [Insights Data](https://apify.com/insights_data) (community)
- **Stats:** 4 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.20 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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

### What is Keyword Search Volume — Bulk Google Metrics (CPC & Trend)?

**Keyword Search Volume — Bulk Google Metrics (CPC & Trend)** is a bulk keyword search volume checker. It looks up Google keyword search volume, CPC, ad competition and 12 months of monthly searches for every keyword you paste, in one or more countries. It's built for SEO specialists, content marketers, PPC advertisers and agencies: just enter your keywords and click **Start**, with no coding and no Google Ads account. On the Apify Free plan you get up to **10 keyword rows per run**.

Every row also comes with trend analytics, search intent, a topic cluster, an opportunity score and click estimates, all calculated by the Actor from the same data. In **Ideas mode**, a few seed keywords grow into a list of related keyword ideas with the same metrics.

- **Keyword research for SEO:** rank article and page ideas by real demand before you write.
- **Google PPC keyword research:** use `cpc` and `competition` to plan Google Ads budgets and spot expensive terms.
- **Agency audits:** run bulk keyword search volume checks for client audits, content gap reviews and programmatic SEO pages.
- **Keyword trend analysis:** find rising, declining and seasonal keywords from 12 months of data.
- **Keyword search volume tracker:** schedule runs and see how each keyword's volume changes from run to run.
- **Data pipelines:** send clean rows to spreadsheets, BI dashboards or LLM workflows.

**You don't need a Google Ads account, an API key or cookies.** The volume, CPC and competition figures are Google Keyword Planner-based metrics. If you want to compare with the keyword search volume Google shows in its own [Google Keyword Planner](https://ads.google.com/home/tools/keyword-planner/), you need a Google Ads account there.

#### What can this keyword search volume tool do?

- 🔑 **Metrics mode:** measure exactly the keywords you give it, one row per keyword and country.
- 💡 **Ideas mode:** expand seeds into related keywords from Google, YouTube, Google Shopping and Amazon search suggestions and Google Trends related queries, then measure them.
- 📍 **Many markets in one run:** pick several countries, or **Worldwide (global)** to get keyword search volume worldwide.
- 💲 **Keyword CPC checker:** average cost per click and ad competition (LOW / MEDIUM / HIGH plus a 0-100 index) for each keyword.
- 📉 **Trend analytics:** trend direction, month, quarter and year change, peak and lowest month, seasonality and spike months.
- 🧬 **Keyword profile:** intent, question flag, length class, keyword clustering into topic groups, opportunity score and click estimates.
- 🎯 **Filters and sorting:** volume, CPC, competition, words, must / must-not contain terms, questions only, intent and trend direction.
- 📦 **Export and automate:** download JSON, CSV, Excel, XML or HTML, run it via API, schedule runs and connect it to other apps.
- 🌐 **No proxy setup:** it starts without a proxy and switches to Apify Proxy automatically when requests are blocked.

***

### What keyword search volume data can you get?

Each row is one keyword in one market. It puts keyword search volume and CPC side by side and adds keyword search volume and competition data, so you see demand, cost and ad pressure at a glance. Field names below are the exact names in the dataset (the results table of a run).

| Field | What it means | Group |
|---|---|---|
| 🔑 `keyword` | The keyword as measured (lower-cased, single spaces) | Core |
| 📊 `search_volume` | Average monthly Google searches | Ads metrics |
| 💲 `cpc` | Average cost per click, rounded to 2 decimals | Ads metrics |
| 🥊 `competition` / `competition_index` | Ad competition: LOW / MEDIUM / HIGH and 0-100 | Ads metrics |
| 📅 `monthly_searches` | Searches per month for the last 12 months, newest first | Monthly searches |
| 📉 `trend`, `mom_change_pct`, `qoq_change_pct`, `yoy_change_pct` | Trend direction and month, quarter and year change in % | Trend analytics |
| 🗓️ `peak_month`, `lowest_month`, `seasonality_index` | Busiest and quietest month; 0 = flat, above 0.5 = strongly seasonal | Trend analytics |
| ⚡ `spike_months`, `last_month_searches`, `typical_monthly_searches` | Unusual months, newest month, median month | Trend analytics |
| 🧲 `intent` | informational / commercial / transactional / navigational | Keyword profile |
| ❓ `is_question`, `word_count`, `length_class` | Question flag, words, head / body / long_tail | Keyword profile |
| 🔗 `cluster` | Leading keyword of the topic group | Keyword profile |
| ⭐ `opportunity_score` | 0-100 blend of demand, ease and commercial value | Keyword profile |
| 👤 `est_clicks_pos1`, `est_clicks_top3`, `est_traffic_value_pos1` | Estimated monthly organic clicks at #1 and top 3, and their value at #1 | Keyword profile |
| 📝 `spell`, `spell_corrected` | Google's spelling of the keyword, and whether Google rewrote it | Location & spelling |
| 📍 `location`, `location_name`, `location_code`, `language_name`, `language_code` | Market and language of the row | Location & spelling |
| 📈 `google_trends` | Google Trends interest now and on average, peak date, 12-month change, breakout flag | Google Trends |
| 🌱 `seed`, `idea_sources` | Ideas mode: the seed an idea came from, and where it was found | Keyword ideas |
| 🔔 `is_new`, `previous_search_volume`, `volume_change_pct` | What changed since the last run | Changes since last run |
| 🧾 `status`, `status_reason`, `data_month`, `scraped_at` | Row status, details, newest data month, collection time | Run status |

- **Keyword CPC** is shown in the currency you request (USD by default). See the [currency note in the pricing section](#how-much-does-it-cost-to-check-keyword-search-volume).
- `monthly_searches` is the keyword monthly search volume for each of the last 12 months. That makes the Actor a handy monthly keyword search volume tool, and you can follow keyword search volume over time without opening another app.
- `length_class` tells you which rows are long tail keywords (4 or more words), body keywords (2-3 words) or head keywords (1 word).
- Trend, change %, intent, cluster, opportunity score and click estimates are the Actor's own estimates, calculated from the Google keyword monthly search volume and the words of each keyword.
- `google_trends` is relative interest (0-100, scaled to each keyword's own peak), not a search count.

#### What data can't this Actor extract?

- Top-of-page bid ranges (`low_top_of_page_bid`, `high_top_of_page_bid`) and AI-assistant volume (`ai_search_volume`, `ai_monthly_searches`). These fields are in the dataset, but the Actor doesn't provide this data, so expect them to be empty (`null`).
- Search-partner volume. Rows cover Google Search only (`search_partners` is `false`).
- Keyword difficulty or search result (SERP) data.
- City or region volume. You get country-level or worldwide volume only.
- Search volume on YouTube, Amazon, Bing or other engines. YouTube, Google Shopping and Amazon are only sources of new keywords in Ideas mode.
- Country-level volume outside the supported markets (see [Location](#location-which-countries-have-country-level-volume)).

To see which ads a brand or advertiser actually runs on Google, try [Google Ads Transparency Center Scraper & API](https://apify.com/insights_data/google-ads-transparency-center-scraper-api).

***

### How to check keyword search volume in bulk

The Actor is designed for an easy start, even if you've never used a scraping tool before.

1. [Create a free Apify account](https://console.apify.com/sign-up) using your email.
2. Open [Keyword Search Volume — Bulk Google Metrics (CPC & Trend)](https://apify.com/insights_data/keyword-search-volume).
3. In **🔑 Keywords**, **replace the 4 example keywords** ("web scraping"…) with your own, one per line. Pick your countries in **🌍 Location**.
4. Click **Start**. In Metrics mode, rows show up in the **Output** tab while the run is still working.
5. Download your data in JSON, CSV, Excel, XML or HTML.

#### Defaults that can make your first run look small

- **🌍 Location** is prefilled with the United States only. Each extra country adds one set of rows.
- **💡 Max idea rows (Ideas mode)** defaults to **10 rows per country**, seeds included. Raise it (up to 1,000) to get more rows.
- On the **Apify Free plan**, a run saves at most **10 rows** in total, across all countries and statuses.
- **📈 Google Trends interest** is off by default. Switch it on if you want the `google_trends` fields.
- Countries without country-level data come back with empty volume unless you set **🚩 Locations without country data** to worldwide volume.

***

### How much does it cost to check keyword search volume?

The Actor uses **pay-per-event** pricing: you pay per saved row, plus a tiny start fee and Apify's platform usage.

| Part | Price | When you pay it |
|---|---|---|
| 💲 Results | **$6.00 per 1,000 results** ($0.006 per row) on the Free plan (lower on paid plans, see below) | For each saved row with `status` `ok` or `no_data` |
| ▶️ Actor start | **$0.00005 per run** at the default 1 GB memory | Once per run |
| ⚙️ Platform usage | Billed by Apify on top of the event prices | Depends on the work the run does |

| Apify plan | Price per keyword row | Price per 1,000 keyword rows |
|---|---|---|
| Free | $0.006 | $6.00 |
| Starter | $0.0054 | $5.40 |
| Scale | $0.0048 | $4.80 |
| Business and higher | $0.0042 | $4.20 |

Paid Apify plans get a lower price per row. The plan discount applies to that price only. The start fee is the same on every plan, and platform usage is billed at your Apify plan's own rates.

"Memory" is the size of the cloud machine the run uses; the default is 1 GB, so the start fee is $0.00005 per run.

**What is and isn't charged:**

- ✅ Charged (at your plan's row price): rows with `ok` **and** rows with `no_data`. A keyword with no search volume in that market still costs the row price, because it was measured.
- ✅ Charged the same: **Worldwide (global)** rows. Worldwide gives one row per keyword at the same price.
- ✅ Charged the same: rows reused from recent results. By default, metrics measured for the same keyword and market in the last 168 hours (7 days) are reused and cost full price. Keyword Planner data changes monthly (`data_month` shows the newest month), so a reused row is from the same kind of monthly data. To always measure fresh, set **💾 Reuse recent results (hours)** (`cacheTtlHours`) to 0, or lower it.
- ❌ Not charged: rows with `unsupported_location` or `provider_failed`. They are saved only so you can see what happened.
- 💱 **CPC currency:** CPC is converted at today's exchange rate. Use a supported 3-letter code such as `EUR` or `GBP`. If the run log warns that CPC stays in USD, treat the `cpc` values as **USD**. In that case the row's `currency` field still shows the code you requested.

**Example costs for result events (one country, at the Free plan price):**

| Keywords | Result events |
|---|---|
| 10 | $0.06 |
| 100 | $0.60 |
| 1,000 | $6.00 |
| 10,000 | $60.00 |

Several countries multiply the rows: 100 keywords in 3 countries = 300 rows = $1.80 in result events at the Free plan price. Add the start fee and platform usage to each run.

**How to measure platform usage for your list:** platform usage depends on your list, countries and settings (Ideas mode and Google Trends do more work per row), so there's no fixed figure. Measure it once:

1. Run 10 of your own keywords in one country (this fits the Free plan).
2. When the run finishes, open it in Apify Console. The run page shows its usage cost.
3. Divide that usage cost by the number of rows saved, then multiply by the rows in your full list (keywords × countries).

If the run switches to Apify Proxy because requests were blocked, platform usage goes up. That's why a test with your own keywords is the best guide.

**Control your spend:** set a **maximum charge limit** when you start a run. When the run reaches it, it stops cleanly and keeps the rows already saved. See the [pricing tab](https://apify.com/insights_data/keyword-search-volume/pricing) for the current event prices.

#### Is this keyword search volume checker free?

You can try it for free. The Apify Free plan includes **$5 of platform usage per month** ([Apify pricing](https://apify.com/pricing)), and this Actor's charges are paid from that credit. Each run on the Free plan saves **at most 10 rows** (keywords × countries, all statuses count), and there's no monthly limit on the number of runs. To save more than 10 rows in one run, you need a paid Apify plan. In Ideas mode on the Free plan, only as many countries are processed as fit into 10 rows (with the default 10 idea rows, that's one country).

***

### ⬇️ Input

Only **🔑 Keywords** is required. Everything else has a sensible default.

#### Settings most people change

| Form field | JSON name | What to set |
|---|---|---|
| 🔑 Keywords | `keywords` | Your keywords, one per line. Duplicates are removed and keywords are lower-cased. Max 80 characters and 10 words per keyword. |
| 🧭 Mode | `mode` | `metrics` (default) measures your keywords; `ideas` expands them into related keywords and measures those. |
| 🌍 Location | `locations` | Country codes such as `us` or `gb`, or `global` for worldwide. Empty = United States. |
| 🔤 Language | `language` | `auto` (default) uses the main language of each country; `all` = no language filter. |
| 💡 Max idea rows (Ideas mode) | `maxIdeas` | Rows per country in Ideas mode, seeds included. Default 10, range 1-1,000. |
| 💱 Currency | `currency` | A 3-letter code for CPC, such as `EUR`. Default `USD`. |
| 🔼 Min search volume / 💵 Min CPC | `minVolume` / `minCpc` | Drop rows below a volume or CPC. 0 = no minimum. |
| 🧲 Search intents | `intents` | Keep only certain intents, for example commercial and transactional search intent keywords. |
| 🔃 Sort rows by | `sortBy` | `search_volume`, `cpc`, `opportunity` and more. Empty = input order, rows appear live. |
| 🏁 Max results per location | `maxResults` | Cap on rows per country after filters. 0 = no cap. |

Here's the prefilled example. It measures 4 keywords in the United States:

```json
{
  "keywords": ["web scraping", "web scraping python", "best web scraping tools", "scrapy vs beautifulsoup"],
  "mode": "metrics",
  "locations": ["us"],
  "language": "auto"
}
```

An Ideas mode example that grows one seed into up to 50 rows:

```json
{
  "keywords": ["keyword research"],
  "mode": "ideas",
  "maxIdeas": 50,
  "locations": ["us"]
}
```

See the [input tab](https://apify.com/insights_data/keyword-search-volume/input-schema) for every field.

#### Location: which countries have country-level volume?

The location list has about 190 countries, but country-level volume exists only for a set of major markets. At the time of writing these are: **United States** (`us`), **United Kingdom** (`gb`), **Canada** (`ca`), **Australia** (`au`), **India** (`in`), **New Zealand** (`nz`) and **South Africa** (`za`), plus **Worldwide** (`global`). The list can change.

You can always tell from the row: a country without country-level data returns `status` `unsupported_location` with empty volume, and it isn't charged. To get numbers for such a country anyway, set **🚩 Locations without country data** (`unsupportedLocation`) to `global`. The row then uses worldwide volume, and `volume_scope` says `global`.

- ✅ Good: `["us", "gb"]`
- ❌ Bad: `["np"]` with `unsupportedLocation` = `skip` (rows come back without volume)

> ⚠️ Each extra country multiplies the rows and the cost: 100 keywords in 3 countries = up to 300 rows.

#### Mode, language and filters

- `maxIdeas` only works in Ideas mode and counts the seeds too. Values above 1,000 are treated as 1,000.
- Language changes the ideas found in Ideas mode, Google spelling and Google Trends. It does **not** change the search-volume market: picking `de` with location `us` still gives US volume.
- **📌 Keep a row for every input keyword** (`keepAllInputRows`) is on by default in Metrics mode. Rows that are not `ok` stay in the results even when a filter like `minVolume` would drop them, and kept `no_data` rows are charged. Turn it off to get only keywords that pass every filter.

#### Advanced settings

The form also has sections for keyword idea sources and depth (🌱), market and data source (📍), extra insights you can switch off (✨), more filters (🎯), output format, CSV copy, result reuse and change tracking (📦), and speed and proxy settings (⚡ 🔒). The defaults work for most runs, and the [input tab](https://apify.com/insights_data/keyword-search-volume/input-schema) describes each field. `network` and `includeAdultKeywords` are kept for compatibility and change nothing.

***

### ⬆️ Output

Rows appear in the **Output** tab, which has ready views such as Overview, Ads metrics, Monthly searches and Trend analytics. To download, open **Storage → Datasets**, pick the run's dataset and click **Export** (JSON, CSV, Excel, XML or HTML). You can choose only the fields you need.

For spreadsheet columns, set `outputFormat` to `flat`: monthly values become `m_YYYY_MM` columns. Turn on `writeCsv` to also save a `keywords.csv` file in **Storage → Key-value stores** (the run's file storage). A short run summary with saved and charged row counts and any warnings is saved there too.

#### JSON example

A real row for `web scraping python` from the prefilled example, shortened (2 of the 12 months shown, some fields left out):

```json
{
  "keyword": "web scraping python",
  "search_volume": 165000,
  "cpc": 0.98,
  "competition": "LOW",
  "competition_index": 9,
  "monthly_searches": [
    { "year": 2026, "month": 9, "monthly_searches": 2400 },
    { "year": 2026, "month": 8, "monthly_searches": 4400 }
  ],
  "status": "ok",
  "location": "US",
  "location_name": "United States",
  "currency": "USD",
  "data_source": "google_keyword_planner",
  "trend": "rising",
  "last_month_searches": 2400,
  "typical_monthly_searches": 3250,
  "mom_change_pct": -45.5,
  "qoq_change_pct": 26.0,
  "peak_month": "November",
  "seasonality_index": 0.43,
  "intent": "informational",
  "cluster": "web scraping",
  "opportunity_score": 60,
  "est_clicks_pos1": 897,
  "est_traffic_value_pos1": 879.06,
  "data_month": "2026-09",
  "volume_scope": "country"
}
```

This row has a search spike: `spike_months` is not empty (the field is left out of this shortened copy because the month itself wasn't kept). That's why `search_volume` (165,000) is far above `typical_monthly_searches` (3,250). See the next section for how to read it.

#### How trend, changes and spikes are decided

This is the one place where the trend fields are explained, so keyword trend analysis stays easy to follow.

- `typical_monthly_searches` is the median month of the last 12.
- `spike_months` lists the months, within the last 12, whose searches are more than 5 times the typical (median) month **and** at least 100 searches above it. `[]` means none were found.
- Before any change or trend is calculated, spike months are treated as a typical month, so one viral month can't flip the result.
- `mom_change_pct` compares the newest month with the month before. Here: 2,400 vs 4,400 = -45.5%.
- `qoq_change_pct` compares the average of the last 3 months with the 3 months before.
- `trend` is based on the last 3 months against the 3 months before (the same window as `qoq_change_pct`). With 15 or more months of data, it compares the last 3 months with the same 3 months a year earlier. In this row the quarter is up 26.0%, so `trend` is `rising`, even though the last single month fell.
- `yoy_change_pct` only appears when 13 or more months of data exist.
- When `spike_months` is not empty, `opportunity_score` and the click estimates use `typical_monthly_searches`, so `est_clicks_pos1` here is 897 and not a much bigger number.

**Which number should you report?** `search_volume` is the average month, the figure keyword tools usually show. When `spike_months` is not empty, `typical_monthly_searches` is a better guide to a normal month. Both are in every row.

#### Status and informational fields

| `status` | Meaning | Charged? |
|---|---|---|
| `ok` | Metrics found | Yes |
| `no_data` | Measured, but no search volume for this keyword in this market | Yes |
| `unsupported_location` | No country-level data for this market | No |
| `provider_failed` | The keyword couldn't be measured this time, for example because of a connection problem. Re-run those keywords later. | No |

- `status_reason`: what the row contains, or why a value is missing. `input_keyword`: your keyword exactly as typed.
- `data_month`: the newest month in the data. `scraped_at`: when the row was collected (UTC).
- `volume_scope`: `country` or `global`. `data_source`: `google_keyword_planner` or `keyword_planner+clickstream`.
- `location_code`: Google's location id (for example `2840` for the US). `search_partners`: always `false`.

#### When optional fields are filled

- `monthly_searches` and the trend fields: when **📅 Monthly searches** and **📉 Trend analytics** are on (default) and the keyword has data.
- `intent`, `opportunity_score`, click estimates and the other profile fields: when **🧬 Keyword profile & value** is on (default). `cluster`: when **🔗 Topic clusters** is on (default).
- `spell`: when **📝 Google spelling check** is on (default) and the check worked.
- `google_trends`: only when **📈 Google Trends interest** is on; `null` for a keyword when Google Trends gave no answer.
- `seed` and `idea_sources`: Ideas mode only. `is_new`, `previous_search_volume`, `volume_change_pct`: only with **🔔 Track changes between runs**.
- `currency`: `null` when `cpc` is `null`. Bid and AI-volume fields: not provided; expect them to be empty.

***

### Tips and advanced usage

#### How many keywords can you check in one run?

On paid plans there's no fixed cap on keywords. On the Free plan, a run saves up to 10 rows. The number of rows is keywords × countries, minus anything your filters or `maxResults` drop. Keywords longer than 80 characters or 10 words are rejected and listed in the log. Run times depend on your list and settings; rows appear live in Metrics mode, so you can watch progress in the Output tab.

#### How to get cheaper results

- **Skip keywords without volume:** set **🔼 Min search volume** to 1 and turn off **📌 Keep a row for every input keyword**. `no_data` rows are then dropped, and dropped rows are not saved or charged.
- **Cap each country** with `maxResults`, and set a **maximum charge limit** for the whole run.
- **Pick only the countries you need.** Every extra country adds a full set of rows.

#### Track keyword volume on a schedule

Turn on **🔔 Track changes between runs** (`monitorChanges`) and schedule the Actor weekly or monthly. Each run adds `is_new`, `previous_search_volume` and `volume_change_pct`, and the history stays in your own Apify account.

#### Known issues

- Bid and AI-volume fields are not provided; expect them to be empty.
- A spike month can push `search_volume` far above the typical month. See [how spikes are decided](#how-trend-changes-and-spikes-are-decided).
- Google Trends answers only a few requests per minute. If it keeps refusing, the run skips Google Trends for the remaining keywords and keeps the rows without it.
- Amazon suggestions are only used for 13 markets (US, GB, DE, FR, IT, ES, CA, JP, IN, AU, MX, BR, NL).

***

### Integrations and API

#### Can I use this Actor as a keyword search volume API?

Yes. The [Apify API](https://docs.apify.com/api/v2) lets you start runs, schedule them and fetch results, so the Actor works as a keyword volume API for your own scripts and apps. Use the `apify-client` [NPM package](https://apify.com/insights_data/keyword-search-volume/api/javascript) for Node.js or the `apify-client` [PyPI package](https://apify.com/insights_data/keyword-search-volume/api/python) for Python. The [API tab](https://apify.com/insights_data/keyword-search-volume/api) has ready-to-use code.

Teams that need a Google keyword search volume API or an SEO keyword research API can call it from any backend with the same JSON as the input example above. No Google Ads developer token is needed, which also makes it a simple Google keyword research API for prototypes.

#### How to get keyword search volume with Python

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("insights_data/keyword-search-volume").call(run_input={
    "keywords": ["web scraping", "web scraping python", "best web scraping tools", "scrapy vs beautifulsoup"],
    "mode": "metrics",
    "locations": ["us"],
    "language": "auto",
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["keyword"], item["search_volume"], item["cpc"])
```

#### Can I integrate it with other apps?

Yes. Connect the Actor with almost any cloud service through [Apify integrations](https://apify.com/integrations): **Make, Zapier, Slack, Google Sheets, Google Drive, Airbyte, GitHub, LangChain** and more. Use [webhooks](https://docs.apify.com/integrations/webhooks) to trigger actions when a run finishes.

Example workflow: schedule a weekly run with `monitorChanges` on, send the dataset to Google Sheets, and get a Slack message when the run finishes so you can review the keywords whose `volume_change_pct` moved the most.

#### Can I use it with AI agents (MCP)?

Yes. Connect the Actor to Claude and other AI assistants through the Apify MCP server. Open the [MCP tab](https://apify.com/insights_data/keyword-search-volume/api/mcp) for setup steps.

***

### Other Google scrapers from Insights Data

These Actors from the same author also work with Google data:

| | |
|---|---|
| 📢 [Google Ads Transparency Center Scraper & API](https://apify.com/insights_data/google-ads-transparency-center-scraper-api) | Extract ads across Search, YouTube, Shopping, Maps and Play by brand, domain or advertiser ID. Pairs well with CPC research. |
| 🏨 [Google Hotels Scraper](https://apify.com/insights_data/google-hotels-scraper) | Hotel prices, ratings, star class, amenities and booking links for any city or hotel. |
| ✈️ [Google Flights Prices API](https://apify.com/insights_data/google-flights-prices-api) | Live fares, schedules, stops, layovers and airlines for one-way, round-trip and multi-city routes. |

***

### ❓ FAQ

#### What is keyword search volume?

Keyword search volume is the number of times a keyword is searched in a month. This Actor reports it as `search_volume`, the average monthly Google searches for one market, plus the month-by-month numbers in `monthly_searches`.

#### How to check keyword search volume in Google?

Google's own tool is Keyword Planner, which you use inside a Google Ads account. With this Actor you paste your keywords, pick a country and click **Start**. You get Keyword Planner-based volume, CPC and competition without setting up an ads account. See [the step-by-step tutorial](#how-to-check-keyword-search-volume-in-bulk).

#### Where does the keyword research search volume come from, and is it exact?

The volume, CPC, competition and monthly numbers are Keyword Planner search volume figures taken from publicly available keyword data. You get single numbers, not ranges like "1K–10K". Volume and monthly values are passed on as received; CPC is rounded to 2 decimals and converted if you ask for another currency. They are not pulled from the official Google Ads API, and like every keyword tool's numbers they are monthly averages and estimates, not exact counts.

#### Can I find search volume of a keyword without a Google Ads account?

Yes. The input has no account, API key or cookie fields. Paste the keyword, pick a country and run it.

#### Should I use Metrics mode or Ideas mode?

| | Metrics mode | Ideas mode |
|---|---|---|
| Use it to | Check search volume of keyword lists you already have | Discover new related keywords around a few seeds |
| Rows per country | One per input keyword (after duplicates are removed) | Up to `maxIdeas` (default 10, max 1,000), seeds included |
| Row order | Input order, saved live (unless sorted) | Seeds first, then the highest-volume ideas |
| Price per saved row | $0.006 on the Free plan, down to $0.0042 on Business | $0.006 on the Free plan, down to $0.0042 on Business |

#### Is this a keyword research tool or a Google keyword search volume tool?

Both. It measures volume, CPC and competition like a Google keyword search volume tool, and Ideas mode, intent, clusters and the opportunity score cover the research side of a keyword research tool. It doesn't provide keyword difficulty or search result (SERP) data.

#### Is it legal to scrape Google keyword data?

Collecting publicly available data is generally legal. Keyword metrics are aggregate numbers and contain no personal data. You are still responsible for using the data in line with applicable laws and the terms of the services involved. This is not legal advice.

#### How does it work?

You paste keywords and pick countries. The Actor cleans the list and removes duplicates, looks up the Keyword Planner-based metrics for each keyword and market, calculates the trend analytics, intent, clusters and estimates itself, adds Google spelling and (if you want) Google Trends interest, applies your filters and saves each row. In Ideas mode it first collects related keywords from public search suggestions.

#### Why check keyword search volume?

- **SEO keyword search volume:** decide which topics deserve a page, and in which country.
- **CPC keyword research:** see what advertisers pay per click before you plan a campaign.
- **Keyword search volume analysis:** compare markets, find seasonal peaks and catch rising terms early.

#### Why am I getting fewer results than expected?

1. **Free plan:** a run saves at most 10 rows. The status message explains when rows were cut.
2. **Ideas mode:** `maxIdeas` defaults to 10 rows per country. Raise it.
3. **Filters:** check `minVolume`, `minCpc`, `intents`, `trends` and `maxResults`.
4. **Unsupported countries:** rows show `unsupported_location`. Set `unsupportedLocation` to `global` for worldwide volume.
5. **Long-tail ideas:** many have no volume (`no_data`). Ideas mode measures extra ideas to fill your `maxIdeas` with rows that have volume.
6. **Failed rows:** `provider_failed` rows weren't charged. Re-run those keywords later.
7. **Maximum charge limit:** the run stops when it's reached. Raise it to collect more.

***

### Support and feedback

Found a bug or have a feature request? Please create an issue on the [Issues tab](https://apify.com/insights_data/keyword-search-volume/issues/open). We're always working on improving the Actor.

Need a **custom solution**, a different keyword workflow or more data? Contact us at hello.insights.data@gmail.com.

Built and maintained by [Insights Data](https://apify.com/insights_data).

# Actor input Schema

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

Keywords to look up, one per line (bulk lists welcome; duplicates are removed, keywords are lower-cased like Google Keyword Planner does). In Metrics mode these are measured directly; in Ideas mode they are seeds that get expanded into related keywords. Free plan users are limited to 10 items per run; paid plans have no limit.

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

Metrics = volume, CPC and competition for exactly the keywords you provide. Ideas = expand your seeds into related keywords and return their metrics too (seeds first, then the highest-volume ideas).

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

Ideas mode only: total keyword rows returned per location, seeds included (1-1,000). If many ideas come back without search volume, more ideas are measured until this many rows carry volume or no ideas are left. Ignored in Metrics mode. Free plan users are limited to 10 items per run; paid plans have no limit.

## `locations` (type: `array`):

Countries to measure volume in. Pick several to get one set of rows per country. Worldwide (global) = volume across all countries. Empty = United States.

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

Language used for keyword ideas, spelling and Google Trends. Auto picks the main language of each country; All languages = no language filter.

## `network` (type: `string`):

Kept for compatibility with other keyword tools. Search-partner volumes are not available, so every row reports Google Search only (search_partners = false) whichever option you pick.

## `ideaSources` (type: `array`):

Where keyword ideas come from in Ideas mode. Pick one or more.

## `autocompleteDepth` (type: `string`):

Starting depth. Basic = the seed itself; Questions = also how / what / why / can … questions; Full = also modifiers (best, vs, for, near me…) and a-z letters. The search goes deeper on its own when too few ideas are found.

## `maxIdeaCandidates` (type: `integer`):

How many discovered ideas are measured before the best Max idea rows are kept (never fewer than Max idea rows). More candidates = better picks, longer run.

## `unsupportedLocation` (type: `string`):

Country-level volume is available for a set of major markets. For other countries: skip = keep the rows but leave volume empty (status unsupported_location); global = use worldwide volume instead (volume_scope = global).

## `dataSource` (type: `string`):

Google Keyword Planner only, or Keyword Planner blended with clickstream data.

## `currency` (type: `string`):

ISO-4217 code (USD, EUR, GBP, INR…). CPC and bid values are converted at today's exchange rate; unknown codes stay in USD.

## `includeMonthlySearches` (type: `boolean`):

Adds monthly_searches: one entry per month with the search volume.

## `includeTrendAnalytics` (type: `boolean`):

Adds trend (rising / stable / declining), month-over-month and quarter-over-quarter change, peak and lowest month, seasonality index and spike months.

## `includeKeywordProfile` (type: `boolean`):

Adds word count, head / body / long-tail class, question flag, search intent, opportunity score (0-100) and estimated clicks and traffic value at position 1.

## `clusterKeywords` (type: `boolean`):

Groups keywords about the same topic; cluster = the cluster's leading keyword.

## `includeSpellCheck` (type: `boolean`):

spell = Google's spelling of the keyword; spell_corrected = true when Google rewrites it.

## `includeGoogleTrends` (type: `boolean`):

Adds google_trends: latest and average interest (0-100), peak date, 12-month change and a breakout flag. Slower: Google Trends answers a few requests per minute.

## `trendsTimeframe` (type: `string`):

Period used for Google Trends interest.

## `includeTrendsSeries` (type: `boolean`):

Also adds every Google Trends data point (date + interest) inside google_trends.series.

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

Drop keywords below this monthly volume. 0 = no minimum.

## `maxVolume` (type: `integer`):

Drop keywords above this monthly volume. 0 = no maximum.

## `minCpc` (type: `number`):

Drop keywords with a lower cost per click. 0 = no minimum.

## `maxCpc` (type: `number`):

Drop keywords with a higher cost per click. 0 = no maximum.

## `competitionLevels` (type: `array`):

Keep only these ad-competition levels. Empty = all.

## `includeTerms` (type: `array`):

Keep only keywords containing at least one of these words or phrases.

## `excludeTerms` (type: `array`):

Drop keywords containing any of these words (whole-word match).

## `minWords` (type: `integer`):

Keep keywords with at least this many words. 0 = no minimum.

## `maxWords` (type: `integer`):

Keep keywords with at most this many words. 0 = no maximum.

## `onlyQuestions` (type: `boolean`):

Keep only question keywords (how, what, why, can…).

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

Kept for compatibility with other keyword tools. Results are never filtered for adult terms, so this switch changes nothing.

## `intents` (type: `array`):

Keep only these search intents. Empty = all.

## `trends` (type: `array`):

Keep only keywords whose 12-month trend is one of these. Empty = all.

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

Leave empty to keep your input order (rows then appear live while the run works). Sorting delivers each location's rows once all of its keywords are measured. Highest first, except keyword (A-Z).

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

Cap on rows per location after filters. 0 = no cap. Free plan users are limited to 10 items per run; paid plans have no limit.

## `keepAllInputRows` (type: `boolean`):

Metrics mode: keywords that could not be measured still get a row with a status explaining why, even when filters are set.

## `outputFormat` (type: `string`):

Full = nested JSON (monthly_searches as a list). Flat = one level for spreadsheets: monthly values become m_YYYY_MM columns and lists are joined with |.

## `writeCsv` (type: `boolean`):

Saves keywords.csv (flat columns) in the run's key-value store, next to the dataset.

## `cacheTtlHours` (type: `integer`):

Keyword Planner data changes monthly, so metrics measured for the same keyword and market within this many hours are reused (stored in your own Apify account). 0 = always measure fresh.

## `monitorChanges` (type: `boolean`):

Remembers each keyword's volume (in your own Apify account) and adds is_new, previous_search_volume and volume_change_pct on the next runs.

## `concurrency` (type: `integer`):

How many idea and spelling look-ups run at the same time.

## `lanesConcurrency` (type: `integer`):

Volume look-ups in flight per connection at the same time.

## `maxRetries` (type: `integer`):

Retries for a request that fails to connect or gets a server error.

## `proxySessions` (type: `integer`):

When a proxy is used, how many separate proxy IPs the work is spread over.

## `proxyConfiguration` (type: `object`):

Starts without a proxy. If requests are blocked, the run switches to a datacenter proxy, then to a residential proxy, and stays on residential for the rest of the run. Pick a proxy here to start on it directly.

## Actor input object example

```json
{
  "keywords": [
    "event organizer software",
    "eventbrite alternative",
    "sell tickets online"
  ],
  "mode": "metrics",
  "maxIdeas": 10,
  "locations": [
    "us"
  ],
  "language": "auto",
  "network": "GOOGLE_SEARCH",
  "ideaSources": [
    "google_autocomplete"
  ],
  "autocompleteDepth": "questions",
  "maxIdeaCandidates": 300,
  "unsupportedLocation": "skip",
  "dataSource": "keyword_planner",
  "currency": "USD",
  "includeMonthlySearches": true,
  "includeTrendAnalytics": true,
  "includeKeywordProfile": true,
  "clusterKeywords": true,
  "includeSpellCheck": true,
  "includeGoogleTrends": false,
  "trendsTimeframe": "today 5-y",
  "includeTrendsSeries": false,
  "minVolume": 0,
  "maxVolume": 0,
  "minCpc": 0,
  "maxCpc": 0,
  "competitionLevels": [],
  "includeTerms": [],
  "excludeTerms": [],
  "minWords": 0,
  "maxWords": 0,
  "onlyQuestions": false,
  "includeAdultKeywords": false,
  "intents": [],
  "trends": [],
  "maxResults": 0,
  "keepAllInputRows": true,
  "outputFormat": "full",
  "writeCsv": false,
  "cacheTtlHours": 168,
  "monitorChanges": false,
  "concurrency": 5,
  "lanesConcurrency": 2,
  "maxRetries": 3,
  "proxySessions": 5,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Every keyword row with all fields (overview columns).

## `overview` (type: `string`):

The headline numbers for every keyword.

## `metrics` (type: `string`):

Keyword Planner metrics: volume, CPC, competition and bid ranges.

## `monthly` (type: `string`):

One row per keyword and month (last 12 months).

## `trends` (type: `string`):

Direction, changes, seasonality and spikes from the monthly data.

## `profile` (type: `string`):

Intent, length, clusters, opportunity and click estimates.

## `ai_bids` (type: `string`):

AI-assistant volume and top-of-page bids (not available; always empty).

## `google_trends` (type: `string`):

Google Trends interest (when switched on).

## `ideas` (type: `string`):

Ideas mode: where each idea came from, with its metrics.

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

Market, language, input keyword and Google's spelling.

## `changes` (type: `string`):

Monitoring: volume compared with the previous run.

## `status` (type: `string`):

Status of every row and when it was collected.

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

Counts by status, filters applied, connection used and notes for this run.

## `csv` (type: `string`):

keywords.csv (flat columns), when 'Also save a CSV file' is on.

# 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": [
        "web scraping",
        "web scraping python",
        "best web scraping tools",
        "scrapy vs beautifulsoup"
    ],
    "locations": [
        "us"
    ],
    "language": "auto",
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("insights_data/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": [
        "web scraping",
        "web scraping python",
        "best web scraping tools",
        "scrapy vs beautifulsoup",
    ],
    "locations": ["us"],
    "language": "auto",
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("insights_data/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": [
    "web scraping",
    "web scraping python",
    "best web scraping tools",
    "scrapy vs beautifulsoup"
  ],
  "locations": [
    "us"
  ],
  "language": "auto",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call insights_data/keyword-search-volume --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,insights_data/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/UFwlxJjEhLH9hIxsM/builds/fvUI49XidCVTLrpXJ/openapi.json
