Keyword Search Volume, CPC & Difficulty Checker
Pricing
from $1.76 / 1,000 keywords
Keyword Search Volume, CPC & Difficulty Checker
Google search volume, CPC, competition, keyword difficulty, search intent and monthly trend for up to 10,000 keywords per run, by country or city, plus keyword ideas from a seed. No account or API key. Export to JSON, CSV or Excel.
Pricing
from $1.76 / 1,000 keywords
Rating
0.0
(0)
Developer
Nice Dev
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
🔎 What is Keyword Search Volume, CPC & Difficulty Checker?
Keyword Search Volume, CPC & Difficulty Checker gives you Google search volume data for your keywords: monthly searches, cost per click (CPC), ad competition, keyword difficulty, search intent, device share, click rate, searcher age and gender, and the volume in every other country. It works by country, by city or worldwide, in any language, for up to 10,000 keywords per run (raise Max keywords, 1,000 by default). It is a Google Keyword Planner API alternative: no Google Ads account, no API key, no quota to request. Run it on a schedule, call it from your code, or plug it into Make, Zapier or n8n.
Paste your keywords (running shoes, chaussures de running), pick a location (United States, France, Paris, France), click Start, and download the results in JSON, CSV or Excel. Or switch to Keyword ideas mode: give a few seed keywords and get a few hundred keyword ideas from real searches around each seed, every idea with the same metrics.
It saves about 200 keywords in 30 seconds (500 keyword ideas in about a minute), for $1.79 per 1,000 keywords (Free plan, less on paid plans).
📋 What data can you extract?
One row per keyword × location × language, 33 fields:
| Category | What you get |
|---|---|
| 🔑 Keyword | the keyword, the keyword as you typed it, its Google results link; in Ideas mode the seed it came from and the kind of idea — laptop stand |
| 📈 Search volume | average monthly searches — 301,000; with Full keyword data: searches of the last months (usually 4), worldwide volume and the volume in each other country |
| 💵 Advertising | cost per click in the local currency and in US dollars, ad competition (0-1, index 0-100, LOW / MEDIUM / HIGH) — $0.26, HIGH |
| 🎯 Keyword difficulty (add-on) | SEO difficulty (how hard to reach the top 10) and paid difficulty (how crowded the ads are), 0-100 |
| 🧭 Search intent | informational, navigational, commercial and / or transactional |
| 📱 Devices and clicks | share of searches on mobile and on desktop, click rate, share of organic and of paid clicks — 68% desktop |
| 👥 Who searches | share of each age group and of each gender — 62% male |
| 🌍 Place and language | country or city, Google Ads location id, country code, language, date the figures were last updated |
| ✅ Found or not | a keyword the source returns no data for (found: false) is kept as a free row, so you see every keyword you sent; a keyword nobody searches (a made-up word, a typo) usually comes back with 0 searches, a real measure, and is a normal row |
Every field, with an example, is listed in the Output section below.
Volume, CPC and competition are always there for a keyword that has data. Intent, months, devices, clicks, age, gender and the other countries are filled when Full keyword data (extractDetails) is on; the two difficulty scores when Keyword difficulty (includeDifficulty) is on. Both are paid options, off by default.
✅ Why use Keyword Search Volume, CPC & Difficulty Checker?
- 🔓 No account, no API key: no Google Ads account with spend, nothing to set up.
- 📊 More columns than a plain volume check: difficulty, search intent, devices, click rate, age and gender, and the volume in every other country.
- 🏙️ Countries, cities or worldwide:
Paris, FranceorSpringfield, Illinois, United States, and the log tells which place was used. - 💡 Keyword ideas mode: a few hundred ideas from real searches per seed, with question and comparison ideas (
how,best,vs…) in English, French, German, Spanish, Italian, Portuguese and Dutch. - 🧩 Nothing missed, nothing twice: one row per keyword you send (even without data), up to Max keywords (1,000 by default,
0= no limit), duplicates looked up once. - 🔔 Monitoring built in: tick Only new keywords, schedule the Actor, and each run returns (and charges) only the keywords it has never delivered before.
- 🔌 API, scheduling, monitoring, integrations (Make, Zapier, n8n, Google Sheets…) and JSON/CSV/Excel export via the Apify platform.
🚀 How to check keyword search volume
- Create a free Apify account.
- Open Keyword Search Volume, CPC & Difficulty Checker and paste your keywords into Keywords, one per line (e.g.
running shoes,standing desk). - Pick a Location: a country (
France),worldwide, or a city with its country (Lyon, France). Leave Language empty to use the main language of the place. - Choose the Mode: Keyword metrics (exactly your keywords) or Keyword ideas (expand each keyword into ideas). Set Max keywords (1000 by default, 0 = no limit), then click Start.
- Download the dataset in JSON, CSV, Excel or via API.
💰 How much does it cost to check keyword volume?
This Actor uses pay per event pricing (the same amounts are in the Pricing tab): a price per keyword row, and a price per option you tick. Platform usage (compute, proxy) is included in the price.
Prices are per 1,000 events, by Apify plan (a higher plan pays less).
| What you pay for | Event | Free | Bronze | Silver | Gold |
|---|---|---|---|---|---|
| Keyword row: volume, CPC, competition | result | $1.79 | $1.78 | $1.77 | $1.76 |
| Keyword row with Full keyword data: months, intent, devices, clicks, age, gender, other countries. Paid option, off by default; replaces the plain row | result-with-details | $2.69 | $2.68 | $2.67 | $2.66 |
| Keyword difficulty add-on, on top of the row. Paid option, off by default | keyword-difficulty | $0.92 | $0.91 | $0.90 | $0.89 |
| Keyword dropped by a filter of this Actor (a keyword you keep pays its normal price instead) | filter-check | $0.12 | $0.11 | $0.10 | $0.09 |
Same, when the keyword had to be looked up on its own first (Full keyword data, or worldwide) | detail-filter-check | $0.12 | $0.11 | $0.10 | $0.09 |
| Run start | apify-actor-start | $0.01 per run | $0.01 per run | $0.01 per run | $0.01 per run |
Keyword the source returns no data for (found: false) | — | free | free | free | free |
A keyword nobody searches comes back as 0 searches and is a normal row. With minVolume or minCpc, a keyword without data has no figure to reach the minimum: it is dropped and costs the filter fee.
Examples (Free plan): 10,000 keywords with volume, CPC and competition ≈ $17.91 ($17.90 + $0.01 run start); 1,000 keywords with full data and difficulty ≈ $3.62 ($2.69 + $0.92 + $0.01). A keyword a filter drops costs only the filter fee, lower than a row: filtering never costs more than taking everything.
⚙️ Input
{"query": "running shoes","location": "United States","maxItems": 100}
French keywords in France and in one city, with full data and difficulty:
{"searchQueries": ["chaussures de running", "tapis de yoga"],"locations": ["France", "Lyon, France"],"language": "fr","extractDetails": true,"includeDifficulty": true}
Keyword ideas around a seed, at most 200 per seed, only ideas with 100 searches a month or more, only the ones not delivered before:
{"mode": "ideas","searchQueries": ["standing desk"],"location": "United Kingdom","maxItemsPerQuery": 200,"minVolume": 100,"onlyNew": true,"stateKey": "desk-ideas-uk"}
| Field | Notes |
|---|---|
mode | metrics (default): data for exactly the keywords you give. ideas: each keyword is a seed, and the Actor returns the related searches people type, the seed included. |
query, searchQueries | Your keywords, one per line (running shoes, chaussures de running), up to 10,000 per run (the rows saved stop at maxItems, 1,000 by default). Duplicates (case ignored) are looked up once. In Ideas mode each one is a seed. |
location, locations | A country (France, or its code fr), worldwide, a city with its country (Paris, France, Springfield, Illinois, United States) or a Google Ads location id (1023191). Empty = United States. Every keyword is looked up in every location; in Ideas mode each seed × location is one search (max 500 searches per run). |
language | 2-letter code of the searches (en, fr, de, ja). Empty = the main language of each location. |
maxItems | Rows to save for the whole run, after filters (0 = no limit). |
maxItemsPerQuery | Ideas mode: cap for EACH seed × location, its own row included. Metrics mode: cap for each location. 0 = no cap. |
extractDetails | Full keyword data (paid option, off by default): months, intent, devices, clicks, age, gender, other countries. |
includeDifficulty | Keyword difficulty add-on (paid option, off by default): SEO and paid difficulty, 0-100. |
includeQuestionIdeas | Ideas mode: also expand each seed with question and comparison words (how, what, why, best, vs, for…), in the language of the search (English, French, German, Spanish, Italian, Portuguese, Dutch; other languages get the English words) (on by default). |
includeNotFound | Keep a free row with found: false for each keyword the source returns no data for (on by default; a keyword with 0 searches is not one of them). Off: such keywords are counted as failed in the log. |
minVolume, maxVolume, minCpc, maxDifficulty | Filters: monthly searches between two bounds, minimum CPC in US dollars, maximum SEO difficulty (works without the difficulty add-on). 0 = no bound. |
excludeKeywords | Drop the keywords that contain one of these words (free, amazon), case and accents ignored. |
stateKey, onlyNew, resetState | Monitoring: onlyNew returns only the keywords never delivered under this memory key (shoes-ideas); resetState forgets the memory. |
| Advanced | proxyConfiguration (Apify proxy by default, included in the price; the residential proxy is not available), maxConcurrency, maxRequestsPerMinute, minRequestIntervalMs, maxRequestRetries, debugLog. |
📦 Output
A real row (keyword laptop stand, worldwide, with full data and difficulty), with shortened decimals and volumeByCountry cut to 3 countries:
{"id": "laptop stand|worldwide|en","url": "https://www.google.com/search?q=laptop+stand&hl=en","keyword": "laptop stand","inputKeyword": "laptop stand","seedKeyword": null,"ideaType": null,"found": true,"searchVolume": 301000,"cpc": 0.26,"cpcCurrency": "USD","cpcUsd": 0.26,"competition": 1,"competitionIndex": 100,"competitionLevel": "HIGH","seoDifficulty": null,"paidDifficulty": 100,"searchIntent": [],"monthlySearches": [{ "year": 2026, "month": 6, "searchVolume": 368000 },{ "year": 2026, "month": 7, "searchVolume": 368000 },{ "year": 2026, "month": 8, "searchVolume": 450000 },{ "year": 2026, "month": 9, "searchVolume": 301000 }],"mobileShare": 0.3183,"desktopShare": 0.6817,"clickRate": 0.587,"organicClickShare": 0.3795,"paidClickShare": 0.2075,"searcherAge": { "under18": 0, "18to24": 0.1305, "25to34": 0.1329, "35to44": 0.2309, "45to54": 0.075, "55to64": 0.022, "over65": 0, "unknown": 0.4087 },"searcherGender": { "male": 0.6243, "female": 0.1783, "unknown": 0.1974 },"globalSearchVolume": 301000,"volumeByCountry": [{ "countryCode": "IN", "locationId": 2356, "language": "hi", "searchVolume": 165000 },{ "countryCode": "US", "locationId": 2840, "language": "es", "searchVolume": 40500 },{ "countryCode": "GB", "locationId": 2826, "language": "en", "searchVolume": 18100 }],"location": "Worldwide","locationId": null,"countryCode": null,"language": "en","dataUpdatedAt": "2026-04-12T07:31:27.000Z","scrapedAt": "2026-10-15T09:00:00.000Z"}
You can download the dataset in various formats such as JSON, HTML, CSV or Excel.
All 33 fields
| Fields | What you get |
|---|---|
id, url | a stable key (keyword, location id or worldwide, language, joined by a vertical bar), the Google results page of the keyword |
keyword, inputKeyword | the keyword as Google counts it (lower case), the keyword as you typed it |
seedKeyword, ideaType | Ideas mode: the seed, and seed, suggestion or question; null in Metrics mode |
found | false = no data for this keyword: every metric is null and the row is free |
searchVolume | average monthly searches, 301000 |
cpc, cpcCurrency, cpcUsd | cost per click in the local currency, that currency, and in US dollars |
competition, competitionIndex, competitionLevel | 1, 100, HIGH (LOW < 34 ≤ MEDIUM < 67 ≤ HIGH) |
seoDifficulty, paidDifficulty | add-on, 0-100 |
searchIntent | full data: informational, navigational, commercial, transactional |
monthlySearches | full data: year, month and searches of each recent month, oldest first |
mobileShare, desktopShare | full data: share of searches on a phone / a computer, 0-1 |
clickRate, organicClickShare, paidClickShare | full data: share of searches with a click, on an organic result, on an ad, 0-1 |
searcherAge, searcherGender | full data: shares by age group and by gender, 0-1 |
globalSearchVolume, volumeByCountry | full data: searches in all countries together, and in each country (largest first) |
location, locationId, countryCode, language | United States, 2840, US, en |
dataUpdatedAt, scrapedAt | when the figures were last refreshed, when the row was saved (ISO 8601) |
💡 Tips
How to get more keywords
Use Keyword ideas mode: each seed gives a few hundred ideas from real searches (more with Question ideas on). Set maxItems to 0 and use short, broad seeds (yoga mat rather than best non slip yoga mat for hot yoga).
How to reduce costs
The price is per keyword row, so the levers are maxItems, maxItemsPerQuery, the filters (a keyword a filter drops costs only the filter fee, lower than a row) and onlyNew for recurring runs (you never pay twice for the same keyword). Keep Full keyword data and Keyword difficulty off when volume, CPC and competition are enough. Only the keywords the source returns no data for (found: false) are free: a misspelled or made-up word can come back with 0 searches and counts as a row.
Several keywords and locations in one run
Paste up to 10,000 keywords into Keywords and add places in More locations: every keyword is looked up in every location (3 keywords × 4 locations = 12 rows). The single query and location fields still work and are added to the lists. A keyword sent twice (case ignored) is looked up, saved and charged once. In Ideas mode, set maxItemsPerQuery to give every seed × location its own cap: without it the first seeds can use up the whole maxItems budget.
Cities: always add the country
Write a city as City, Country (Lyon, France) or City, Region, Country (Springfield, Illinois, United States). Many towns share a name, and Paris alone may give a town in the United States. The log always tells which place was used, for example Location "Paris, France" → Paris, Ile-de-France, France (location id 1006094), and warns when several places share the name. Write the city's English name (Vienna, Austria, not Wien). When no place carries the name exactly, a place whose name begins with it as a whole word is used and the log says so (Freiburg, Germany → Freiburg im Breisgau); a name that no place carries or begins with stops the run before anything is charged, never a town whose name only starts with the same letters. States and regions alone are not available: California gives a city of that name, not the state. City rows carry volume, CPC and competition; the full data is often empty for a city.
Monitoring: only the new keywords
Tick Only new keywords (onlyNew) and schedule the Actor, best in Ideas mode to catch the new searches that appear around your seeds. The first run returns everything; each later run skips the keywords (same keyword, location and language) already delivered: they are not saved and not charged. The memory lives in a named key-value store of your account (keyword-volume-scraper-seen, up to 150,000 keywords per key) and is only updated with keywords that really reached the dataset, so a failed run never hides anything. Give each schedule its own stateKey (two schedules sharing a key would hide each other's keywords), and tick resetState once to start over. Your keyword list is always read to its end: new keywords you add to it are found wherever they are.
🔌 Integrations and API
Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.
🤖 Use with AI agents (MCP)
AI agents (Claude, ChatGPT, Cursor…) can find and run this Actor through the Apify MCP server, billed to their Apify account like any run. It returns one row per keyword × location with its Google search volume, CPC and competition. Actor id: nice_dev/keyword-volume-scraper; MCP server with this Actor only: https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/keyword-volume-scraper.
Smallest input, for a cheap first call:
{"query": "running shoes","location": "United States","maxItems": 10}
Key output fields: keyword, searchVolume, cpcUsd, competitionLevel, location, found, searchIntent (with extractDetails) and seoDifficulty (with includeDifficulty).
Cost: $1.79 per 1,000 keywords on the Free plan ($1.76 on Gold) plus $0.01 per run start, see the pricing section above. Cap each call with maxItems and, through the API, with the run option maxTotalChargeUsd.
❓ FAQ
Is it legal to scrape keyword search volume?
The Actor only reads keyword statistics that are shown publicly to any anonymous visitor. It logs in to nothing and solves no captcha. The data is made of counts and shares about searches, never about a person: it holds no personal data. You are responsible for using the data in compliance with the Terms of Use of the services involved and applicable law. This Actor is not affiliated with Google.
Do I need a Google Ads account or an API key?
No. You need nothing but your Apify account: no Google Ads account, no ad spend, no API key.
How exact are the volumes?
They are Google's own search volume figures, rounded the way Google Ads rounds them (… 33,100, 40,500, 49,500, 60,500, 74,000, 90,500, 110,000 …): two keywords in the same bracket show the same number. The CPC is the average cost of a click on a Google ad for the keyword. dataUpdatedAt tells when the figures of each keyword were last refreshed.
Does it need a login or a proxy?
No login. The proxy is included in the price: leave the default setting (the residential proxy is not available). A request that is turned away is retried at once on a new proxy session, up to 10 times on top of the retries (without a proxy, after a pause of 5 seconds, doubled at each retry up to 150 seconds). Behind a proxy, when the source keeps answering "too many requests" (HTTP 429), the retries that count wait the same way.
Is the data safe to open in Excel or to show on a web page?
Keywords are what people type: a keyword can begin with -, +, = or @, and Excel or Google Sheets may read such a cell of a CSV file as a formula or as a number. The Actor leaves the text as it is, so that the JSON and the API give the real value: when you open a CSV, import the keyword columns as text. On a web page, escape every field like any text written by a stranger. url is always a Google search link.
Known limitations
monthlySearchescovers the last months only (usually 4), not 12 months.- Volumes are rounded to Google Ads brackets (see above), and keywords of categories Google Ads restricts (such as
vpn) show a volume of 0. - States and regions alone are not available, only countries, cities and
worldwide. For a city that shares its name with others, check the place written in the log. worldwidereads each keyword on its own, one request per keyword instead of one per 10: the figures of the whole world are only given keyword by keyword, so such a run takes longer, and a keyword a filter drops there costs thedetail-filter-check.- A Google Ads location id that is not a country (a region, a city) is used as given: its rows have
cpcUsdbut nocpcin a local currency. - The full data (intent, months, devices, clicks, age, gender, other countries) is often empty for a city, and the volume in other countries is given for country searches.
- Top-of-page bid ranges are not available.
onlyNewremembers keywords, not their figures: a keyword whose volume changed is not returned again.- Two runs sharing the same
stateKeyat the same time may both return the same new keyword.
A run that reaches its timeout stops itself about 45 seconds before it: no new request is sent, what it read is saved and, with onlyNew, remembered, and the run ends Succeeded with "Stopped before the run's timeout". Resurrect it to go on from there, or give the next run a longer timeout (Run options).
A run the platform stops without warning (out of memory)
- Resurrect it: it goes on from where it stood at most a minute before the stop. What it had read since is read again, and the keywords already saved are skipped: none is delivered or charged twice, and
maxItemsstill counts them. - With
onlyNew, the memory is saved after each write (at most once every 2 seconds): resurrect the stopped run and the keywords it had saved meanwhile join the memory; leave it stopped for good, and the next run may return the keywords of its last 2 seconds once more.
Something doesn't work?
The last line of the log counts the keywords saved and filtered out, and the requests that failed after every retry. Those requests are listed, with the reason, in the FAILED_REQUESTS record of the run's key-value store. A run that saved nothing and had failed requests fails, and its last message gives the cause (a place that cannot be found says so before anything is charged, and suggests writing it as City, Country).
If the data source changes, you are told instead of paying for blank rows. If the first 20 keywords read all lack their search volume, CPC, competition or update date, the run saves nothing more, stops and fails, and its last message names the missing field: at most those first keywords are charged. Keywords without any data (found: false) are not counted in that check. A run of fewer keywords (a scheduled onlyNew run that finds a few new ones, a small Max keywords) is checked at its end, from 5 keywords: its keywords are already saved, and the run fails with the missing field instead of ending green.
🛟 Support
Open an issue in the Issues tab with a link to your run: the run log and the FAILED_REQUESTS record of the key-value store show exactly which requests failed and why.