# google-search-autocomplete-scraper-youtube-suggestions (`scraper-engine/google-search-autocomplete-api`) Actor

Scrape Google Search autocomplete suggestions in real time. Collect keyword ideas, query variations, trending searches, and long-tail phrases at scale. Ideal for SEO research, content planning, PPC targeting, and market analysis. Export structured results in JSON, CSV, or Excel.

- **URL**: https://apify.com/scraper-engine/google-search-autocomplete-api.md
- **Developed by:** [Scraper Engine](https://apify.com/scraper-engine) (community)
- **Categories:** Automation, Lead generation, Social media
- **Stats:** 6 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$14.99/month + usage

To use this Actor, you pay a monthly rental fee to the developer. The rent is subtracted from your prepaid usage every month after the free trial period.You also pay for the Apify platform usage, which gets cheaper the higher Apify subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#rental-actors

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### Google Autocomplete Scraper — Web and YouTube Suggestion Overlap

Google + YouTube Autocomplete Scraper expands each seed keyword into the live autocomplete suggestions Google shows in its web search box and in YouTube's search box, then compares the two lists. Every row returns `webSuggestions`, `youtubeSuggestions`, the terms that appear on `bothSourcesSuggestions`, and per-source counts — structured JSON, no HTML parsing. No account, login or API key is involved. Paste your seeds and press Start.

⚠️ **Read the row-count and charging section before your first run.** The two A-Z expansion toggles multiply your row count by 26 each, every pushed row is charged, and autocomplete carries no search-volume data. All three are explained below.

### What is Google + YouTube Autocomplete Scraper?

Google + YouTube Autocomplete Scraper is an Apify Actor that calls Google's public keyless suggest endpoint once per seed per corpus and flattens the response into one dataset row per query. It returns the suggestion strings themselves — the ranked phrases the type-ahead box would show — plus a cross-source overlap analysis between the Google web list and the YouTube list.

No Google account, YouTube account, login, cookie, OAuth token or API key is required, and no captcha-solver key either. The only credential in play is your Apify token. The first request of a run goes out with no proxy at all.

It is built for SEO and PPC teams mining long-tail keywords, content and video strategists who need to know where search intent and video intent diverge, and developers feeding real query phrasing into agents and search UIs.

### What Google and YouTube autocomplete data is publicly available to scrape?

Google's suggest endpoint serves a ranked list of suggestion strings to any anonymous caller, for either corpus, with no key. What it does not serve is any metric about those strings — no volume, no cost, no competition, no trend line.

| Data Category | Public on the suggest endpoint | Not available this way |
| ----- | ----- | ----- |
| Ranked Google web suggestions for a seed | ✅ Public — anonymous GET, no key | — |
| Ranked YouTube search suggestions for a seed | ✅ Public — same endpoint, `ds=yt` | — |
| Suggestion rank order | ✅ Public — array order is preserved as returned | — |
| Language and country localisation (`hl`, `gl`) | ✅ Public — passed on every request | — |
| Monthly search volume per suggestion | ❌ | Not in the response at all — a keyword-volume product |
| CPC, competition, keyword difficulty | ❌ | Paid keyword tools |
| Interest over time / trend series | ❌ | Google Trends, a separate product |
| Suggestion subtitles, thumbnails, entity types | ❌ | Not in the `client=firefox` response shape this Actor uses |
| Suggestions personalised to a signed-in user | ❌ | Requires a logged-in session — none is used here |

Google + YouTube Autocomplete Scraper only returns publicly visible data — the same predictions any visitor's search box would show. Nothing behind a login wall.

### ⚠️ Row count, charging, and what a suggestion is not

Three things decide what a run costs and what it can tell you, so they get their own section instead of a footnote.

**A-Z expansion is what drives the row count.** By default each seed is queried exactly once and produces exactly one row. `alphabetPrefix` adds 26 extra queries per seed (`a minecraft`, `b minecraft` … `z minecraft`); `alphabetSuffix` adds another 26 (`minecraft a` … `minecraft z`). The formula is `seeds × (1 + 26 if prefix + 26 if suffix)` rows. Three seeds with both toggles off is 3 rows; three seeds with both on is **159 rows** and, with both sources selected, 318 HTTP requests. Both toggles default to `false` — turn them on deliberately.

**Every pushed row is charged, including rows that came back empty.** Charging is per saved row: one `row_result` event per row written. The row builder writes **no** error, status, type or outcome key at all — there are no uncharged accounting rows in this Actor and no marker to filter on. A seed that returns nothing still lands as a charged row carrying `webCount: 0`, `youtubeCount: 0`, `onBothSources: false` and no `suggestion_XX` keys. The closest thing to a failure filter is the counts themselves: `rec["webCount"] == 0 and rec["youtubeCount"] == 0`.

**Autocomplete suggestions carry no volume data.** The endpoint returns strings and nothing else. There is no `volume`, `cpc`, `competition` or `difficulty` field in this Actor's output, because there is none in the response. Rank order tells you which phrase Google offers first for that prefix; it is not a traffic estimate and should not be read as one. If you need volume, pair these suggestions with a keyword-volume source.

### What data can I extract with Google + YouTube Autocomplete Scraper?

Every row carries the query that was actually sent, both suggestion lists in full, the same lists flattened into numbered columns for spreadsheet use, and the cross-source overlap. Nine fixed keys, plus one numbered key per suggestion in each list.

| Field Name | Description |
| ----- | ----- |
| `query` | The query string actually sent to the endpoint. With A-Z expansion on this is the expanded form (`a minecraft`), not the original seed — no separate key carries the untouched seed |
| `suggestion_01`, `suggestion_02`, … | One key per **web** suggestion, two-digit zero-padded, numbered in the order Google returned them. Written only for suggestions that exist — omitted entirely rather than set to `null` |
| `sourcesQueried` | Array of the corpora actually queried for this row: `["web", "youtube"]`, `["web"]` or `["youtube"]`, always in that fixed order |
| `webSuggestions` | Full array of Google web suggestion strings, in returned rank order. `[]` when the corpus was not selected or came back empty |
| `webCount` | Integer length of `webSuggestions` |
| `youtubeSuggestions` | Array of YouTube suggestion strings. With `deduplicateSuggestions` on (the default) this holds only terms **not** already in the web list; with it off it is the raw YouTube list |
| `youtubeCount` | Integer length of `youtubeSuggestions` — that is, the **post-deduplication** count when dedup is on. The raw YouTube list length is `youtubeCount + overlapCount` in that case |
| `youtube_suggestion_01`, `youtube_suggestion_02`, … | One key per entry of `youtubeSuggestions`, two-digit zero-padded, same omit-don't-null rule as the web columns |
| `bothSourcesSuggestions` | Array of the terms that appear in **both** lists. Matching is case- and whitespace-insensitive; the strings are returned in YouTube's own spelling and order. Computed whether or not deduplication is on |
| `overlapCount` | Integer length of `bothSourcesSuggestions` |
| `onBothSources` | Boolean — `true` when `overlapCount` is greater than zero |

> The default dataset view shows 11 of these columns — `query`, `onBothSources`, `webCount`, `youtubeCount`, `overlapCount` and the first three suggestion columns from each source. `sourcesQueried`, `webSuggestions`, `youtubeSuggestions`, `bothSourcesSuggestions` and every numbered column past the third are in the JSON but not in that table view. Export as JSON to see everything.

#### Query and web suggestion fields

`query` is the join key for everything else, and it is the *sent* query rather than the seed you typed. Sorting a 159-row expansion run alphabetically on `query` therefore groups by expansion letter, not by seed — if you need the seed back, keep your own seed list and match on substring. `webSuggestions` is the canonical list and `suggestion_01` onwards is the same data flattened for CSV and Excel, which is why both exist. Google returns a variable number of suggestions per query, so the number of numbered columns varies row to row; a short list simply has fewer keys.

#### YouTube and cross-source overlap fields

`youtubeSuggestions` is the one field the `deduplicateSuggestions` toggle changes. On by default, it strips any term already present in the web list, so the column reads as *net-new video-search phrasing* — the queries people type into YouTube that they do not type into Google. Nothing is lost by leaving it on, because the stripped terms are exactly `bothSourcesSuggestions`; the raw list is `youtubeSuggestions` plus `bothSourcesSuggestions`. `onBothSources` is the cheap boolean to filter on when you want the seeds where the two audiences agree, and `overlapCount` is what you sort on when you want to rank that agreement.

Deduplication is scoped to a single row: one YouTube list against that same row's web list. Suggestions are **not** deduplicated across seeds or across A-Z expansions, so a phrase that legitimately answers both `a minecraft` and `minecraft a` appears in both of those rows.

#### 🤖 Add-on: Need additional Google or YouTube data?

Autocomplete tells you how people phrase a search; it does not tell you what they get back. **Youtube Search Scraper** takes a suggestion string straight out of `youtubeSuggestions` and returns the videos actually ranking for it, and **Youtube Video Details Scraper** goes a level deeper on any result. On the search side, **Ahrefs Scraper** and **MOZ Scraper** add the volume and difficulty metrics autocomplete cannot give you, and **Quora Search Scraper** surfaces the question phrasing behind the same intent.

### Why not build this yourself?

The request looks trivial — one GET, read the second element of the JSON array, done. What makes it a maintenance job is everything around that line.

The endpoint does not fail honestly. A block arrives as a 403, a 429, a 503, an empty body, or a 200 carrying something that is not the expected two-element array — so a naive scraper that trusts the status code writes hollow rows and never notices. This Actor treats all five of those as blocked and climbs a proxy ladder in response: no proxy, then Apify `GOOGLE_SERP` datacenter, then residential, sticking on residential once it gets there and retrying that rung up to three times with a 1s, 2s, 3s backoff before returning an empty list for that query. Building that ladder yourself means an equivalent proxy account, a blocked-response classifier, and a fallback state machine shared across concurrent requests.

Then there is the shape of the job. Language and country are not free text — they are the codes the endpoint expects, and mapping 77 language names and 190 country names onto them is a table you have to write and keep. A-Z expansion turns 3 seeds into 318 requests, which needs connection pooling and per-host limits rather than a naive loop. Cross-source overlap needs case- and whitespace-normalised matching or it reports false negatives on trivial spacing differences. None of that is visible until it is in production, and each fix costs a debugging session and a redeploy.

Neither Google nor YouTube publishes a supported public autocomplete API, so there is no official route to compare this against — check Google's current published terms and developer documentation before building on the suggest endpoint yourself.

### How to use Google + YouTube Autocomplete Scraper

Google + YouTube Autocomplete Scraper runs on Apify. Start it from the Apify Console or call it through the Apify API.

1. Open the Actor on Apify and click **Try for free**
2. Enter your seeds in **🌱 Seed keywords** (`queries`), one phrase per line — this is the **only required input**. The Console prefills three example seeds; clear them and paste your own
3. Pick your corpora in **📡 Suggestion sources** (`sources`). Both are selected by default
4. Set **🌐 Language** and **📍 Country** if you are researching a market other than English / United States
5. Leave the two **⚡ A-Z expansion** toggles off for a quick look; turn them on when you want long-tails and have read the row-count section above
6. Click **Start**, then export as JSON, CSV or Excel, or read the dataset through the Apify API

**A run with no seeds does nothing rather than guessing.** `queries` is marked required, so the Console will not let you start without it — but over the API an empty array reaches the code, which logs `No queries provided` and exits cleanly with zero rows and zero charges. There is no hardcoded fallback seed anywhere in this Actor; the three example phrases in the form are a schema prefill, not a default.

#### How to scale to bulk keyword expansion

`queries` is an array, so bulk is the normal mode: paste as many seeds as you like into one run and each is processed in turn. Two multipliers sit on top of that — `alphabetPrefix` and `alphabetSuffix`, worth 26 extra queries per seed each — and two corpora, each of which is a separate request. Queries are processed one at a time, with the web and YouTube fetches for the same query issued concurrently; the HTTP session is pooled at 20 total connections and 10 per host. For a recurring keyword set, save the input as an Apify task and attach a schedule rather than re-pasting seeds.

### What can you do with Google and YouTube autocomplete data?

- 🔍 **An SEO content strategist** planning a cluster runs one seed with `alphabetSuffix` on and mines `webSuggestions` across all 27 rows for the question and modifier phrasing that never shows up in a volume-based keyword tool.
- 📺 **A video strategist** deciding what to script filters rows on `youtubeCount` with `deduplicateSuggestions` left on, because `youtubeSuggestions` then holds only phrasing specific to video search rather than repeating the web list back.
- 🎯 **A PPC manager** building a negative-keyword list scans `webSuggestions` for the irrelevant modifiers Google attaches to a brand term — "free", "alternative", a competitor's name — before the budget finds them first.
- 🌍 **A market researcher** running the same seed set across several `targetCountry` values compares `bothSourcesSuggestions` per market to see which framings of a product are universal and which are local.
- 🤖 **An AI engineer** building a search agent indexes `query` and `webSuggestions` into a vector store so the agent can rewrite a vague user request into the phrasings people actually search, instead of inventing one from model priors.
- 📊 **A growth analyst** schedules a weekly run on a fixed seed list and diffs `webSuggestions` between runs to catch a new modifier entering the suggestion set — an early signal that interest is shifting.

Every one of these is callable from an agent framework over the Apify API, since the Actor is a standard HTTP-triggered run.

### How does Google + YouTube Autocomplete Scraper handle rate limits and blocking?

The endpoint serves this Actor without a proxy, and that is where every run starts: the proxy tier is initialised to `none` and the first requests go out on a direct connection. Escalation is automatic and one-way. A response counts as **blocked** when its status is 403, 429 or 503, when the body is empty or whitespace, when it is not valid JSON, or when it parses to something other than the expected two-element array — a soft block dressed as a 200 is caught by that last check rather than parsed into a hollow row.

On the first block the Actor moves to Apify's `GOOGLE_SERP` datacenter group, waits a second, and retries. On the next it moves to residential and stays there for the rest of the run. On residential it retries the same query up to three more times with a rising 1s, 2s, 3s pause; if all three fail it returns an empty suggestion list for that query and moves on. The run never stops on a single failure. Every request carries a 30-second total timeout and a 10-second connect timeout.

There is no captcha solving anywhere in this Actor, because the suggest endpoint does not put a challenge in front of these requests. There is also no browser — these are plain HTTP GETs.

### ⬇️ Input

Eight parameters, one of them required, read straight from the input schema.

| Parameter | Required | Type | Description | Example Value |
| ----- | ----- | ----- | ----- | ----- |
| `queries` | **Yes** | array | One seed phrase per line. Each seed is expanded into live autocomplete suggestions. `stringList` editor. A run that reaches the code with an empty array logs `No queries provided` and exits with zero rows. | `["minecraft", "best laptops 2024"]` |
| `sources` | No | array | Which autocomplete corpora to query per seed. `web` = Google web search suggest; `youtube` = YouTube search suggest. Multi-select editor. Default `["web", "youtube"]`. | `["web", "youtube"]` |
| `deduplicateSuggestions` | No | boolean | When on, the YouTube list drops any term already in the Google web list, so `youtubeSuggestions` holds only net-new video-search phrases — the shared terms are still reported in `bothSourcesSuggestions`. Turn off to keep the raw YouTube list. Default `true`. | `true` |
| `suggestionLanguage` | No | string | Interface language, sent as `hl`. Closed dropdown of 77 language names, mapped internally to their language codes. Default `"English"`. | `"Spanish"` |
| `targetCountry` | No | string | Geo the suggestions are localised for, sent as `gl`. Closed dropdown of 69 country names, mapped internally to two-letter codes. Default `"United States"`. | `"United Kingdom"` |
| `alphabetPrefix` | No | boolean | Prepend each letter a-z before every seed (`a minecraft`, `b minecraft` …) to mine more long-tails. Takes the query count to 27 per seed. Default `false`. | `false` |
| `alphabetSuffix` | No | boolean | Append each letter a-z after every seed (`minecraft a`, `minecraft b` …). Takes the query count to 27 per seed, or 53 combined with the prefix toggle. Default `false`. | `true` |
| `proxyConfiguration` | No | object | Optional proxy, `proxy` editor. Prefilled `{"useApifyProxy": true}`. See the note below for what it actually changes. | `{"useApifyProxy": true}` |

**Three things the schema does not show.**

`proxyConfiguration` does **not** force a proxy from the first request. Every run begins on a direct connection whatever you set here; the value is only read once the ladder has already escalated to the residential rung, at which point your settings are used instead of the built-in `RESIDENTIAL` group. If `useApifyProxy` is absent or falsy in your object, the built-in group is used anyway. It is a way to steer the residential fallback — a proxy country, for instance — not a way to skip the direct and datacenter rungs.

Several legacy input aliases are still accepted for backward compatibility, with the documented name taking precedence: `query` for `queries`, `usePrefix` / `use_prefix` for `alphabetPrefix`, `useSuffix` / `use_suffix` for `alphabetSuffix`, `language` for `suggestionLanguage`, and `country` for `targetCountry`. `queries` also accepts a bare string, which is treated as a one-item list, and `sources` does the same. Use the documented names.

`maxRetries` is read from the input and passed down, but the fetch routine never uses it — the residential retry count is fixed at three. Setting it changes nothing. Likewise, the language and country dropdowns are closed lists in the Console, but a value passed over the API that is not in the internal map falls back silently to `en` / `us` rather than failing, and a `sources` array containing neither `web` nor `youtube` falls back silently to `web` so a run never queries zero corpora.

#### Example input

Two seeds, both corpora, suffix expansion on, localised to the United Kingdom. This is a 2 × 27 = 54-row run.

```json
{
  "queries": ["minecraft", "best laptops 2024"],
  "sources": ["web", "youtube"],
  "deduplicateSuggestions": true,
  "suggestionLanguage": "English",
  "targetCountry": "United Kingdom",
  "alphabetPrefix": false,
  "alphabetSuffix": true,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

### ⬆️ Output

One dataset row per query — where "query" means one seed, or one A-Z expansion of a seed. Typed, normalized JSON with the same nine fixed key names on every run, plus the numbered suggestion columns. Rows are pushed as each query completes, so the dataset fills while the run is still going and a crash part-way through never loses what has already landed. Export as JSON, CSV or Excel, or read the dataset through the Apify API.

Charging is per saved row: one `row_result` event per row. **There are no uncharged rows and no error marker.** The row builder writes no `errorReason`, `status`, `isError`, `type` or equivalent field, so a query that was blocked on every retry is indistinguishable in shape from a query Google genuinely had no suggestions for — both arrive as a charged row with zero counts. Filter those with `rec["webCount"] == 0 and rec["youtubeCount"] == 0`, and read the run log if you need to know which of the two it was.

#### Example output

A row for the seed `how to lose weight`, both corpora selected, deduplication on:

```json
{
  "query": "how to lose weight",
  "suggestion_01": "how to lose weight fast",
  "suggestion_02": "how to lose weight in a week",
  "suggestion_03": "how to lose belly fat",
  "suggestion_04": "how to lose weight without exercise",
  "suggestion_05": "how to lose weight in 2 weeks",
  "suggestion_06": "how to lose water weight",
  "suggestion_07": "how to lose weight after 40",
  "suggestion_08": "how to lose weight with pcos",
  "sourcesQueried": ["web", "youtube"],
  "webSuggestions": [
    "how to lose weight fast",
    "how to lose weight in a week",
    "how to lose belly fat",
    "how to lose weight without exercise",
    "how to lose weight in 2 weeks",
    "how to lose water weight",
    "how to lose weight after 40",
    "how to lose weight with pcos"
  ],
  "webCount": 8,
  "youtubeSuggestions": [
    "how to lose weight fast at home",
    "how to lose weight walking",
    "how to lose weight naturally",
    "how to lose weight in 30 days workout",
    "how to lose weight yoga"
  ],
  "youtubeCount": 5,
  "youtube_suggestion_01": "how to lose weight fast at home",
  "youtube_suggestion_02": "how to lose weight walking",
  "youtube_suggestion_03": "how to lose weight naturally",
  "youtube_suggestion_04": "how to lose weight in 30 days workout",
  "youtube_suggestion_05": "how to lose weight yoga",
  "bothSourcesSuggestions": [
    "how to lose weight fast",
    "how to lose belly fat"
  ],
  "overlapCount": 2,
  "onBothSources": true
}
```

And the shape a query with no suggestions produces — still a charged row, with the numbered columns simply absent:

```json
{
  "query": "q how to lose weight",
  "sourcesQueried": ["web", "youtube"],
  "webSuggestions": [],
  "webCount": 0,
  "youtubeSuggestions": [],
  "youtubeCount": 0,
  "bothSourcesSuggestions": [],
  "overlapCount": 0,
  "onBothSources": false
}
```

### How does it work?

For each query the Actor builds one URL against Google's public suggest endpoint — `suggestqueries.google.com/complete/search` — with the query URL-encoded, `client=firefox`, and your language and country as `hl` and `gl`. The YouTube corpus is the **same endpoint with `&ds=yt` appended**: one integration, two datasets, not two separate services. When both corpora are selected the two requests for a query are issued concurrently, and the queries themselves run in sequence.

There is no headless browser, no JavaScript execution, no login and no cookie jar. Requests begin on a direct connection and escalate to an Apify datacenter and then a residential proxy only if the endpoint starts refusing them. The response is Google's own JSON array; the Actor reads the suggestion list out of it, normalises casing and whitespace for the cross-source comparison only — the strings themselves are returned exactly as Google sent them, unedited — and writes the row.

Only publicly visible data is collected, and the output key names stay the same whatever Google does to its search interface.

### Integrations

Google + YouTube Autocomplete Scraper is an Apify Actor, so it works with anything that can call the Apify API or consume a dataset.

#### Calling Google + YouTube Autocomplete Scraper from Python

The callable Actor id is your username plus the Actor's slug:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")

run = client.actor("<YOUR_USERNAME>/google-search-autocomplete-scraper-youtube-suggestions").call(run_input={
    "queries": ["minecraft", "best laptops 2024"],
    "sources": ["web", "youtube"],
    "deduplicateSuggestions": True,
    "targetCountry": "United Kingdom",
    "alphabetSuffix": True,
})

for rec in client.dataset(run["defaultDatasetId"]).iterate_items():
    if rec["webCount"] or rec["youtubeCount"]:
        print(rec["query"], rec["webCount"], rec["youtubeCount"], rec["bothSourcesSuggestions"])
```

Works in Go, Ruby, Node.js, cURL — any language that can make an HTTP request. Read `webSuggestions` and `youtubeSuggestions` rather than the numbered columns when you are working in code; the numbered keys exist for spreadsheet exports.

#### No-code tools (n8n, Make, Zapier)

In n8n, use the Apify node — or an HTTP Request node pointed at the Apify run endpoint with your token — and pass the same JSON input shown above; an Item Lists node splitting on `webSuggestions` turns one row into one item per suggestion, which is usually what you want before writing to a sheet. In Make, the Apify module supports run-and-wait, so a weekly seed-list refresh can feed a Google Sheets, Airtable or Slack step directly. Both platforms handle scheduling, which is how a fixed seed list becomes a rolling record of how suggestions change over time.

### Is it legal to scrape Google and YouTube autocomplete suggestions?

Scraping publicly accessible autocomplete suggestions is broadly treated as permissible where no authentication is bypassed, and this Actor calls a keyless public endpoint with no account, no cookie and no session.

The output is aggregate query strings — phrasings compiled from many users' searches, with no user identifier, no profile, no contact detail and no engagement metric in any field written. **GDPR and equivalent personal-data regimes do not attach to this output the way they would to a profile scraper**, because there is no data subject attached to a suggestion. The one nuance worth naming: a suggestion is free text, so a returned string can itself contain a person's name simply because that is what people search for — if you retain suggestion history in bulk, treat the suggestion fields as free text that may contain names rather than as guaranteed-anonymous labels.

What applies primarily is contractual: Google's and YouTube's terms of service covering automated access to their services, plus database and unfair-competition rules covering systematic reuse of a compiled dataset. Consult legal counsel if your use case involves republishing this data as a competing keyword dataset, or bulk retention where suggestion strings are matched back to individuals.

### ❓ Frequently asked questions

#### What fields does Google + YouTube Autocomplete Scraper return?

The five most used are `query`, `webSuggestions`, `youtubeSuggestions`, `bothSourcesSuggestions` and `onBothSources`. Every row also carries `sourcesQueried`, `webCount`, `youtubeCount` and `overlapCount`, plus one numbered column per suggestion in each list. See the data fields table above for all of them.

#### Does it require a Google or YouTube account, login or API key?

No. No Google account, no YouTube account, no login, no cookie, no OAuth token, no API key and no captcha-solver key. The suggest endpoint is keyless and public. The only credential involved is your Apify token, and by default requests go out with no proxy at all.

#### Are Google web and YouTube suggestions two separate sources?

They are two distinct suggestion corpora reached through **one endpoint**. Both requests go to `suggestqueries.google.com/complete/search` with the same `client=firefox` parameter; the YouTube corpus is selected by appending `&ds=yt`. It is a dataset switch on a single integration, not two separate services — but the two result sets genuinely differ, which is exactly what `bothSourcesSuggestions` and `overlapCount` measure on every row.

#### How many seed keywords can I expand in one run, and how many rows does that produce?

As many seeds as you like — `queries` is an array and every entry is processed in the same run. Rows follow `seeds × (1 + 26 if alphabetPrefix + 26 if alphabetSuffix)`: with both toggles off, one row per seed; with one on, 27; with both on, 53. Ten seeds with both toggles on is 530 rows. Request count is that row count multiplied by the number of selected `sources`. There is no cap in the code — the multipliers are the cost control, so decide on them before you start.

#### What happens if a seed returns zero suggestions?

You still get a row, and it is still charged. The row carries `webCount: 0`, `youtubeCount: 0`, `overlapCount: 0`, `onBothSources: false`, empty arrays, and no numbered suggestion keys at all — they are omitted rather than written as `null`. This Actor pushes no uncharged accounting rows and writes no error field, so an empty row means either "Google had nothing for that prefix" or "every retry was blocked", and the run log is what distinguishes them. In code, filter with `rec["webCount"] == 0 and rec["youtubeCount"] == 0`. Nonsense prefixes produced by A-Z expansion are the usual reason for empty rows in a large run, and they are normal.

#### Do the suggestions come with search volume, CPC or difficulty?

No, and no autocomplete source can provide them. The endpoint returns suggestion strings only; there is no `volume`, `cpc`, `competition` or `difficulty` key in this Actor's output because there is none in the response. Rank order reflects what Google offers first for that prefix, not how much traffic the phrase gets. Pair these suggestions with a keyword-volume product if you need numbers attached to them.

#### Do the language and country settings actually change the suggestions?

Yes — both are sent on every request. `suggestionLanguage` becomes the `hl` parameter and `targetCountry` becomes `gl`, mapped from the dropdown name to the code the endpoint expects. Two mappings are worth knowing if you compare output against another tool: Hebrew is sent as the legacy `iw`, and United Kingdom is sent as `uk`. Both dropdowns are closed lists in the Console; a value passed over the API that is not in the internal map falls back silently to `en` / `us` rather than raising an error, so check the values you send programmatically.

#### Does it work with Claude, ChatGPT and other AI agent tools, and is the output LLM-ready?

Yes to both. It is callable as a standard HTTP endpoint through the Apify API, so LangChain, CrewAI, n8n or a hand-written tool definition can invoke it and receive typed, normalized JSON with consistent field names across runs — no HTML parsing, no selectors, no cleanup pass. Pass a row straight into a context window, index it into a vector store, or hand it to an agent tool as a query-expansion step.

#### How does it compare to other Google autocomplete Actors on the Apify Store?

Checked on the Apify Store on 25 July 2026: `maged120/google-autocomplete-ppe` is the most used of the three and documents a single `queries` input taking objects with `query`, `language`, `country_code` and `cursor_pos`, output as one row per suggestion with `query`, `text`, `subtitle`, `thumbnail` and `url` — a richer per-suggestion shape, with a note that structure validation happens in the Actor rather than in the schema. `johnvc/google-autocomplete-api` documents `queries`, `gl` and `hl` inputs and a three-key output of `query`, `position` and `value`, one row per suggestion, and states pay-per-result pricing of $0.002 per suggestion returned; it also documents MCP registration and an n8n community node. `maged120/youtube-music-autocomplete` covers YouTube **Music** autocomplete only, with a `queries` input and a `query` + `suggestions` output.

Observable differences here: two corpora in one run with per-row overlap analysis, A-Z prefix and suffix expansion built in, closed 77-language and 69-country dropdowns instead of raw codes, and one row per query rather than one row per suggestion. Dual-source overlap, A-Z expansion and a `bothSourcesSuggestions` field are **not documented** on any of the three listings above. Against them, this Actor returns no per-suggestion metadata such as `subtitle`, `thumbnail` or a search `url`, and has no MCP registration documented — real trade-offs. These are field-list and input-flexibility differences you can verify yourself, not performance claims.

#### What happens when Google blocks a request or changes the endpoint, and do I need to manage proxies?

You never manage proxies — the ladder is automatic: direct connection, then Apify `GOOGLE_SERP` datacenter, then residential with three retries and a rising backoff, all decided by the Actor at runtime. You create no proxy account and rotate no IPs. Blocking is detected on status (403, 429, 503) *and* on body shape, so a soft block that arrives as a 200 is caught rather than parsed. If a query cannot be recovered, the run continues with the next one. As for endpoint changes, the Actor is maintained and the output key names stay put regardless; because it reads a JSON response rather than rendered HTML, a Google front-end redesign does not affect it at all.

#### Which fields work best for AI training data and RAG indexing?

For RAG indexing: `webSuggestions` and `youtubeSuggestions` are the high-information text fields, and they chunk best paired with their own `query` so a retrieved chunk carries the seed it belongs to instead of floating free. `bothSourcesSuggestions` is the field to index when you want cross-platform intent rather than platform-specific phrasing. For training or modelling: `webCount`, `youtubeCount`, `overlapCount` and `onBothSources` are the structurally consistent fields on every record, and `sourcesQueried` is the flag to check first so a single-source run is never read as a zero-overlap finding. All values return as typed primitives, arrays of strings or booleans — no normalization pass needed.

### 🔗 Related scrapers

| Scraper Name | What it extracts |
| ----- | ----- |
| Youtube Search Scraper | Video search results for any keyword or suggestion string |
| Youtube Video Details Scraper | Full metadata and stats for a specific video |
| Youtube Channel Finder | Channels matching a keyword, with channel-level detail |
| Ahrefs Scraper | Keyword ideas, difficulty, SERP overviews and domain metrics |
| MOZ Scraper | Domain and page authority metrics from a second SEO source |
| Google News Scraper by Publisher Site Filter | News coverage for a keyword, filtered to a publisher or domain |
| Quora Search Scraper | Question-intent results for keyword and content research |

### 💬 Your feedback

Found a bug, or need a language, country or corpus that is not covered? Open an issue on the Actor's Issues tab. Reports that include the exact input JSON and the `query` value from the row that looked wrong are the fastest to reproduce and fix — and if a seed is returning empty rows for a reason that is not obvious, that input plus the run log is usually enough to tell blocking apart from a genuinely empty suggestion set.

# Actor input Schema

## `queries` (type: `array`):

One seed phrase per line. Each seed is expanded into live autocomplete suggestions. Example: \["minecraft", "best laptops 2024"].

## `sources` (type: `array`):

Which autocomplete corpora to query per seed. 'web' = Google web search suggest; 'youtube' = YouTube search suggest (a genuinely different result set). Default: both.

## `deduplicateSuggestions` (type: `boolean`):

When on, the YouTube list drops any term already in the Google web list, so youtubeSuggestions holds only net-new video-search phrases (shared terms still reported in bothSourcesSuggestions). Turn off to keep the raw YouTube list. Default: on.

## `suggestionLanguage` (type: `string`):

Interface language (hl) for the suggestions. Default: English.

## `targetCountry` (type: `string`):

Geo (gl) the suggestions are localized for. Default: United States.

## `alphabetPrefix` (type: `boolean`):

Prepend each letter a-z before every seed (a minecraft, b minecraft…) to mine more long-tails. Multiplies request count by 26. Default: off.

## `alphabetSuffix` (type: `boolean`):

Append each letter a-z after every seed (minecraft a, minecraft b…) to mine more long-tails. Multiplies request count by 26. Default: off.

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

Optional proxy. The actor already falls back none → datacenter → residential automatically; set this only to force residential from the start.

## Actor input object example

```json
{
  "queries": [
    "how to lose weight",
    "best laptops 2024",
    "healthy breakfast ideas"
  ],
  "sources": [
    "web",
    "youtube"
  ],
  "deduplicateSuggestions": true,
  "suggestionLanguage": "English",
  "targetCountry": "United States",
  "alphabetPrefix": false,
  "alphabetSuffix": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "queries": [
        "how to lose weight",
        "best laptops 2024",
        "healthy breakfast ideas"
    ],
    "sources": [
        "web",
        "youtube"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scraper-engine/google-search-autocomplete-api").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 = {
    "queries": [
        "how to lose weight",
        "best laptops 2024",
        "healthy breakfast ideas",
    ],
    "sources": [
        "web",
        "youtube",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("scraper-engine/google-search-autocomplete-api").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "queries": [
    "how to lose weight",
    "best laptops 2024",
    "healthy breakfast ideas"
  ],
  "sources": [
    "web",
    "youtube"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call scraper-engine/google-search-autocomplete-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=scraper-engine/google-search-autocomplete-api",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/RAHGzaoI6SDNkQ44e/builds/QyZ6wTbZBzRbXOhT7/openapi.json
