Keyword Search Volume & CPC Checker: Google Keyword Planner
Pricing
from $2.21 / 1,000 keyword rows
Keyword Search Volume & CPC Checker: Google Keyword Planner
Keyword search volume checker for a keyword list: Google search volume, CPC, competition, bids, keyword difficulty, search intent and up to 104 months of history per keyword, any country or worldwide. Keyword Planner view, keyword ideas, ranked keywords, AI and Bing search volume. Pay per keyword.
Pricing
from $2.21 / 1,000 keyword rows
Rating
0.0
(0)
Developer
Hyperbach
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
8 days ago
Last modified
Categories
Share
Google keyword search volume, CPC, competition and top-of-page bids for your keyword list — each keyword read on its own, so its figure does not change with the rest of your list, with up to 104 months of history, keyword difficulty, search intent, SERP features and backlink averages on the same row, for any country (and worldwide), 10,000 keywords a run. Every keyword you give gets a row: a figure, or a typed reason why not (no_data, invalid, unsupported_location, upstream_error), and only a row with figures is charged. Google's own Keyword Planner view on request (search partners, cities and postal codes, a date window), with a flag on every keyword whose figure Google merged with its close variants in the same batch — the quiet way other tools return 6,600 for event tickets and 720 for event ticketing in one run and 6,600 for both in another. Keyword ideas per seed, the keywords a domain ranks for, AI-assistant, Bing and clickstream volumes as add-ons, a per-account memory so the same keyword is never charged twice in the same data month, and onlyChanges for a monthly schedule. Save a run as a task and schedule it: a monthly tracker that delivers only the keywords that moved. No login, no Google Ads account, no API key, no proxy.
Why this keyword volume checker
- A figure that does not change with your list. Google's Keyword Planner answers a batch: close variants in one request take one group figure, and which figure depends on the batch (in our test
event ticketingwas 720 alone and 6,600 next toevent ticketandevent tickets; 24 of 1,000 buyer keywords took a group figure that differed from their own, by up to 83×). The default view here (labs) reads each keyword on its own, so its volume, CPC, competition, bids and history are the same whatever else you list. Close variants that Google counts as one search (plurals, word order, misspellings) share one figure on both views —yoga mat,yoga matsandmat for yogaare 110,000 each, as in 5 of 5 such sets we tried — so do not add them up: thegoogle_adsview flags every keyword whose figure is shared with other keywords of the batch (ads_variants_merged) and names them (ads_group_keywords).view=bothputs the two figures side by side. Ready-made: Keyword Planner volume next to Labs, close variants flagged. - Every keyword accounted for, every charge explained. Every keyword you give gets a row with a
status:okwith figures (charged), or freeno_data(the source holds no figure),invalid(over 80 characters or 10 words, a symbol Google Ads refuses — the row says which),unsupported_location,upstream_error(the source's own error, with the reason) ornot_read(a cap or the time limit stopped the run before it).chargedandbilling_noteare on every row; a run that delivers nothing charges nothing. - Up to 104 months of history at the base price, difficulty and intent on the same row. The Labs view carries the monthly series back to 2018 (90–103 months on 73 of 78 ordinary keywords in our test, 18 on the other 5; idea and ranked rows carry 12), the keyword difficulty (0–100), the search intent, the SERP features Google shows (
has_ai_overviewamong them), the result count and the backlink averages of the top 10, in one row. Trend columns (trend_3m_percent,trend_12m_percent,peak_month) are computed from the row's own series (the FAQ says how they differ from the source's ownsource_trend). - Any country, worldwide and per country in one run.
locationstakes country codes or names,worldwideand numeric Google Ads location codes for cities, regions and postal codes; one row per keyword per location. The Labs view serves 92 countries in their own languages; worldwide, cities and the rest are read on the Google Ads view, andsource_viewsays which one each row came from. Ready-made: search volume by country: US, UK, Canada, Australia and worldwide. - Ideas and ranked keywords, filtered before the charge.
seedsgives up to 1,000 keyword ideas per seed (topic ideas, long-tail suggestions or Google's related searches),domainsthe keywords a domain ranks for with position, URL and estimated traffic;minSearchVolumeis applied at the source so a filtered row is never charged. Ready-made: keyword ideas for a seed, 1,000+ monthly searches, the keywords a website ranks for, top 100 by traffic. - A shared cache and a memory that protects your bill. The source updates its figures once a month (
data_monthon every row); a keyword read earlier in the month can come from the Actor's shared cache with the same figures and its read time (read_fromsays which; when the cache is off the figures are read live), and a keyword you were already delivered in the same data month is not charged again.onlyChangesturns a saved task on a monthly schedule into a change feed: only the keywords whose data month or volume moved. - Plain HTTPS to a paid API, 256 MB, a few seconds per 700 keywords. No browser, no page, no proxy; 1,000 keywords are two source tasks (about 30 s with both views), 5,000 keywords took 45 s in our test, 10,000 about two minutes.
Who it's for
- SEO and content teams — a keyword list of any size with volume, difficulty, intent and up to 104 months of seasonality per keyword, in the markets they write for.
- PPC and agencies — the Keyword Planner view (competition index, bids, search partners, cities and postal codes) with the variant-merge flag that explains why two tools disagree.
- Product and market research — worldwide and per-country rows for the same keywords in one run, trends and peak months, AI-assistant and Bing volumes next to Google's.
- Developers and agents — typed rows with stable snake_case names, a status and a charged flag on every row, a run summary to check a pipeline against, and
onlyChangesfor a schedule.
Quick start
A keyword list, United States, the Labs view
{"keywords": ["event ticketing","sell tickets online"]}
Both views: the Labs figure next to Google's Keyword Planner figure, close variants flagged
{"keywords": ["event ticketing","event ticket","event tickets"],"view": "both"}
Worldwide and two countries in one run
{"keywords": ["event ticketing"],"locations": ["worldwide","US","DE"],"language": "en"}
Keyword ideas for a seed and a domain's ranked keywords, volume 100 and up
{"seeds": ["event ticketing"],"ideasPerSeed": 100,"domains": ["eventbrite.com"],"keywordsPerDomain": 100,"minSearchVolume": 100}
Output
One row per keyword and location (keyword ideas and ranked keywords are rows of their own kind):
| field | meaning |
|---|---|
row_type | keyword (your keyword in one location), keyword_idea (an idea of a seed) or ranked_keyword (a keyword a domain ranks for). |
keyword | The keyword as the source reads it: lowercase, trimmed, one space between words. Null on a domain's status row. |
keyword_inputs | Every spelling of the keyword you gave (case and spacing variants are folded into one row and charged once). Null on idea and ranked rows. |
status | ok (figures served, charged), or free: no_data (the source holds no figure for this keyword in this location), invalid (no keyword for the source: over 80 characters, over 10 words, a symbol Google Ads refuses; a blank entry of the list is skipped), unsupported_location (a location or language the source does not serve, a location code it does not know), upstream_error (the source refused or failed the task after the retries), below_min_volume (under minSearchVolume), not_read (the run stopped before it: the cap, the charge limit, the time limit). |
status_detail | Why the row has the status it has, in words: the symbol a keyword contains, the source's own refusal sentence, the floor it fell under, what stopped the run. Null on an ordinary ok row. |
charged | true when this row is charged (a row with figures that you were not already delivered this data month). Every status row and every repeat inside the data month is false. |
billing_note | Why a row with figures is not charged: delivered to you on <date> for data month <YYYY-MM>; not charged again. Null otherwise. |
task_fee_labs | On the first charged row of a live Labs or AI task: the number of labs_task fees this row carries (1, or 2 with the AI add-on's task). Null on every other row. |
task_fee_ads | On the first charged row of a live Google Ads or Bing task: the number of ads_task fees this row carries (1, or 2 with the Bing add-on's task). Null on every other row. |
scraped_at | When the figures were read from the source (UTC, ISO 8601). On a row served from the shared cache, the time of the original read. |
location | The location as you gave it (US, Germany, worldwide, 1023191). |
location_code | The Google Ads location code the row was read for (2840 = United States, 2276 = Germany, 1023191 = New York). Null for worldwide. |
location_name | The location's name from the Actor's table (United States, Germany, worldwide); location <code> for a city, region or postal code given as a numeric code. |
language_code | The Google Ads language code the row was read for (en, de, es). |
search_partners | true when the figures are for Google Search and its search partners (searchPartners, Google Ads view); false for Google Search alone. |
source_view | Which view the main figures of this row come from: labs (the keyword database: each keyword read on its own, so its figure does not change with the rest of your list; up to 104 months, difficulty, intent) or google_ads (Google's Keyword Planner figure as served, close variants merged inside the batch). Close variants that Google counts as one search (plurals, word order, misspellings) share one figure on both views. |
data_month | The source's data month, YYYY-MM: the latest month the monthly series holds (Google updates the Keyword Planner data once a month). Figures read inside one data month are the same figures. |
source_updated_at | When the source last refreshed this keyword's record (the Labs view's last_updated_time). Null on the Google Ads view. |
task_id | The source's task id of the request that served this row, for tracing a figure. Null on a status row that reached no task. |
read_from | live (read from the source in this run) or cache (served from the Actor's shared cache: the same figures of the same data month, read at scraped_at). |
search_volume | Average monthly searches for the keyword in the location and language (Google's figure). On the google_ads view a figure Google merged with close variants in the batch (ads_variants_merged). Null on a status row. |
competition | Google Ads competition level: LOW, MEDIUM or HIGH (the Labs view's 0–1 competition read on Google's thresholds). |
competition_index | Competition as an index 0–100 (the Google Ads index as served; on the Labs view its 0–1 competition × 100). |
cpc | Average cost per click in USD, as Google Ads reports it for the keyword. |
low_top_of_page_bid | The lower top-of-page bid estimate in USD (Google Ads). |
high_top_of_page_bid | The higher top-of-page bid estimate in USD (Google Ads). |
monthly_searches | The monthly series, oldest first: [{"year", "month", "search_volume"}, …]. Up to 104 months on a Labs keyword row (90–103 on 73 of 78 ordinary keywords in our test, 18 on the other 5), 12 on idea and ranked rows and on the Google Ads view (47 with a date window); trimmed to dateFrom / dateTo when given. |
months_count | How many months the series holds. |
first_month | The first month of the series, YYYY-MM. |
last_month | The last month of the series, YYYY-MM (the data month unless dateTo cut it). |
trend_3m_percent | The last month's searches against three months earlier, in percent (computed from the row's own series; null when either month is missing or zero). Not the source's source_trend.quarterly, which compares with two months earlier. |
trend_12m_percent | The last month's searches against the same month a year earlier, in percent (year over year; computed from the row's own series). |
peak_month | The month with the most searches in the series, YYYY-MM (the latest when tied). |
source_trend | The source's own trend object on the Labs view: {"monthly", "quarterly", "yearly"} percentage changes against the month before, two months before and a year before (so quarterly is not trend_3m_percent). Null on the Google Ads view. |
keyword_difficulty | Keyword difficulty 0–100 (the Labs view: the chance of ranking in the top 10, on the source's logarithmic scale). Null on the Google Ads view. |
search_intent | The main search intent: informational, navigational, commercial or transactional (Labs view). |
secondary_intents | Further intents the source sees for the keyword (Labs view), or null. |
core_keyword | The main keyword of the synonym group this keyword belongs to, by the source's clustering (Labs view). |
detected_language | The language the source detected for the keyword (Labs view). |
categories | Google product category ids the keyword falls into (Labs view), or null. |
serp_item_types | The kinds of result Google's page shows for the keyword (organic, people_also_ask, ai_overview, images, video, …; Labs view with includeSerpInfo). |
serp_results_count | The number of results Google reports for the keyword (Labs view with includeSerpInfo). |
serp_check_url | A Google search URL for the keyword in the location and language (Labs view with includeSerpInfo). |
has_ai_overview | true when Google's page for the keyword shows an AI Overview (read from serp_item_types). |
avg_backlinks | The average number of backlinks of the top-10 organic results (Labs view). |
avg_referring_domains | The average number of referring domains of the top-10 organic results (Labs view). |
avg_domain_rank | The average main-domain rank of the top-10 organic results (the source's scale; Labs view). |
spelling_suggestion | Google Ads' spelling correction of the keyword when it offers one (Google Ads view), or null. |
ads_search_volume | With view = both: Google's Keyword Planner volume for the keyword as served in this batch (close variants merged), next to the Labs figure in search_volume. Null otherwise. |
ads_competition | With view = both: the Google Ads competition level (LOW, MEDIUM, HIGH). |
ads_competition_index | With view = both: the Google Ads competition index 0–100. |
ads_cpc | With view = both: the Google Ads CPC in USD. |
ads_low_top_of_page_bid | With view = both: the Google Ads lower top-of-page bid in USD. |
ads_high_top_of_page_bid | With view = both: the Google Ads higher top-of-page bid in USD. |
ads_monthly_searches | With view = both: the Google Ads monthly series, oldest first (12 months; 47 with a date window). |
ads_variants_merged | On every row read on the Google Ads view: true when other keywords of your list in the same batch share this keyword's exact Google Ads figures (volume, competition index, CPC, bids and monthly series): Google merged the close variants into one group figure. false when the figure is this keyword's alone within the batch. With view = both, compare with the Labs figure: the same (as for most plurals and word-order variants) means Google counts these keywords as one search on both views; a different one means the batch changed this keyword's Google Ads figure. |
ads_group_keywords | The other keywords of your list that share this keyword's Google Ads figures (the merged group), or null. |
ads_task_id | With view = both: the id of the Google Ads task the ads_* figures came from (task_id is the Labs task of the main figures). |
ai_search_volume | With includeAiVolume: how often the keyword is asked of AI assistants per month (the source's AI keyword data), or null. Close variants can share one AI figure (the five event ticketing variants all 4,889 in our test; no flag is derived for it); a misspelling has its own, often 0. |
ai_monthly_searches | With includeAiVolume: the AI-assistant monthly series, oldest first (12 months). |
bing_search_volume | With includeBingVolume: Bing's average monthly searches for the keyword (US, GB, CA, AU, DE, FR). |
bing_cpc | With includeBingVolume: Bing's average cost per click in USD. |
bing_competition | With includeBingVolume: Bing's competition, 0–1. |
bing_monthly_searches | With includeBingVolume: Bing's monthly series, oldest first. |
clickstream_search_volume | With includeClickstream: the clickstream-based search volume (Labs view). |
clickstream_normalized_volume | With includeClickstream: Google's volume normalized with clickstream data (Labs view). |
clickstream_monthly_searches | With includeClickstream: the clickstream monthly series, oldest first. |
change_type | With the per-account memory (any run from your account; the Actor's own runs keep none): new (first time this keyword tuple is delivered to you), changed (its data month or volume moved since the last delivery) or unchanged. Null when the memory was not open. |
previous_volume | The volume as last delivered to you (memory), or null on a new row. |
volume_change | search_volume minus previous_volume, or null. |
volume_history_own | The Actor's own reads of this keyword tuple for your account: [{"read_at", "data_month", "search_volume"}, …], newest last, up to 24. |
seed | On a keyword_idea row: the seed keyword it came from. |
idea_source | On a keyword_idea row: ideas, suggestions or related. |
domain | On a ranked_keyword row: the domain the keyword ranks for. |
rank_absolute | On a ranked_keyword row: the domain's position on Google's page for the keyword, every result counted. |
rank_group | On a ranked_keyword row: the position among results of the same kind (organic). |
previous_rank_absolute | On a ranked_keyword row: the domain's position at the source's previous check of this keyword, or null (a new ranking). |
is_new | On a ranked_keyword row: true when the domain did not rank for this keyword at the source's previous check. |
is_up | On a ranked_keyword row: true when the position rose since the source's previous check. |
is_down | On a ranked_keyword row: true when the position fell since the source's previous check. |
ranked_url | On a ranked_keyword row: the ranking URL. |
ranked_title | On a ranked_keyword row: the ranking page's title on Google's page. |
estimated_traffic | On a ranked_keyword row: the source's estimated monthly traffic the keyword brings the URL. |
is_featured_snippet | On a ranked_keyword row: true when the ranking result is a featured snippet. |
Example record:
{"row_type": "keyword","keyword": "cat litter","keyword_inputs": ["cat litter"],"status": "ok","status_detail": null,"charged": true,"billing_note": null,"task_fee_labs": null,"task_fee_ads": null,"scraped_at": "2026-10-13T11:47:44Z","location": "US","location_code": 2840,"location_name": "United States","language_code": "en","search_partners": false,"source_view": "labs","data_month": "2026-08","source_updated_at": "2026-09-15 08:11:03 +00:00","task_id": "10131147-1380-0607-0000-96201f17749b","read_from": "live","search_volume": 90500,"competition": "HIGH","competition_index": 100,"cpc": 2.09,"low_top_of_page_bid": 0.98,"high_top_of_page_bid": 5.33,"monthly_searches": [{"year": 2025,"month": 3,"search_volume": 90500},{"year": 2025,"month": 4,"search_volume": 90500},{"year": 2025,"month": 5,"search_volume": 90500},{"year": 2025,"month": 6,"search_volume": 110000},{"year": 2025,"month": 7,"search_volume": 110000},{"year": 2025,"month": 8,"search_volume": 110000},{"year": 2025,"month": 9,"search_volume": 110000},{"year": 2025,"month": 10,"search_volume": 110000},{"year": 2025,"month": 11,"search_volume": 110000},{"year": 2025,"month": 12,"search_volume": 110000},{"year": 2026,"month": 1,"search_volume": 110000},{"year": 2026,"month": 2,"search_volume": 90500},{"year": 2026,"month": 3,"search_volume": 90500},{"year": 2026,"month": 4,"search_volume": 90500},{"year": 2026,"month": 5,"search_volume": 90500},{"year": 2026,"month": 6,"search_volume": 90500},{"year": 2026,"month": 7,"search_volume": 110000},{"year": 2026,"month": 8,"search_volume": 110000}],"months_count": 18,"first_month": "2025-03","last_month": "2026-08","trend_3m_percent": 21.5,"trend_12m_percent": 0,"peak_month": "2026-08","source_trend": {"monthly": 0,"quarterly": 22,"yearly": 0},"keyword_difficulty": 28,"search_intent": "transactional","secondary_intents": null,"core_keyword": null,"detected_language": "en","categories": [10015,10130,10683,11962],"serp_item_types": ["popular_products","people_also_ask","organic","images","product_considerations","related_searches"],"serp_results_count": 222,"serp_check_url": "https://www.google.com/search?q=cat%20litter&hl=en&gl=US&ie=UTF-8&uule=w+CAIQIFISCQs2MuSEtepUEUK33kOSuTsc","has_ai_overview": false,"avg_backlinks": 318.8,"avg_referring_domains": 54,"avg_domain_rank": 512.8,"spelling_suggestion": null,"ads_search_volume": null,"ads_competition": null,"ads_competition_index": null,"ads_cpc": null,"ads_low_top_of_page_bid": null,"ads_high_top_of_page_bid": null,"ads_monthly_searches": null,"ads_variants_merged": null,"ads_group_keywords": null,"ads_task_id": null,"ai_search_volume": 50004,"ai_monthly_searches": [{"year": 2025,"month": 10,"search_volume": 51972},{"year": 2025,"month": 11,"search_volume": 48829},{"year": 2025,"month": 12,"search_volume": 53451},{"year": 2026,"month": 1,"search_volume": 50156},{"year": 2026,"month": 2,"search_volume": 46135},{"year": 2026,"month": 3,"search_volume": 47988},{"year": 2026,"month": 4,"search_volume": 44880},{"year": 2026,"month": 5,"search_volume": 45041},{"year": 2026,"month": 6,"search_volume": 36093},{"year": 2026,"month": 7,"search_volume": 38301},{"year": 2026,"month": 8,"search_volume": 38556},{"year": 2026,"month": 9,"search_volume": 50004}],"bing_search_volume": 36520,"bing_cpc": 0.95,"bing_competition": 0.9,"bing_monthly_searches": [{"year": 2025,"month": 9,"search_volume": 39420},{"year": 2025,"month": 10,"search_volume": 30220},{"year": 2025,"month": 11,"search_volume": 41120},{"year": 2025,"month": 12,"search_volume": 42040},{"year": 2026,"month": 1,"search_volume": 44910},{"year": 2026,"month": 2,"search_volume": 38370},{"year": 2026,"month": 3,"search_volume": 38800},{"year": 2026,"month": 4,"search_volume": 37330},{"year": 2026,"month": 5,"search_volume": 36630},{"year": 2026,"month": 6,"search_volume": 28590},{"year": 2026,"month": 7,"search_volume": 30310},{"year": 2026,"month": 8,"search_volume": 35650},{"year": 2026,"month": 9,"search_volume": 31310}],"clickstream_search_volume": null,"clickstream_normalized_volume": null,"clickstream_monthly_searches": null,"change_type": null,"previous_volume": null,"volume_change": null,"volume_history_own": null,"seed": null,"idea_source": null,"domain": null,"rank_absolute": null,"rank_group": null,"previous_rank_absolute": null,"is_new": null,"is_up": null,"is_down": null,"ranked_url": null,"ranked_title": null,"estimated_traffic": null,"is_featured_snippet": null}
Pricing
Pay per row with figures, plus one fee per source task the run reads live: no start fee, no minimum, no platform usage billed to you. Prices fall with your Apify plan.
| per 1,000 | what one event is | Free | Starter | Scale | Business |
|---|---|---|---|---|---|
keyword | a keyword row with figures (status ok) | $4.4286 | $3.76431 | $3.10002 | $2.2143 |
keyword_idea | a keyword idea row of a seed | $5.075 | $4.31375 | $3.5525 | $2.5375 |
ranked_keyword | a keyword a domain ranks for | $2.50 | $2.125 | $1.75 | $1.25 |
ads_view | add-on on a keyword row: the Google Ads figures beside the Labs ones (view = both) | $0.375 | $0.375 | $0.375 | $0.375 |
ai_volume | add-on on a keyword row: AI-assistant search volume (includeAiVolume) | $5.00 | $4.25 | $3.50 | $2.50 |
bing_volume | add-on on a keyword row: Bing volume (includeBingVolume) | $1.125 | $0.95625 | $0.7875 | $0.5625 |
clickstream | add-on on a keyword row: clickstream volume (includeClickstream) | $0.57143 | $0.57143 | $0.57143 | $0.57143 |
The source charges the Actor per task (a batch of up to 700 or 1,000 keywords), so each live task carries one fee, on the first charged row it delivers (task_fee_labs, task_fee_ads say which row):
| per task | what one event is | Free | Starter | Scale | Business |
|---|---|---|---|---|---|
labs_task | once per live Labs or AI task that delivers a charged row (up to 700 keywords, a seed's ideas, a domain's ranked keywords) | $0.05 | $0.05 | $0.05 | $0.05 |
ads_task | once per live Google Ads or Bing task that delivers a charged row (up to 1,000 keywords) | $0.375 | $0.375 | $0.375 | $0.375 |
A keyword row is $0.0044286 on the Free plan ($0.0022143 on Business). On the Labs view 1 keyword costs $0.0544286, 100 keywords $0.49286 and 1,000 keywords $4.5286 (two tasks); on the Google Ads view 1,000 keywords cost $4.8036, and with view = both $5.2786. A figure from the Actor's shared cache (the same keyword read earlier in the same data month) carries no task fee, and a task none of whose rows is charged carries none either. An add-on is charged only on a row that carries its figure. Free: every status row (no_data, invalid, unsupported_location, upstream_error, below_min_volume, not_read), a keyword you were already delivered in the same data month (billing_note says when), the unchanged rows onlyChanges keeps back, and a run that failed before its first row. A run that stops early (a timeout, an abort) is charged for the rows it delivered. maxItems counts the charged rows; before the first request the log says the most the run can cost at your plan's prices. Enterprise plans have their own rates; the Actor's Pricing tab shows the price for your plan.
Usage patterns
- Your keywords — Give
keywords(a list) or paste them intokeywordsText(one per line or comma-separated); both are merged, lowercased, trimmed and deduplicated (keyword_inputskeeps every spelling you gave), and charged once. Up to 10,000 keywords a run, read in batches of 700 (Labs) or 1,000 (Google Ads).locationsandlanguageapply to every keyword: one row per keyword per location. Ready-made: search volume, CPC and difficulty for a list of 25. - Which figure:
labs,google_adsorboth—labs(the default) is a keyword database built on Google Ads data: each keyword read on its own (its figure does not depend on the rest of your list), up to 104 months, difficulty, intent, SERP features, backlink averages, 92 countries. Close variants that Google counts as one search (plurals, word order, misspellings) share one figure on both views.google_adsis Google's Keyword Planner view as Google serves it: 12 months (47 withdateFrom), search partners, worldwide, cities and postal codes, and the group figure for close variants, flagged.bothreads the two and puts the Google Ads figures in theads_*columns of the Labs row (theads_viewadd-on is charged on each row that carries them). A location or a language the Labs view lacks is read on the Google Ads view by itself;source_viewsays which view a row came from. - What a row is —
row_type=keyword: your keyword in one location, withstatusok and the figures (charged), or a free status that says why not.keyword_idea: one idea of aseed, with the Labs figures (12 months of history) andidea_source.ranked_keyword: one keyword adomainranks for, withrank_absolute,ranked_url,ranked_title,estimated_traffic, the position movement and the keyword's figures (12 months). Every row sayssource_view,data_month,source_updated_at,task_idandread_from(live or cache). - Add-ons and the window —
includeAiVolumeadds how often the keyword is asked of AI assistants (12 months),includeBingVolumeBing's volume, CPC and competition (US, GB, CA, AU, DE, FR),includeClickstreamclickstream-based and normalized volumes (Labs; doubles the source task). Each is a separate event, charged only on rows that carry a figure.dateFrom/dateTo(YYYY-MM) trim the monthly series; on the Google Ads view the source serves up to 4 years back. Ready-made: AI-assistant and Bing search volume next to Google's. - A schedule, a memory and the cap — Save a run as a task and schedule it monthly with
onlyChanges: the Actor keeps a memory per account andstateStoreName, delivers only the keywords that are new to it or whose data month or volume moved, and never charges a keyword you were already delivered in the same data month (billing_notesays when).maxItemscaps the charged rows; the rows past it get freenot_readrows that say so. The log's first line says the most the run can cost at your plan's prices. Ready-made: a monthly tracker that delivers only the keywords that moved.
Input configuration
| field | type | default | what it does |
|---|---|---|---|
keywords | array | [] | The keyword list, one keyword per entry (event ticketing). Up to 10,000 a run; the run reads them in batches of 700 (Labs view) or 1,000 (Google Ads view). Also accepted: keywordsText below, merged with this list. |
keywordsText | string | "" | Paste a whole list instead: one keyword per line, or comma-separated. Merged with keywords; duplicates are folded and charged once. |
locations | array | [] | One row per keyword per location. A country as its ISO code (US, DE, GB) or name (Germany), worldwide (Google's figure for all countries), or a numeric Google Ads location code for a city, region or postal code (1023191 = New York, 1006886 = London). Empty = United States. Up to 50 locations a run; a location the Actor does not know is a free unsupported_location row, never a silent fallback. |
language | string | "en" | A Google Ads language as its code (en, de, es, pt, ja, zh_TW or zh-TW) or name (German, Chinese (Traditional)). One language a run; the 46 Google Ads languages are accepted. The Labs view serves each country in its own languages (the United States in en and es, Germany in de): a pair the Labs view lacks is read on the Google Ads view, and the row's source_view says so. |
view | labs / google_ads / both | "labs" | labs (the default): a keyword database built on Google Ads data, where every keyword is read on its own (its figure does not depend on the rest of the list): volume, CPC, competition, bids, up to 104 months of history, keyword difficulty, intent, SERP features and backlink averages; 92 countries. google_ads: the Google Ads Keyword Planner view as Google serves it, where close variants in one batch take one group figure (ads_variants_merged says so), 12 months (47 with a date window), search partners, worldwide, cities and postal codes. both: the Labs row with the Google Ads figures in the ads_* columns; the ads_view add-on is charged on each row that carries them. Each live Labs task (up to 700 keywords) carries one labs_task fee and each Google Ads task (up to 1,000) one ads_task fee, on its first charged row. Close variants Google counts as one search (plurals, word order, misspellings) share one figure on both views. |
searchPartners | boolean | false | Google Search and its search partners together (the Keyword Planner's network setting) instead of Google Search alone. A Google Ads setting: with it the keyword rows are read on the google_ads view (event ticketing: 880 with partners, 720 without, in our test). |
dateFrom | string | "" | The first month of the monthly series, YYYY-MM (or a date). On the Google Ads view the source serves up to 4 years back (47 months); on the Labs view the series (up to 104 months) is trimmed to the window. Empty = everything the view holds. |
dateTo | string | "" | The last month of the monthly series, YYYY-MM (or a date). Empty = the source's latest month (data_month on every row). |
includeSerpInfo | boolean | true | On the Labs view: the SERP features Google shows for the keyword (serp_item_types, has_ai_overview), the result count and a check URL. Free. Off = the columns stay null. |
includeClickstream | boolean | false | Clickstream-based search volume and the clickstream-normalized volume next to Google's, from the labs keyword database (clickstream_search_volume, clickstream_normalized_volume, clickstream_monthly_searches). The clickstream add-on is charged on each keyword row that carries a figure. |
includeAiVolume | boolean | false | How often the keyword is asked of AI assistants (ChatGPT and the like), with 12 months of history (ai_search_volume, ai_monthly_searches; 92 countries). The ai_volume add-on is charged on each keyword row that carries a figure, and each AI task (up to 700 keywords) one labs_task fee. |
includeBingVolume | boolean | false | Bing's search volume, CPC, competition and 13 months next to Google's (bing_* columns); served for US, GB, CA, AU, DE and FR in English, French and German. The bing_volume add-on is charged on each keyword row that carries a figure, and each Bing task (up to 1,000 keywords) one ads_task fee. |
includeAdultKeywords | boolean | false | Ask Google Ads to return figures for adult keywords too (its default hides them). Google may still return no data for some. |
minSearchVolume | integer | 0 | Keep only keywords with at least this many monthly searches. Ideas and ranked keywords are filtered at the source before anything is charged; one of your own keywords under the floor is a free below_min_volume row without figures. 0 = no floor. |
seeds | array | [] | Seeds for keyword ideas (event ticketing): up to ideasPerSeed ideas per seed and location, each a keyword_idea row with volume, CPC, competition, difficulty, intent and the seed. Up to 100 seeds a run. |
ideasPerSeed | integer | 100 | How many ideas to read per seed and location (1 to 1,000; the source holds up to a million for a broad seed). Applies when seeds is given. |
ideasSource | ideas / suggestions / related | "ideas" | Which Labs list the ideas come from: ideas (the seed's topic, ordered by relevance), suggestions (long-tail phrases containing the seed, by volume) or related (Google's related searches, two levels deep). |
domains | array | [] | Domains whose organic ranking keywords you want (eventbrite.com, a URL is read as its domain): up to keywordsPerDomain keywords per domain and location, the highest estimated traffic first, each a ranked_keyword row with the position, the ranking URL and title, the estimated traffic and the keyword's figures. Up to 100 domains a run. |
keywordsPerDomain | integer | 100 | How many ranked keywords to read per domain and location (1 to 1,000; eventbrite.com ranks for 1.4 million). Applies when domains is given. |
onlyChanges | boolean | false | For a saved task on a schedule: deliver a keyword row only when it is new to this memory or its data month or volume moved since it was last delivered to you; the unchanged ones are counted in the status message and not delivered. The memory lives with the Actor per Apify account and stateStoreName. The source updates once a month, so a monthly schedule is the natural one. |
stateStoreName | string | "" | The name of the memory this run reads and writes (letters, digits, -, _). The same name across runs tracks the same keyword set; different tasks can keep different names. Empty = one default memory per account. The memory also makes sure a keyword you were already delivered in the same data month is not charged again (billing_note says when). |
maxItems | integer | 0 | Stop after this many charged rows (keyword rows with figures, idea rows, ranked keyword rows; the free status rows do not count). 0 = no cap. |
Errors
A run does not fail because of your input. When an input cannot be used — a date that is not a date, an id in the wrong form, two settings that contradict each other — the run ends Succeeded, charges nothing, and says what to change:
- the status message starts with
INPUT REJECTED; - the dataset holds one row,
{"error": true, "code": "…", "message": "…"}, and no results; - the key-value store record
ERRORholds the same object.
From code, check error on the first row before reading results.
A keyword the source holds no figures for is not an error: it gets one free keyword row with status no_data and the reason, and the run goes on with the others. A run that ends Failed is a fault on our side, never your input; it charges nothing, and we are alerted.
FAQ
Where do the figures come from, and are they Google's?
From two sources the Actor reads on its own account: the Google Ads Keyword Planner data (the google_ads view: the figures Google serves, including its grouping of close variants) and a keyword database built on it (the labs view: each keyword read on its own, up to 104 months, difficulty, intent). In our tests the two views agreed on 916 of 1,000 keywords; the 24 that differed were keywords whose Google Ads figure was a group's (108 more shared a group figure that Labs holds too), and the rest had no figure on one side. source_view, data_month, source_updated_at and task_id are on every row, so a figure can be traced.
Why does event ticketing show 720 in one tool and 6,600 in another?
Because Google's Keyword Planner answers a batch, not a keyword: close variants in the same request take one group figure (event ticketing, event ticket, event tickets and tickets for events all became 720 in one of our batches, while each is 6,600 or 720 on its own). The labs view reads each keyword on its own, so its figure does not move with the batch (event tickets 6,600, event ticketing 720); close variants that Google counts as one search keep one shared figure there too (yoga mat and yoga mats, 110,000 each). On the google_ads view ads_variants_merged and ads_group_keywords tell you when and with what a figure was shared.
Why does a misspelt keyword show the figure of the right spelling?
Because Google counts a misspelling with its right spelling. On the labs view a misspelling the database holds carries the right spelling's figure (expresso machine 368,000 like espresso machine; mortgage calculater like mortgage calculator, which core_keyword names); one it does not hold is a free no_data row. With view = both or google_ads that one is read on the Google Ads view and shows Google's figure, the right spelling's (projet management software 165,000 like project management software): charged, with source_view google_ads and a status_detail that says the Labs database has no record. spelling_suggestion stays null when the source gives no correction (on every misspelling in our tests).
What do the trend columns compare?
trend_3m_percent compares the last month with the month three months before it, trend_12m_percent with the same month a year before; both are computed from the row's own series. The source's own source_trend (Labs view) is not the same: its monthly compares with the month before, its quarterly with two months before (on 78 of 78 rows in our test) and its yearly with a year before. So trend_3m_percent and source_trend.quarterly differ on most rows (47 of 78; coffee grinder: 0 % against 22 %).
Why is there a fee per source task?
The source charges the Actor per task, whatever its size (a Labs task of up to 700 keywords, a Google Ads or Bing task of up to 1,000). A run of one keyword would cost the Actor more than its row price, so each live task carries one fee (labs_task, ads_task) on the first charged row it delivers, and no run is sold below its cost. There is no start fee and no minimum: a keyword served from the shared cache carries no task fee, and a task that delivers no charged row (every keyword no_data, say) carries none. The log's first line says the most a run can cost, task fees included; a list whose first row and task fee your maximum charge cannot pay is not read (its free not_read rows say what it needs), so no fee is spent on rows you would not receive.
What is free?
Every row without figures: no_data (the source holds nothing for the keyword in that location), invalid (over 80 characters or 10 words, or a symbol Google Ads refuses: ! @ % ^ ( ) = { } ; ~ < > ? \ | *),unsupported_location, upstream_error, below_min_volume, not_read; a keyword you were already delivered in the same data month; the unchanged rows onlyChanges` keeps back; and a run that failed before its first row.
How current are the figures, and how often should I re-run?
Google updates the Keyword Planner data once a month (the latest month is data_month on every row; in our tests the figures held exactly across 26 reads within a month). A monthly schedule with onlyChanges is the natural one: a re-run inside the same data month returns the same figures, from the cache, and does not charge you again for them.
Which countries and languages?
The labs view serves 92 countries in their own languages (the United States in English and Spanish, Germany in German, and so on); the google_ads view serves every Google Ads location (217 countries, cities, regions, postal codes, and worldwide) in 46 languages. Give a country as its ISO code or name, a city as its numeric Google Ads location code (1023191 New York, 1006886 London, 1003854 Berlin, 9040871 Paris). A location the Actor does not know is a free unsupported_location row, never a silent fallback to the United States.
What are the limits?
10,000 keywords, 50 locations, 100 seeds and 100 domains a run; up to 1,000 ideas per seed and 1,000 ranked keywords per domain. The source allows 12 Google Ads tasks a minute on the account: the Actor paces them and waits out a limit answer at the next minute, so a large list on the google_ads view takes about a minute per 12,000 keywords. The labs view reads 700 keywords a task, four tasks at a time.
Can I bring my own API key or Google Ads account?
No. The Actor runs on its own account and charges per row with figures and per live source task; there is nothing to configure.
What does a FAILED run mean?
The source did not serve a single keyword (an outage or a refused credential): every keyword got a free upstream_error row with the reason, nothing was charged, and we are alerted. A keyword with no data, a bad keyword or an unknown location never fails a run.
Integration
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_TOKEN' });const run = await client.actor('hyperbach/keyword-search-volume').call({"keywords": ["event ticketing", "sell tickets online"]});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Python
from apify_client import ApifyClientclient = ApifyClient('YOUR_TOKEN')run = client.actor('hyperbach/keyword-search-volume').call(run_input={'keywords': ['event ticketing', 'sell tickets online']})items = client.dataset(run['defaultDatasetId']).list_items().items
CLI
$apify call hyperbach/keyword-search-volume --input '{"keywords": ["event ticketing", "sell tickets online"]}'
REST
curl -X POST "https://api.apify.com/v2/acts/hyperbach~keyword-search-volume/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H 'Content-Type: application/json' -d '{"keywords": ["event ticketing", "sell tickets online"]}'
Support
This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.