Keyword Suggestions API — Google, Bing & Amazon avatar

Keyword Suggestions API — Google, Bing & Amazon

Pricing

from $0.12 / 1,000 keyword returneds

Go to Apify Store
Keyword Suggestions API — Google, Bing & Amazon

Keyword Suggestions API — Google, Bing & Amazon

Keyword research as data. Every autocomplete suggestion for your seed keywords from Google, YouTube, Bing, Amazon, eBay and DuckDuckGo, expanded alphabet-soup style with question, preposition and comparison modifiers. One row per keyword, with relevance and repeat counts. No API key, no login.

Pricing

from $0.12 / 1,000 keyword returneds

Rating

0.0

(0)

Developer

Insight Solutions

Insight Solutions

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

9 days ago

Last modified

Share

Real keyword research, from the search boxes themselves. Give this Actor a list of seed keywords and it asks the public autocomplete endpoints of Google, YouTube, Bing, Amazon, eBay and DuckDuckGo what they would suggest — then expands each seed alphabet-soup style (best crm a … best crm z), with question, preposition and comparison modifiers (how best crm,

best crm without
, best crm vs), and returns every suggestion as a row.

These are the phrases real people are typing right now, ranked by the engines themselves. No API key. No login. No Search Console, no Keyword Planner account. $0.20 per 1,000 keywords, proxy included, queries that return nothing are free, and a run that returns nothing costs nothing at all.

Try it in 30 seconds

{
"keywords": ["best crm", "yoga mat"],
"sources": ["google", "youtube", "bing"],
"expansions": [],
"country": "us",
"language": "en"
}

Two seeds, three engines, six requests, about ninety keywords. Then turn the expansions on and watch it become a research project:

{
"keywords": ["best crm"],
"sources": ["google", "bing", "amazon"],
"expansions": ["alphabet", "questions", "comparisons"]
}

That is 64 queries per engine — the seed, best crm a through best crm z, best crm how and how best crm for thirteen question words, and eleven comparison forms — and typically several hundred unique keywords.

Price — $0.20 per 1,000 keywords on the FREE tier (+ $0.001 per run); proxy is included, and queries that return nothing, keywords no engine suggests for, and requests an endpoint blocked are all free diagnostic rows. Pay-per-event, no API key, no browser, limited permissions — works over the Apify MCP server (mcp.apify.com) and with agentic (x402) payments.

From code — client.actor("insight.solutions/keyword-suggestions-api").call(run_input={…}) with apify-client, or POST https://api.apify.com/v2/acts/insight.solutions~keyword-suggestions-api/run-sync-get-dataset-items.

What comes back

One keyword row per suggestion:

{
"ok": true,
"rowType": "keyword", // "keyword" | "diagnostic"
"input": "Best CRM", // exactly what you typed
"seed": "best crm", // normalised: trimmed, lower-cased
"source": "google", // google | youtube | bing | amazon | ebay | duckduckgo
"suggestion": "best crm app for small business", // the keyword itself
"position": 1, // 1-based rank within its query
"relevance": 1251, // Google's and Bing's own score; null elsewhere
"suggestType": "QUERY", // Google says QUERY, Amazon says KEYWORD
"query": "best crm a", // the exact prefix that produced it
"expansion": "alphabet", // seed | alphabet | numbers | questions | prepositions | comparisons
"modifier": "a",
"modifierPosition": "suffix", // "prefix" for "how best crm"
"alsoFrom": 7, // 7 other queries returned this too — a strength signal
"wordCount": 6, // 3+ words is the long tail
"containsSeed": true,
"language": "en",
"country": "us",
"marketplace": null, // "amazon.com", "ebay.co.uk" … on marketplace rows
"ebayCategories": null, // eBay only: the departments it maps the query to
"error": null,
"errorType": null,
"scrapedAt": "2026-09-11T15:04:05.487Z",
"sourceUrl": "https://suggestqueries.google.com/complete/search?client=chrome&q=best%20crm%20a&hl=en&gl=us"
}

A marketplace row carries the two extra columns:

{
"source": "ebay",
"seed": "yoga mat",
"suggestion": "yoga mat non slip",
"position": 2,
"marketplace": "ebay.co.uk",
"ebayCategories": ["Fitness, Running & Yoga Equipment"],
"relevance": null,
"sourceUrl": "https://autosug.ebay.com/autosug?kwd=yoga%20mat&sId=3&_jgr=1&_ch=0&_callback=0"
}

Every row carries the same columns, so six engines, five expansions and the diagnostics export as one rectangular table.

Use cases

  • Long-tail keyword discovery. One seed plus alphabet and questions is the AnswerThePublic pattern, as a dataset rather than a picture. Filter wordCount >= 4 and you have the phrases with intent behind them.
  • Content briefs from real questions. expansions: ["questions"] returns what people actually ask about a topic — appended and prepended, because crm how and how crm are different questions. That is your H2 list.
  • Product and listing research. Amazon and eBay autocomplete is buying intent, not browsing intent. ebayCategories also tells you which department eBay thinks the query belongs to, which is where your listing should sit.
  • PPC negative-keyword mining. Filter containsSeed: false and you get the places the engine took the query that you did not mean — the fastest source of negatives there is.
  • Tracking what the engines suggest over time. scrapedAt plus a weekly schedule is a time series of suggestion lists. Autocomplete moves; a keyword entering or leaving the list is a signal.
  • Multi-engine comparison. Google, Bing and YouTube disagree about the same seed more than you would expect, and the disagreement is the interesting part. source is on every row, so it is a pivot rather than a join.
  • Seeding an LLM pipeline. A few hundred real phrases, ranked, with their source and their repeat counts, is a far better prompt input than a model's own guess at what people search for.

How it works, and why it keeps working

Every search box on the web is backed by a small public endpoint that answers a prefix with a list of completions. They are fast, they are tiny, and they are public — a browser calls them on every keystroke. This Actor calls six of them.

SourceEndpointShape
Googlesuggestqueries.google.com/complete/search?client=chromeJSON array. 15 suggestions with a relevance score and a type each
YouTubethe same host with ds=ytJSON array. 10 video-search suggestions
Bingapi.bing.com/osjson.aspxJSON array. Up to ~25 — the longest lists here — with relevance scores
Amazoncompletion.amazon.com/api/2017/suggestionsJSON object. ~10 shopping suggestions, scoped to a department
eBayautosug.ebay.com/autosugJSONP. ~10 suggestions plus the categories eBay maps the query to
DuckDuckGoduckduckgo.com/ac/JSON array. 8 suggestions, no locale

Four things catch naive scrapers here, and all four are handled:

The bodies are not what the headers say. Google serves

content-type: text/javascript
with a content-disposition: attachment header, and the body is JSON. eBay serves application/json with a body that is not JSON — it is JSONP, wrapped in /**/vjo.darwin.domain.finding.autofill.AutoFill._do(…) with a comment prologue and a dotted callback name. Nothing here trusts a content type.

The array shape differs per client. Google's chrome client answers five elements, its firefox client four, Bing five with a different arrangement, and DuckDuckGo two. The parser finds the suggestions at index 1 and the metadata by looking for an object rather than by counting — which is also why Bing's relevance scores come through even though only Google documents them.

Expansion is the whole trick, and it is arithmetic. Each expansion term is one more request per source. The input schema states the count for every expansion so the cost is visible before the run, not after it, and maxRunSecs stops a run that would not finish.

Not every engine welcomes every address. Google, Bing, YouTube, Amazon and eBay all answer Apify's cheap datacenter proxy. DuckDuckGo does not — it closes the connection before TLS completes. When an endpoint refuses an exit IP — HTTP 429, HTTP 403, or a body that is not the expected JSON — that session is retired and the same request goes out once more from a different address. Retrying on an address that was just refused only deepens the block, so it is never done. If the second address is refused too, that keyword and engine stop, keep every suggestion already collected, and file one free blocked row saying where it stopped. Google additionally has a second client (firefox) that is tried before anything is called a block.

How it compares

  • Six engines, one schema. Search intent, video intent and buying intent in the same table, with source as a column rather than three different tools.
  • alsoFrom is a real signal. With dedupe on, a suggestion that turned up under twelve different prefixes carries alsoFrom: 12. That is the engine telling you how much it wants to suggest that phrase — free, and available nowhere else.
  • Failures are free and legible. A seed nobody suggests anything for, an engine that refused the run, a source name that does not exist: each produces a diagnostic row with an errorType you can branch on, and no charge. A run whose keywords were all usable but produced nothing — a seed no engine completes, an engine that refused us — finishes SUCCEEDED with zero results, a status message that says so, and a free diagnostic row per keyword and source telling you why; nothing is charged, start fee included. A run finishes FAILED only when there was nothing usable to attempt (no keyword, or no source this Actor knows), or the Actor itself hit an error.
  • A partial run is kept, not thrown away. Hit maxRunSecs or your charge ceiling halfway through an alphabet expansion and you keep the letters already collected.
  • Honest about what is not here. No search volume, no CPC, no difficulty score — see Limits below, in detail, rather than as a footnote.
  • No login, ever. No Google account, no Keyword Planner, no cookie jar, no session token. Public endpoints only, which is also why it runs under Apify's limited permissions.

Input reference

FieldTypeDefaultWhat it does
keywordsarray of stringsprefilled with twoSeed keywords. Compared case- and space-insensitively; up to 200 per run, each under 200 characters
sourcesarray["google","youtube","bing"]Which engines to ask: google, youtube, bing, amazon, ebay, duckduckgo. Each is one request per query
expansionsarray[]alphabet (+26 queries), numbers (+10), questions (+26, appended and prepended), prepositions (+12), comparisons (+11). All five is 86 queries per seed per source
languagestringenISO 639-1. Google/YouTube hl; folded into Bing's market
countrystringusISO 3166. Google/YouTube gl; upper-cased into Bing's market; mapped to eBay's site ID. Amazon ignores it
maxSuggestionsPerQueryinteger20How many to keep per query. The engines' own ceilings are 15 (Google), ~25 (Bing), ~10 (the rest)
dedupebooleantrueOne row per unique suggestion per seed and source, with alsoFrom counting the other queries that returned it. Off: every query keeps its own rows
amazonDepartmentstringapsAmazon's search alias — aps is all departments, electronics, books, sporting… scope it
maxConcurrencyinteger4(keyword, source) pairs in parallel. Each worker keeps its own proxy session
maxRunSecsinteger240Whole-run wall-clock budget. When it runs out the Actor keeps what it has and files a free diagnostic row for each job it never finished
proxyConfigurationobjectApify datacenterFive of six engines answer datacenter addresses. DuckDuckGo needs RESIDENTIAL

Output reference

ColumnOn which rowsWhat it is
ok, rowTypealltrue plus keyword, or false plus diagnostic
input, seedallThe seed as you typed it, and its normalised form
sourceallWhich engine — rows come out grouped by engine
suggestionkeywordThe keyword itself, verbatim
positionkeyword1-based rank within the query that produced it
query, expansion, modifier, modifierPositionkeywordThe exact prefix sent, and how it was built from the seed
relevancekeywordThe engine's own ordering score — Google and Bing publish one; not a search volume
suggestTypekeywordQUERY from Google, KEYWORD from Amazon, null elsewhere
alsoFromkeywordHow many other queries returned the same suggestion. Null when dedupe is off
wordCount, containsSeedkeywordLong-tail filter, and whether the engine stayed on your phrase
marketplace, ebayCategorieskeywordamazon.com / ebay.co.uk …, and the departments eBay maps the query to
language, countryallThe locale this run asked for
sourceUrlkeywordThe exact endpoint the row was read from, so any row can be checked by hand
error, errorTypediagnosticWhat went wrong, and a type to branch on
scrapedAtallWhen the row was written, UTC

errorType is one of no-results, blocked, timeout, invalid-input.

Pricing

$0.20 per 1,000 keywords. Pay-per-event, with proxy already inside that number — there is no separate proxy line on your bill for this Actor.

EventWhat triggers itFREEStarterScaleBusiness
Keyword returned (primary)One keyword row written to your dataset$0.0002$0.0002$0.00016$0.00012
Run startedOnce per run, after the first paid row$0.001$0.001$0.001$0.001

Quick-look example. The prefill — 2 seeds, 3 engines, no expansion: about 90 keywords × $0.0002 + $0.001 = $0.019, from six requests.

Research example. One seed, alphabet + questions, three engines: 159 requests, typically 400–900 unique keywords = $0.08–$0.18 per seed.

Seed-list example. 50 keywords, no expansion, three engines: 150 requests, about 2,250 keywords = $0.451. Weekly, that is about $1.95 a month.

What you are never charged for: a query that returned no suggestions, a keyword no engine suggests anything for, a keyword that was empty or too long, a source name this Actor does not have, a job the run never reached before maxRunSecs, or a request an endpoint blocked. Duplicates folded by dedupe are billed once, not once per query that found them. If a whole run comes back empty it finishes SUCCEEDED with zero results and a "0 results" status message, and bills nothing at all, start fee included.

Set ACTOR_MAX_TOTAL_CHARGE_USD on a run and the Actor stops asking once the ceiling is in sight, rather than handing you rows it cannot bill or billing you for rows it cannot hand over. It finishes SUCCEEDED with the ceiling named in its status message, and everything already delivered is yours.

Limits, and the ones that might bite

No search volume, no CPC, no difficulty. Autocomplete endpoints publish suggestions, not metrics. relevance is Google's and Bing's own ordering score: it is comparable within one query and meaningless across queries, and it is not a monthly search count. alsoFrom is the closest thing here to a popularity signal, and it is a signal about the engine's suggestion graph, not about volume. Anything that claims real search volume for arbitrary keywords without an ads account is estimating.

Amazon is US-only. completion.amazon.co.uk and completion.amazon.de answer HTTP 200 with suggestions: [] for every prefix — measured on 2026-09-11 from both datacenter and residential exits — so this Actor ships the one marketplace that works, ignores country for Amazon, and marks every Amazon row marketplace: "amazon.com". amazonDepartment still scopes it to a department. If Amazon's other completion hosts start answering, that is a change to make here, not a workaround to attempt in your input.

DuckDuckGo needs a residential proxy. It closes datacenter connections before the TLS handshake finishes. If duckduckgo is in sources, set proxyConfiguration to {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}. With the datacenter default the Actor still tries, and files one free blocked row per keyword saying exactly this — it does not fail your run or silently skip the engine.

Locale is a request, not a guarantee. hl/gl change what Google suggests, and the German captures show it plainly. Bing's market=de-DE is weaker: eight of twelve suggestions for a German seed came back in English. eBay's site ID does change the list. DuckDuckGo has no locale parameter at all. What you get is what the engine chose to do with the locale you asked for.

Suggestions are personalised and volatile. These endpoints answer differently by region, by time of day, and sometimes by exit IP. Two runs an hour apart will not match exactly, and they should not — that is the data being live rather than cached. Key a time series on scrapedAt and expect churn at the bottom of every list.

Expansion cost is linear and it adds up. Each term is one request per source. Five expansions × six sources × 50 seeds is 25,800 requests and roughly 40 minutes at the default concurrency — inside the 3,600 s ceiling, but only just. Raise maxRunSecs before you raise the expansion count, or split the seed list.

The ceilings are the engines', not ours. maxSuggestionsPerQuery: 50 does not make Google send 50. Google's chrome client sends 15, Bing about 25, and YouTube, Amazon, eBay and DuckDuckGo about 10 each. The way to get more keywords is more prefixes, which is what the expansions are for.

containsSeed: false is common and is not an error. Autocomplete drifts — ask for best crm and Google will happily suggest something that does not contain the phrase. Those rows are often the useful ones; the column is there so you can split them out either way.

The upstream format may change. These endpoints are undocumented and their owners change them without notice — that is true of every tool that reads this data, including the ones that do not say so. When a shape changes, rows stop arriving and you get free blocked diagnostic rows rather than quietly wrong data, and a run that returns nothing bills nothing.

Rate and reliability. Requests go out through proxy sessions pinned per worker, one rotation per block, and a 150–300 ms pause between queries of the same job. Four jobs in parallel is the default; no rate limiting was observed at one to two requests per second per source, but raising maxConcurrency a long way is how you would find some.

Use it from an AI agent, or from code

One JSON object in, one flat array out — the shape agent runtimes want. The Actor runs with limited permissions, uses pay-per-event pricing and never enters Standby, so it works over the Apify MCP server and with x402 agentic payments. The Integrations tab pushes results to Slack, a webhook, Zapier, Make, Google Sheets, Snowflake or BigQuery.

curl -X POST "https://api.apify.com/v2/acts/insight.solutions~keyword-suggestions-api/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"keywords":["best crm"],"sources":["google","bing"],"expansions":["questions"]}'
# pip install apify-client
from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("insight.solutions/keyword-suggestions-api").call(run_input={
"keywords": ["best crm", "crm for real estate"],
"sources": ["google", "bing"],
"expansions": ["alphabet", "questions"],
})
rows = [r for r in client.dataset(run["defaultDatasetId"]).iterate_items() if r["ok"]]
long_tail = sorted(
(r for r in rows if r["wordCount"] >= 4),
key=lambda r: r["alsoFrom"] or 0,
reverse=True,
)
for row in long_tail[:20]:
print(row["alsoFrom"], row["source"], row["suggestion"])

FAQ

Do I need a Google account, Search Console or Keyword Planner? No. Every source here is the public autocomplete endpoint the engine's own search box calls on each keystroke. No login, no API key, no cookie.

Does this give me search volume? No, and nothing that reads autocomplete can. You get the suggestions, their rank, the engine's own relevance score where it publishes one, and alsoFrom — how many different prefixes led to the same phrase. For monthly volume you need an ads account; this is the other half of the job, the part that tells you which phrases exist.

What is alsoFrom, exactly? With dedupe on, the count of other queries in the same run that returned the same suggestion for the same seed and source. Run an alphabet expansion and a phrase with alsoFrom: 20 came back under twenty of the twenty-six letters. That is a keyword the engine really wants to suggest.

How many keywords will one seed give me? Seed only, three engines: 40–50. Add alphabet and you are usually in the 300–500 range; add questions too and 400–900 is typical. It depends entirely on how broad the seed is — a narrow seed returns empty lists for most letters, and those cost you nothing.

Why did I get fewer than maxSuggestionsPerQuery? Because the engine sent fewer. Google's chrome client tops out at 15, Bing at about 25, the rest at about 10. The setting is a cap, not a request.

Why is Amazon only US? Because the other Amazon completion hosts answer with an empty list for every prefix, from every exit IP we tested. Shipping them would mean returning "no suggestions" rows that look like a property of your keyword rather than of the endpoint.

Why did DuckDuckGo give me a blocked row? Because the run used datacenter proxy. DuckDuckGo closes those connections before TLS completes. Set apifyProxyGroups: ["RESIDENTIAL"] and it answers.

Can I get suggestions in another language? Set language and country. Google honours them well, eBay changes storefront, Bing honours them loosely, and DuckDuckGo has no locale parameter at all. The language and country columns record what you asked for on every row.

How do I deduplicate between runs? On (seed, source, suggestion) lower-cased — the same key this Actor de-duplicates on within a run. scrapedAt gives you the version.

What happens if one engine fails? The others still run. The failed one produces a free diagnostic row for that keyword and the run finishes SUCCEEDED. If every job fails, the run still finishes SUCCEEDED — with zero results, a "0 results" status message pointing at the diagnostic rows, and nothing billed at all. It finishes FAILED only when there was nothing usable to attempt or the Actor itself hit an error.

Is the data fresh? Live. Every run calls the endpoints at that moment; nothing is cached.

  • Public endpoints only. These are the same autocomplete endpoints a browser calls while you type. The Actor never logs in, never accepts cookies or session tokens, and never uses an API key belonging to anyone else. The Amazon request carries a fixed placeholder session-id because the endpoint requires the parameter to be present; it identifies nobody and no customer ID is ever sent.
  • No personal data is collected. A keyword suggestion is an aggregate of what many people typed, published by the engine. If one of your seeds is a person's name, the suggestions you get back may be about that person — that is your input and your responsibility, and the ordinary data-protection rules apply to what you do with the result.
  • Suggestions are the engines' output, not facts. Autocomplete reflects what is typed, including things that are wrong, unkind or defamatory about a person or a business. Treat a row as evidence of what is searched for, not as a claim about the world.
  • Not affiliated with Google, Microsoft, Amazon, eBay or DuckDuckGo. All names and trademarks belong to their owners and are used only to describe which public endpoints this Actor reads.

Our other Actors

Every Insight Solutions Actor is pay-per-result with no browser, no login and no API key, and every one of them returns free diagnostic rows instead of billing for failures. Prices are per 1,000 results.

Video, audio & social

News, documents & the web

Business, finance & jobs

Apps & games