# Keyword Ideas: Google, YouTube & Bing Autocomplete (`khalilbenali/keyword-ideas-autocomplete`) Actor

Long-tail keyword ideas from Google, YouTube, Shopping and Bing autocomplete, ranked by cross-engine consensus, with Google Trends direction. HTTP only.

- **URL**: https://apify.com/khalilbenali/keyword-ideas-autocomplete.md
- **Developed by:** [khalil ben ali](https://apify.com/khalilbenali) (community)
- **Categories:** SEO tools, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 keyword ideas

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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 does Keyword Ideas: Google, YouTube & Bing Autocomplete do?

Keyword Ideas turns a few seed keywords into hundreds of long-tail keyword ideas. It reads the suggestion boxes of **Google**, **YouTube**, **Google Shopping** and **Bing**, expands every seed with letters, digits, question words, prepositions and your own modifiers, and merges everything into one clean list. Each idea is saved once per seed, with every engine that suggested it, its position in each engine's list and the query that found it. An idea is charged once per run, even when several seeds produce it.

Two things set it apart from a plain autocomplete scraper:

- **Cross-engine consensus.** An idea that two or three engines suggest independently is a stronger signal than one that appears in a single box. Ideas are ranked by how many engines suggested them, then by their best position.
- **Trend direction.** Optionally, the best ideas of each seed get a Google Trends verdict: rising, flat or falling, from 12 months of weekly interest. It uses the same HTTP-only engine as our [Google Trends Scraper](https://apify.com/khalilbenali/google-trends-scraper).

You pay once per unique idea in the whole run, never for duplicates.

### Why do consensus and trend direction matter?

Autocomplete tells you what people type, but not which ideas deserve your time. When Google, Bing and YouTube all complete "coffee grinder" with "for espresso", that phrase is worth a page, a video or an ad group. A keyword that only one box shows may be a local quirk. Trend direction adds the missing question: is interest growing or fading? Falling ideas can be skipped before you write for them, and rising ones can be prioritised.

### Use cases

- **SEO:** build topic clusters and long-tail lists, and find the questions people ask (`isQuestion`).
- **Content planning:** turn a topic into an editorial calendar of ideas that more than one engine suggests.
- **YouTube creators:** use the YouTube box to find video titles that people already search for.
- **E-commerce:** use the Google Shopping box to find product phrases, brands and "vs" comparisons.
- **PPC:** harvest keyword candidates, and use `engineCount` and the trend to pick the strongest.
- **AI agents and automation:** flat, predictable items with a stable schema, callable through the Apify API or MCP.

### How to use it

Open the Input tab, add your seeds and choose the engines. The default input expands one seed on Google and Bing with the seed itself, `a` to `z` and twelve question words (39 queries per engine). It finishes in about two minutes.

#### Quick start

```json
{
    "seeds": ["coffee grinder"],
    "engines": ["google", "bing"],
    "country": "US",
    "language": "en",
    "expansions": ["alphabet", "questions"]
}
```

#### Expansions

- `alphabet`: "seed a" to "seed z" (26 queries per engine). On by default.
- `digits`: "seed 0" to "seed 9" (10 queries).
- `questions`: "how seed", "what seed", "why", "can", "are", "is", "does", "should", "which", "where", "when", "who" (12 queries). On by default.
- `prepositions`: "seed for", "seed with", "seed near", "seed vs", "seed without", "seed to", "seed like" (7 queries).
- `custom`: your own `customModifiers`, for example `best`, `cheap`, `2026`, used as a prefix and as a suffix.

The seed itself is always queried. Set `maxQueriesPerSeed` to cap the first-level queries per seed and engine (0 means no cap).

#### Depth 2

```json
{ "seeds": ["standing desk"], "expansions": ["questions"], "depth": 2, "recursionTopN": 10 }
```

Depth 2 takes the best `recursionTopN` ideas of each seed and queries each one again as plain text. It finds ideas two steps away from the seed. These items carry `depth: 2` and the idea they came from in `parent`.

#### Trend direction

```json
{ "seeds": ["coffee"], "engines": ["google"], "includeTrend": true, "trendTopN": 5, "trendGeo": "US" }
```

The top `trendTopN` ideas of each seed (default 20, at most 100) are looked up on Google Trends. The direction is **rising** when the average of the last 13 weeks is more than 15% above the 13 weeks before, **falling** when it is more than 15% below, and **flat** otherwise. The running week is left out because it is not finished. Each lookup takes about five seconds.

### Output

Results are available as JSON, CSV, Excel and more from the Output tab and the dataset API. One item per unique idea and seed:

```json
{
    "keyword": "coffee grinder for espresso",
    "seed": "coffee grinder",
    "sources": [
        { "engine": "google", "position": 1, "relevance": 601, "query": "coffee grinder" },
        { "engine": "youtube", "position": 3, "relevance": 601, "query": "coffee grinder" },
        { "engine": "bing", "position": 11, "relevance": null, "query": "coffee grinder" }
    ],
    "engineCount": 3,
    "firstQuery": "coffee grinder",
    "modifierType": "seed",
    "depth": 1,
    "parent": null,
    "duplicateOf": null,
    "country": "US",
    "language": "en",
    "wordCount": 4,
    "isQuestion": false,
    "status": "ok",
    "scrapedAt": "2026-10-10T12:00:00.000Z",
    "trend": {
        "direction": "falling",
        "averageValue": 35.6,
        "recentAverage": 22.77,
        "previousAverage": 33.46,
        "changePercent": -32,
        "peakMonth": "2026-02"
    },
    "trendStatus": "ok"
}
```

- Ideas are lower case with single spaces and no trailing punctuation. The seed itself is never an idea.
- `duplicateOf` is `null` for the first copy of an idea. If the same idea turns up under a later seed, it is saved again with that seed's own sources and trend, and `duplicateOf` names the seed where it was first saved. These repeats are free.
- `sources` has one entry per engine, its best-ranked occurrence. `relevance` is Google's own score and is `null` for the other engines.
- `modifierType` tells how `firstQuery` was built: `seed`, `alphabet`, `digit`, `question`, `preposition`, `custom` or `recursion`.
- `trend` and `trendStatus` appear only with `includeTrend`. They are `null` for ideas that were not looked up. Trend values are Google's relative 0-100 index for that idea, not search counts.
- The Output tab also links the **ENGINE_STATUS** record: for every engine its HTTP requests, ideas, status and a message.

### Pricing

You pay per result, in plain words. There is no separate charge for compute.

| Event                                         | Free / Bronze | Silver  | Gold    | Platinum | Diamond |
| --------------------------------------------- | ------------- | ------- | ------- | -------- | ------- |
| Run start (one per GB of memory, minimum one) | $0.003        | $0.003  | $0.003  | $0.003   | $0.003  |
| `idea`: one per unique idea saved             | $0.001        | $0.0009 | $0.0008 | $0.0008  | $0.0008 |
| `trend-signal`: one per trend direction found | $0.002        | $0.0018 | $0.0016 | $0.0016  | $0.0016 |

Apify charges the run start once per GB of memory, minimum one. The default 256 MB counts as one, and the Actor never needs more. The Pricing tab of this page is authoritative: if it differs from this table, it wins.

What is charged, exactly:

- **An idea is charged once per run.** If the same idea appears under several seeds, the first copy is charged and the later copies (`duplicateOf` is set) are free.
- **A trend signal is charged once per idea and run**, when its Google Trends direction was found. Ideas without Google Trends data, and lookups that were blocked or failed, are free. A trend that is reused for a repeat of an idea is not charged again.
- Engines that were skipped or blocked cost nothing, and nothing is charged for results that were not saved.

Worked examples at the Free/Bronze price:

- 300 ideas: 300 x $0.001 = $0.30 (plus the $0.003 start, about $0.30).
- 300 ideas and 20 trend signals: $0.30 + 20 x $0.002 = $0.34.

If you set a maximum cost per run, the Actor stops cleanly when it is reached and keeps what it saved.

### FAQ

#### Why are Amazon, eBay and DuckDuckGo not included?

Their robots.txt files disallow their suggestion endpoints, and this Actor respects robots.txt. It also checks robots.txt at runtime for every host it calls. If a path ever becomes disallowed, that engine is skipped and reported as `robotsDisallowed`.

#### How many ideas will I get, and how long does it take?

Google, YouTube and Google Shopping answer from one host, and Bing from another. Every host gets one request at a time with a pause of 1.6 to 2.5 seconds, so a query takes about two seconds. The default input sends 39 queries per engine, which is **about 1.5 to 2 minutes per seed per host**. Seeds run one after the other, and the engines of different hosts run in parallel. So the default input (Google and Bing) takes about 1.5 to 2 minutes per seed, and every additional engine on the Google host (YouTube, Shopping) adds about the same again. Trend lookups add about five seconds per idea. Google returns up to 15 suggestions per query and Bing 12 to 24, and the merged list is typically a few hundred ideas per seed. `maxIdeasPerSeed` (default 500, at most 5000) keeps the best-ranked ideas and stops an engine once enough are collected. Seeds are limited to 50 per run.

#### What happens if the run is about to hit its time limit?

Fifty seeds on the default input take more than an hour, which is the default run timeout. The Actor reads the platform's time limit and, when less than 90 seconds are left, starts no new seed, query or trend lookup. It saves what it collected, and ends with a status message that says it stopped early. Raise the run timeout, or use fewer seeds or expansions, to collect the rest.

#### Is it legal?

The Actor reads public, aggregated suggestions that the engines show to anyone typing in a search box. It collects no personal data and uses no logins or cookies from user accounts. You remain responsible for using the data in line with each engine's terms and the laws that apply to you. This Actor is not affiliated with or endorsed by Google, YouTube or Microsoft.

#### What do the statuses mean?

Every saved idea has `status: ok`. Problems are reported per engine in the ENGINE_STATUS record and in the final status message:

- `ok`: the engine answered normally.
- `robotsDisallowed`: its robots.txt disallows the suggestion endpoint, so it was not called.
- `blocked`: the engine rate-limited the run (HTTP 403 or 429 three times in a row), or the host returned a web page instead of JSON, or redirected the request, which is how bot checks and consent pages are served. A web page or redirect stops every engine on that host: Google, YouTube and Google Shopping share one. The other engines carry on. The Actor never tries to solve or evade a CAPTCHA or bot check.
- `error`: three queries in a row failed, or its robots.txt could not be loaded (the engine is skipped rather than guessed at).

An engine that was stopped stays stopped if the run is restarted by the platform.

`trendStatus` is `ok` (charged), `noData` (Google Trends has no data for the idea, free), `blocked` or `error` (free). Long-tail ideas often have too little volume for Google Trends, so `noData` is normal. After three CAPTCHA or consent pages from Google Trends in one run, no further trend lookups are made and the rest are `blocked`. If no idea could be collected because every engine was blocked, the run fails with an explanation instead of ending empty.

#### Why are some Bing suggestions missing?

For many seeds Bing appends templated places to its answers, for example "coffee grinder best in london" or "... in madrid". When such a suffix repeats across several different queries and its place is a known city, country or region, it is template noise, not an idea, and it is dropped. "near me" is dropped only when it repeats across three or more alphabet letters for a seed that is not local (it is kept for "dentist"). Suffixes like "in python" or "in excel" are never dropped. A suggestion that Google, YouTube or Google Shopping also produced for the seed is never dropped. Suggestions that only repeat the query you sent are removed too.

#### Why does Google Trends use a proxy from the first request?

By design. The Trend direction option uses the same HTTP-only client as our Google Trends Scraper, which runs through an Apify datacenter proxy session on the platform from its first request, because Google Trends rate-limits Apify's shared IPs much sooner without one. The suggestion hosts are different: they are called directly, and only after repeated HTTP 429 or 5xx answers does a host move to an Apify datacenter proxy session (never residential). If a proxy session does not connect, the Actor rotates to a new session once and then goes direct, instead of waiting out timeouts.

#### What happens if the platform migrates or restarts my run?

The Actor saves its progress to the run's key-value store. After a migration it continues where it stopped: queries that were answered are not sent again, trend answers that were already found (ok or no data) are not looked up again, and ideas that were already saved are neither saved nor charged a second time. Trend lookups that were blocked or failed are tried again, except after the bot-check cap. Once a seed's list of ideas to save is fixed, a restarted run saves exactly that list, so it never exceeds `maxIdeasPerSeed`.

#### What are the limits?

- Suggestions show what people type, not how often. There are no search volumes.
- Trend direction needs enough Google Trends data. It is relative interest per idea and is not comparable between ideas.
- The engines can change their endpoints at any time. Report problems through the Issues tab.

### Changelog

- **1.0 (2026-10-10):** first release with Google, YouTube, Google Shopping and Bing autocomplete, alphabet, digit, question, preposition and custom expansions, depth 2, cross-engine consensus ranking, Bing template-noise filter, Google Trends direction, robots.txt checks, migration-safe resume, a run time-limit guard and pay-per-event pricing (one charge per unique idea per run).

# Actor input Schema

## `seeds` (type: `array`):

The topics to find ideas for, for example "coffee grinder". 1 to 50 seeds. Whitespace is trimmed, and duplicates and empty lines are ignored. Every seed is expanded separately. If the same idea turns up under more than one seed it is saved under each of them, but it is charged only once per run: the later copies carry duplicateOf (the seed where it was first saved) and are free.

## `engines` (type: `array`):

Whose suggestion box to read. Ideas that several engines suggest rank higher. Google, YouTube and Google Shopping share one host, so they are queried one after the other.

## `country` (type: `string`):

Two-letter country code that localises the suggestions, for example US, GB, FR or DE.

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

Language code of the suggestions, for example en, fr, de or pt-BR. Use the language your seeds are written in.

## `expansions` (type: `array`):

How each seed is multiplied into queries. The seed itself is always queried. Alphabet adds "seed a" to "seed z" (26 queries per engine), Digits "seed 0" to "seed 9" (10), Questions "how seed", "what seed" and ten more question words (12), Prepositions "seed for", "seed with" and five more (7), and Custom your own modifiers as prefix and suffix. More expansions mean more ideas and a longer run.

## `customModifiers` (type: `array`):

Words to add before and after each seed, for example best, cheap or 2026. Used when Custom is selected in Expansions. Up to 50 modifiers, each at most 40 characters.

## `depth` (type: `integer`):

1 expands each seed once. 2 also re-expands the best ideas of depth 1 with plain queries (one query per idea and engine), which finds ideas two steps away from the seed.

## `recursionTopN` (type: `integer`):

With depth 2: how many of the best-ranked ideas per seed are expanded again. 1 to 50.

## `maxIdeasPerSeed` (type: `integer`):

Keeps the best-ranked ideas of each seed (most engines first, then best position) and stops asking an engine once enough ideas are collected. Also caps what you can be charged per seed. 1 to 5000.

## `includeTrend` (type: `boolean`):

Adds a trend object to the best-ranked ideas of every seed: rising, flat or falling, from 12 months of weekly Google Trends interest. Ideas that Google Trends has data for are charged one extra trend-signal event. It adds about 5 seconds per idea.

## `trendTopN` (type: `integer`):

How many of the best-ranked ideas per seed get a trend lookup. 1 to 100. Used when Add Google Trends direction is on.

## `trendGeo` (type: `string`):

Google Trends region for the trend lookup, for example US, FR or US-CA. Leave empty to use the country above.

## `maxConcurrency` (type: `integer`):

How many engines are queried at the same time. Each host still gets one request at a time, with a pause of 1.6 to 2.5 seconds between requests. 1 to 4.

## `maxQueriesPerSeed` (type: `integer`):

A hard cap on the first-level queries sent per seed and engine, in priority order: seed, custom, questions, prepositions, alphabet, digits. 0 means no cap. Useful for quick tests.

## Actor input object example

```json
{
  "seeds": [
    "coffee grinder"
  ],
  "engines": [
    "google",
    "bing"
  ],
  "country": "US",
  "language": "en",
  "expansions": [
    "alphabet",
    "questions"
  ],
  "customModifiers": [],
  "depth": 1,
  "recursionTopN": 10,
  "maxIdeasPerSeed": 500,
  "includeTrend": false,
  "trendTopN": 20,
  "trendGeo": "",
  "maxConcurrency": 4,
  "maxQueriesPerSeed": 0
}
```

# Actor output Schema

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

One item per unique idea and seed.

## `trend` (type: `string`):

Ideas with their Google Trends direction (Add Google Trends direction).

## `sources` (type: `string`):

One row per idea and engine that suggested it.

## `engineStatus` (type: `string`):

Requests, ideas, status and message of every engine (ok, robotsDisallowed, blocked or error).

# 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 = {
    "seeds": [
        "coffee grinder"
    ],
    "engines": [
        "google",
        "bing"
    ],
    "country": "US",
    "language": "en",
    "expansions": [
        "alphabet",
        "questions"
    ],
    "depth": 1,
    "recursionTopN": 10,
    "maxIdeasPerSeed": 500,
    "includeTrend": false,
    "trendTopN": 20,
    "trendGeo": "",
    "maxConcurrency": 4,
    "maxQueriesPerSeed": 0
};

// Run the Actor and wait for it to finish
const run = await client.actor("khalilbenali/keyword-ideas-autocomplete").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 = {
    "seeds": ["coffee grinder"],
    "engines": [
        "google",
        "bing",
    ],
    "country": "US",
    "language": "en",
    "expansions": [
        "alphabet",
        "questions",
    ],
    "depth": 1,
    "recursionTopN": 10,
    "maxIdeasPerSeed": 500,
    "includeTrend": False,
    "trendTopN": 20,
    "trendGeo": "",
    "maxConcurrency": 4,
    "maxQueriesPerSeed": 0,
}

# Run the Actor and wait for it to finish
run = client.actor("khalilbenali/keyword-ideas-autocomplete").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 '{
  "seeds": [
    "coffee grinder"
  ],
  "engines": [
    "google",
    "bing"
  ],
  "country": "US",
  "language": "en",
  "expansions": [
    "alphabet",
    "questions"
  ],
  "depth": 1,
  "recursionTopN": 10,
  "maxIdeasPerSeed": 500,
  "includeTrend": false,
  "trendTopN": 20,
  "trendGeo": "",
  "maxConcurrency": 4,
  "maxQueriesPerSeed": 0
}' |
apify call khalilbenali/keyword-ideas-autocomplete --silent --output-dataset

```

## MCP server setup

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

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/RDGPZze5NWIhaCSTx/builds/AEqUkVgjLtrqkXkPP/openapi.json
