# Google Autocomplete Scraper & Rank Change Monitor (`automa-flow/google-autocomplete-rank-change-monitor`) Actor

Scrape Google autocomplete suggestions by country, language and vertical. Monitor new, lost and rank-changed phrases across Web, YouTube, Shopping and News with persistent baselines and configurable confirmation. Export typed changes and per-prefix status.

- **URL**: https://apify.com/automa-flow/google-autocomplete-rank-change-monitor.md
- **Developed by:** [Vadim Bezrukov](https://apify.com/automa-flow) (community)
- **Categories:** SEO tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 verified prefix checks

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## 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 & Rank Change Monitor

Track the Google search suggestions shown for your brand, competitors and topic
prefixes. Get typed alerts when a suggestion appears, disappears or changes rank,
with a saved baseline and configurable confirmation across consecutive checks.

Monitor Web, YouTube, Shopping and News suggestions by country and language.
Useful for SEO topic research, brand monitoring, ecommerce keyword discovery and
recurring n8n, Make or API workflows. This is autocomplete position monitoring;
it does not measure website rankings in search results or keyword search volume.

**$0.002 per verified prefix check, including platform usage.** No start fee,
Google login, source API key or proxy subscription is required. An Apify account
is required to run the Actor. The three-prefix example costs $0.006.

The first run returns confirmed suggestions and saves a baseline. Later runs
return typed changes and compact status rows for unchanged, duplicate or
unsuccessful entries. Use the `changes` Dataset view for the alert feed.

### One content brief, then confirmed changes

The default three prefixes now address the same job: air-fryer content questions in US English on Google Web. Replace them together for your topic. Keep country, language, vertical and `monitorKey` stable for comparable observations.

| Run with `confirmationChecks: 2` | What it means |
| --- | --- |
| First run | Takes two successful samples per prefix to establish the confirmed baseline; returns suggestions with `emitSnapshot` |
| First later appearance or disappearance | Candidate change awaits confirmation; it is not yet a new/lost alert |
| Next successful confirming run | Emits the confirmed addition/removal when the same condition persists |
| Failed check | Retains the previous good state; it is not an empty suggestion list |

Rank moves follow `minRankDelta`; confirmation mainly governs suggestion presence/absence. The SEO research Task uses `confirmationChecks: 1` for an immediate snapshot; use 2 for a recurring alert watchlist.

To validate an idea, pick a few relevant suggestions yourself and submit them to [Google Trends](https://apify.com/automa-flow/google-trends-monitor). Match country and search property, and compare keywords together when you need a common scale. Autocomplete position/relevance is not search volume; there is no automatic keyword expansion or extra Trends run.

### 30-second quickstart

Use the saved [SEO content-planning example](https://apify.com/automa-flow/google-autocomplete-rank-change-monitor/examples/find-seo-content-questions-google-autocomplete)
as a starting point, replacing its sample question prefixes. Check **Current
suggestions** after the first run; an empty Changes view on a new baseline is
expected. A three-prefix daily watchlist costs $0.18 over 30 successful days at
the current $0.002/check rate, including platform usage.

```json
{
  "targets": [
    { "query": "how to use air fryer", "externalId": "how-to", "country": "us", "language": "en", "vertical": "web" },
    { "query": "can air fryer", "externalId": "can-it", "country": "us", "language": "en", "vertical": "web" },
    { "query": "why air fryer", "externalId": "why-it", "country": "us", "language": "en", "vertical": "web" }
  ],
  "monitorKey": "example-autocomplete-content-questions",
  "mode": "snapshotAndChanges",
  "baselineMode": "emitSnapshot",
  "confirmationChecks": 1
}
```

Run once and export **Current suggestions**. Group the phrases into how-to,
capability and troubleshooting questions, discard irrelevant suggestions, then
select a small set for a content brief. Validate demand with a jointly normalized
Google Trends comparison before prioritizing articles. This is a research input,
not an automatically generated content plan.

The example uses one source sample for immediate research. For recurring alerts,
set `confirmationChecks: 2` and keep that setting and `monitorKey` stable. Review
confirmed changes on later runs; country, language, vertical, source filtering
and observation time affect coverage. This does not reproduce every personalized
Google UI list, expand the alphabet, or guarantee an exhaustive keyword universe.

For n8n or Google Sheets, run the saved Task, wait for completion and retrieve its
default Dataset. Keep `external_id`, query, country, language, vertical and the
observation timestamp alongside each suggestion. Route confirmed change records
to editorial review; retain failed checks without treating them as lost phrases.
Scheduling and writing to Sheets are configured in your integration.

A target is a plain string or an object. Defaults are `country: "us"`,
`language: "en"`, `vertical: "web"`.

### Choose a workflow

| Workflow | Starting prefixes / scope | Result and repeat use |
| --- | --- | --- |
| Compare countries | `insurance` in US, UK (`gb`) and India; English Web | Current lists for side-by-side review. One sample per check; keep the same prefix to compare markets. |
| Plan SEO content | `how to use air fryer`, `can air fryer`, `why air fryer`; US Web | Current question suggestions for editorial review, with changes on later checks. This does not generate answers or expand every keyword. |
| Monitor brand comparisons | `notion vs`, `notion alternatives`; US Web | First-run baseline, then confirmed new/lost phrases and rank changes. The Changes view is empty until an actual change is confirmed. |
| Plan fitness videos | `home workout`, `running shoes`, `yoga for beginners`; US YouTube | Confirmed suggestion lists and changes for a recurring video-topic review. |
| Research German Shopping terms | `beste laufschuhe`, `wanderschuhe`, `kaffeemaschine`; Germany, German Shopping | Confirmed product-query suggestions and changes for German shops; no product prices or search volumes. |

Replace the sample prefixes and use a separate `monitorKey` for each watchlist.
Keep that key stable between checks. With `confirmationChecks: 2`, a new or lost
phrase needs two consecutive successful checks; a daily watch can therefore
take another daily run to confirm it. First-run lists are in **Current suggestions**.
Use `snapshotAndChanges` if you need the list again on every successful run,
or `changesOnly` for a compact recurring feed. Monitor Tasks do not create schedules
or send notifications automatically.

The prepared Task examples use 2–3 scopes ($0.004–$0.006 per successful run) and
a $0.02 run cap, allowing up to ten distinct checked scopes at the current price.
If you add more targets, increase the cap deliberately or expect uncharged
`SKIPPED` rows. A single checked prefix can produce multiple Dataset rows.

The following output examples are illustrative excerpts, not live market findings.

#### Sample `NEW_SUGGESTION`

```json
{
  "record_type": "CHANGE",
  "status": "SUCCESS",
  "change_type": "NEW_SUGGESTION",
  "query": "notion vs",
  "external_id": "notion-competitors",
  "country": "us",
  "vertical": "web",
  "suggestion": "notion vs obsidian 2026",
  "position": 3,
  "previous_position": null,
  "relevance": 600,
  "observed_at": "2026-09-11T06:00:00Z"
}
```

#### Sample `LOST_SUGGESTION`

```json
{
  "record_type": "CHANGE",
  "status": "SUCCESS",
  "change_type": "LOST_SUGGESTION",
  "query": "notion vs",
  "suggestion": "notion vs goodnotes",
  "position": null,
  "previous_position": 10,
  "previous_relevance": 554,
  "observed_at": "2026-09-11T06:00:00Z"
}
```

#### Sample `RANK_CHANGED`

```json
{
  "record_type": "CHANGE",
  "status": "SUCCESS",
  "change_type": "RANK_CHANGED",
  "query": "notion vs",
  "suggestion": "notion vs google docs",
  "previous_position": 6,
  "position": 1,
  "delta": -5,
  "previous_relevance": 602,
  "relevance": 602,
  "observed_at": "2026-09-11T06:00:00Z"
}
```

`delta` is negative when a suggestion moves up. It is measured among the
suggestions confirmed in both checks, so a volatile neighbour arriving or
leaving does not count as a move. That is why it can differ from
`position - previous_position`.

Complete examples, including a baseline run and a run summary, are in
`examples/`.

### What it detects

| Change | Meaning |
| --- | --- |
| `NEW_SUGGESTION` | A phrase has become consistently present. |
| `LOST_SUGGESTION` | A previously confirmed phrase has become consistently absent. |
| `RANK_CHANGED` | A phrase moved among suggestions confirmed in both checks. |
| `METADATA_CHANGED` | The suggestion type changed, such as QUERY to NAVIGATION. |

With the default `confirmationChecks: 2`, a new or lost phrase must be observed
on two consecutive successful checks. The baseline takes two samples in its
first run; later runs normally take one per prefix. This delays an alert until
the second confirming run. Set `confirmationChecks: 1` for immediate changes.

Google rotates suggestions between identical requests. In one local capture of
12 prefixes sampled 12 times within about a minute, confirmation plus comparison
among confirmed suggestions produced **92% fewer change events** than a naive
diff. This is a reduction in observed short-interval churn on that sample, not a
measured accuracy rate or a guarantee that real changes will all be preserved.
The first comparison after a baseline can still be noisier than later checks.

`minRelevance: 0` includes all suggestions. Raising it excludes lower-scoring
phrases and can remove useful long-tail terms. Google's relevance is an ordering
score, not search volume. Score changes alone never generate an alert.

### Countries, languages and verticals

```json
{
  "targets": [
    { "query": "insurance", "country": "us" },
    { "query": "insurance", "country": "gb" },
    { "query": "insurance", "country": "in" },
    { "query": "beste laufschuhe", "country": "de", "language": "de" },
    { "query": "running shoes", "vertical": "youtube" },
    { "query": "running shoes", "vertical": "shopping" }
  ]
}
```

The same prefix in a different country, language or vertical is a **different
target**: monitored separately, compared separately, charged separately.
`country` and `language` are validated against ISO 3166-1 alpha-2 and ISO 639-1,
because Google accepts an invalid code silently and answers with global
suggestions - `country: "uk"` would otherwise be monitored for the wrong market
indefinitely.

One local comparison of 11 prefixes found the following mean overlap with Web.
These sample observations are not guarantees for your market:

| Vertical | Overlap with Web | Use it for |
| --- | --- | --- |
| `web` | - | the default search dropdown |
| `youtube` | 14% | video demand language; strongly distinct |
| `shopping` | 18% | product and commercial modifiers; strongly distinct |
| `news` | 81% | mostly mirrors Web; distinct for some prefixes only |

Google Images is not supported. Its endpoint behavior was not independently
verified during source investigation.

Note that `language` is a weak signal at the source: `country` does most of the
work, and Google frequently ignores a language that does not match the prefix.

### Scheduling and webhooks

1. Save your watchlist as a task.
2. Schedule it daily or weekly (Apify Console, **Schedules**).
3. Add a webhook on **Run succeeded** pointing at your endpoint, Slack relay or
   n8n/Make/Zapier scenario.

For a daily check at 06:00 UTC, use `0 6 * * *`. The source repository includes
`examples/schedule.json` and `examples/webhook.json`, matching the
[schedule](https://docs.apify.com/api/v2/schedules-post) and
[webhook](https://docs.apify.com/api/v2/webhooks-post) APIs. These are templates;
running the Actor does not create a schedule or send notifications by itself.

Example schedule body for one prefix ($0.002 maximum per scheduled run):

```json
{
  "name": "autocomplete-brand-watch-daily",
  "isEnabled": true,
  "isExclusive": true,
  "cronExpression": "0 6 * * *",
  "timezone": "UTC",
  "actions": [{
    "type": "RUN_ACTOR",
    "actorId": "07uQmK4SMPp5OCXjH",
    "runInput": {
      "body": "{\"targets\":[{\"query\":\"notion vs\"}],\"monitorKey\":\"brand-watch-daily\"}",
      "contentType": "application/json; charset=utf-8"
    },
    "runOptions": {"memoryMbytes": 256, "timeoutSecs": 600, "maxTotalChargeUsd": 0.002}
  }]
}
```

Example webhook body, after replacing the URL with an endpoint you control:

```json
{
  "eventTypes": ["ACTOR.RUN.SUCCEEDED", "ACTOR.RUN.FAILED", "ACTOR.RUN.TIMED_OUT", "ACTOR.RUN.ABORTED"],
  "condition": {"actorId": "07uQmK4SMPp5OCXjH"},
  "requestUrl": "https://YOUR-OWN-ENDPOINT.example/apify/autocomplete"
}
```

The webhook carries run metadata, not individual change rows. Its receiver should
read `RUN_SUMMARY`, then fetch that run's Dataset with
`view=changes&clean=true` to exclude empty baseline/status projections. Notify only
for relevant changes or operational failures; a succeeded run may contain
invalid or failed inputs.

Every change row is usable as an alert payload as it stands: it carries the
prefix, your `external_id`, the suggestion, both positions, and a `source_url`
that a human can open to verify the claim.

Start with daily checks. More frequent checks can make short-lived rotation
more prominent in your alert feed.

Run only one job at a time for each `monitorKey`. Its state is one KVS record;
overlapping jobs can overwrite each other's comparisons. Wait for the previous
run to finish before starting another run with the same key.

Changing `confirmationChecks` or `minRelevance` starts a fresh confirmed baseline
for the affected targets. The old baseline remains intact until the new check
succeeds and is delivered. State saved before these settings were recorded also
re-baselines once. A relevance drop below the floor silently excludes the phrase;
it does not emit `LOST_SUGGESTION` while Google still returns it.

### Pricing

One event: **$0.002 per prefix checked**, where a prefix means one exact scope -
query plus country, language and vertical.

| Watchlist | Per run | Daily for a month |
| --- | --- | --- |
| 20 prefixes | $0.04 | ~$1.20 |
| 100 prefixes | $0.20 | ~$6 |
| 500 prefixes | $1.00 | ~$30 |

Predictable from the watchlist alone. It does not matter whether a prefix
returns 15 suggestions or none, whether it changed or not, or how many changes
it produced. **Never charged:** retries, failed checks, responses that could not
be trusted, prefixes held back by your charge limit, rejected entries, and the
same scope listed twice.

Platform compute, storage operations and source requests during the run are
included in the event price. Baselines, unchanged checks and valid empty results
are each one verified check; confirmation samples are not extra paid events.
There are no plan-tier discounts at launch. The minimum allowed run charge cap
is $0.002; it is a spending ceiling, not a minimum fee.

Set **Maximum cost per run** explicitly. One, 20, 100 and 500 unique scopes have
maximum event bills of $0.002, $0.04, $0.20 and $1.00. The default API cap is $1;
use $0.006 for the three-prefix example. A lower cap preserves completed output
and emits `SKIPPED` for entries it cannot deliver. The summary reconciles charges
with delivered checks. Failed runs can contain earlier completed, paid checks.

Cloud measurements on 2026-09-09 at 256 MB: the default three-prefix baseline
took 3.4 seconds; 100-prefix baseline and repeat checks took 16.1 and 9.7 seconds.
These are single-run observations, including platform startup, not latency SLAs.

### Failure semantics

**A check that failed is never reported as a suggestion that disappeared.** That
is the guarantee this Actor is built around.

Charging, Dataset delivery and state saving are separate operations. An
interruption during delivery can leave completed, paid rows without a saved
comparison state. Resurrection fails closed instead of repeating side effects;
a fresh run may report the same changes again if state was not saved. Inspect
the Dataset and `RUN_SUMMARY` when available after a failed run.

| `status` | Meaning |
| --- | --- |
| `SUCCESS` | Google answered with suggestions |
| `NO_RESULTS` | Google answered, validly, with none. A real observation, not a failure |
| `FAILED` | the answer could not be trusted. Nothing was reported as lost, the stored baseline is untouched, and you were not charged |
| `INVALID_INPUT` | the entry was rejected before any request was made |
| `SKIPPED` | the budget prevented delivery, either before checking or when the platform declined the charge; the error explains which |

Treated as **failure**, never as an empty result: rate limits and server errors
after the retry budget, timeouts, an HTTP 200 carrying an HTML challenge or
consent page, invalid JSON, an unexpected response shape, and a metadata array
that does not line up with the suggestion list.

There is deliberately no `PARTIAL`. One check of one prefix either produces a
trustworthy observation or it does not.

**Mass-outage protection.** Among at least ten checked prefixes with previously
confirmed suggestions, if at least half now return none, that is treated as a
suspected source event: the empty prefixes keep their previous state, are reported
as `FAILED`, and are not charged. A Google outage cannot generate a wave of false
"lost" alerts.

One prefix failing does not stop the remaining checks. If every attempted target
fails verification, the Apify run fails after writing diagnostic rows and
`RUN_SUMMARY`. Mixed successful and failed targets retain their individual
outcomes. An all-invalid batch fails without source requests or charges.

Each submitted entry has at least one row, joined by zero-based `input_index`.
Duplicate scopes share one check and one charge. Their status rows preserve each
entry's `external_id` and identify the first occurrence through `duplicate_of`.
In `changesOnly`, an unchanged verified target receives `TARGET_STATUS` with
`SUCCESS` or `NO_RESULTS`; `baselineMode: "storeOnly"` likewise returns status
without the suggestion list. Filter `record_type: "CHANGE"` for alerts.

`status` describes the latest source sample. `suggestion_count` describes the
confirmed set: a first empty sample can be `NO_RESULTS` while old suggestions
remain pending confirmation. A positive relevance floor requires a valid score
for every returned suggestion; missing scores produce `FAILED`, never losses.

### How this differs from Google Trends

They measure different things and complement each other.

**Google Trends** - interest over time, regional interest, related and rising
queries, breakout signals. *Is this topic growing?*

**Google Autocomplete Scraper & Rank Change Monitor** - what Google suggests right now
for an exact prefix, which suggestions are in the list, where they sit, and how
that changes across scheduled checks. *What language is Google putting in front
of people who start typing this?*

For interest curves, use a Google Trends Actor.

### Limitations

- **The endpoint is undocumented.** It is a public, unauthenticated,
  browser-facing endpoint, not a supported Google API. It can change shape or
  disappear without notice. When it does, the Actor reports failures and
  preserves your state rather than inventing changes.
- **Suggestion membership can be unstable at the tail.** The confirmation
  model manages this; it does not abolish it. Expect the head of the list to be
  solid and the last few slots to move.
- **Relevance is not search volume, and relevance moves are not reported as
  changes.** `relevance` is Google's own ordering score. Measured, it is largely
  derived from position - the tail is a literal `550 + k` counter - and where it
  does move independently, the movement is not separable from noise: across
  short-interval samples, 1.9% of suggestions that held their exact
  position still had their score move, by as much as 150 points. This does not establish a dependable demand signal, so score changes do not
  generate a `RELEVANCE_CHANGED` event. Do not
  read relevance as demand, and do not read a rank move as a revenue forecast.
- **`suggest_subtypes` are undocumented opaque integers.** Passed through as
  returned; never used for change detection.
- **Query prefixes are capped at 100 characters**, because Google answers 101
  with HTTP 400.
- **Anonymous suggestions.** No Google account, no cookies, no session.
  No cookies are sent, including cookies set by earlier responses. You get
  anonymous endpoint suggestions; they can still vary with Google's server
  selection, IP location and other source behavior.
- **Maximum 500 prefixes per run.**

### API and MCP

Save the quickstart JSON as `input.json`. The following Bash example starts a
run with a $0.006 cap. Supply your Apify token through your secret manager or
environment; keep it out of shared commands, URLs and source control.

```bash
curl --request POST \
  --header "Authorization: Bearer $APIFY_TOKEN" \
  --header "Content-Type: application/json" \
  --data-binary @input.json \
  'https://api.apify.com/v2/acts/automa-flow~google-autocomplete-rank-change-monitor/runs?maxTotalChargeUsd=0.006&memory=256&timeout=600'
```

Poll `GET /v2/actor-runs/{runId}`. When it finishes, use its
`defaultKeyValueStoreId` to read `GET /v2/key-value-stores/{storeId}/records/RUN_SUMMARY`,
and its `defaultDatasetId` to read `GET /v2/datasets/{datasetId}/items`.
Keep the Authorization header on each request. Prefer these run-specific IDs
over the last-run endpoint when you have several watchlists.

The default Dataset view shows current suggestions and per-entry outcomes.
Additional views are `changes`, `current` and `status`. Add `?view=changes&clean=true`
for the alert feed. The `changes` view projects and unwraps the optional `change`
object; keep `clean=true` to omit empty projected rows. Raw Dataset records keep
their flat fields, so `record_type == "CHANGE"` is the equivalent client-side filter.
The other views select columns; inspect `record_type` and
`status` to distinguish snapshots, successful checks, failures and skipped work.
`RUN_SUMMARY.operational` reports batch health; a succeeded platform run may
still contain invalid or failed entries.

The authenticated hosted MCP tool exposes this Actor's inputs and structured
run output at:

```
https://mcp.apify.com?tools=automa-flow/google-autocomplete-rank-change-monitor
```

Example agent request: "Check my brand prefixes under monitorKey brand-watch.
Read RUN\_SUMMARY and report failed or skipped checks separately. Return only
NEW\_SUGGESTION and LOST\_SUGGESTION rows as alerts."

The direct MCP tool currently exposes `waitSecs` but not a per-call
`maxTotalChargeUsd` option. For a strict per-call spending ceiling, use the Apify
run API above. API execution and an authenticated hosted MCP execution were verified;
public MCP search visibility must be checked after Store publication.
Execution requires the customer's OAuth session or Apify token. See the
[Apify MCP documentation](https://docs.apify.com/integrations/mcp).

`source_id` aliases the stable `target_key`, and `scraped_at` aliases the UTC
`observed_at` batch timestamp. Keep `schema_version` and `fingerprint` when
exporting rows so observations can be joined to earlier runs.

***

**Independent community Actor. Not affiliated with, sponsored by, or endorsed by
Google.** "Google" and "YouTube" are trademarks of Google LLC, used here only to
describe what this Actor reads.

### Technical source details

- **Endpoint:** `https://www.google.com/complete/search` with `client=chrome`,
  over HTTPS. No browser, no Playwright, no proxy, no CAPTCHA solving, no
  session bootstrap.
- **Machine-readable instructions.** `https://www.google.com/robots.txt` was
  checked on 2026-09-09 by expanding every rule in the `User-agent: *` group.
  The recorded source investigation found no rule matching `/complete/search`.
  Google's [Terms of Service](https://policies.google.com/terms) also cover
  protective measures, privacy and intellectual property. Absence of a matching
  [robots.txt](https://www.google.com/robots.txt) rule is not a commercial reuse
  license. Source risk is **MODERATE**: public, unauthenticated access with no
  supported API or explicit commercial automation license. Use only for lawful
  monitoring, respect source restrictions, and review the terms before
  redistributing collected suggestions. The Actor does not bypass blocks.
- **Request volume.** One request per prefix per run, plus one extra per prefix
  on a default first run to fill the confirmation window (up to three samples
  with `confirmationChecks: 3`). At most four requests in
  flight. Retries are bounded; the Actor does not bypass access restrictions.
- **State.** The Apify key-value store only, one compact record per
  `monitorKey`, holding the last confirmed suggestion set per prefix. No
  database. If that record cannot be written, the run fails rather than claiming
  a baseline was saved.
- **Data collected.** Public autocomplete suggestions and the prefixes you
  supply. These can contain personal names or other personal information; avoid
  supplying sensitive personal queries. No account data, credentials or cookie
  values are exported. Your prefixes and `monitorKey` are kept out of run logs.
  Run datasets and the comparison baseline remain in your Apify storage until
  you delete them or apply your account's retention policy.

# Actor input Schema

## `targets` (type: `array`):

One entry per prefix. A plain string is the query; an object may also set country, language, vertical and your own externalId. A target's identity is query + country + language + vertical, so the same prefix in two countries is two targets and is charged twice, while the same scope listed twice is checked, charged and compared once.

## `monitorKey` (type: `string`):

Names the stored baseline this run compares against. Use one key per watchlist (for example seo-brand-watch). Changing it starts a fresh baseline.

## `mode` (type: `string`):

changesOnly returns the first-run baseline and later typed changes. Entries without another output row receive TARGET\_STATUS, including unchanged checks, duplicates and unsuccessful inputs. snapshotAndChanges also returns the confirmed suggestion list for every verified target. Use the changes Dataset view for an alert feed without status rows.

## `baselineMode` (type: `string`):

emitSnapshot returns every target's confirmed suggestions on the first run. storeOnly saves the baseline and returns a compact status without suggestions. Neither baseline mode emits a change alert.

## `confirmationChecks` (type: `integer`):

Consecutive successful samples required to confirm presence or absence. The first run takes this many samples per prefix; later runs normally take one. Default 2 reduces short-lived rotation but delays alerts until the second confirming run. Set 1 for immediate differences. Confirmation samples do not add paid events.

## `minRankDelta` (type: `integer`):

Ignore moves smaller than this many positions among suggestions confirmed in both checks. This reduces shifts caused solely by a volatile neighbour entering or leaving. Default 2; set 1 for single-position moves.

## `minRelevance` (type: `integer`):

Exclude suggestions below this Google relevance score. Default 0 includes all suggestions. Higher floors can remove useful long-tail phrases. Below-floor phrases still present in Google's response are excluded without a LOST\_SUGGESTION event. Relevance is an ordering score, not search volume. Missing scores under a positive floor fail the check.

## `includeMetadata` (type: `boolean`):

Attaches Google's suggestion type (QUERY or NAVIGATION) and its undocumented subtype codes to each row. Relevance and position are always included. Turning this off does not change what is monitored.

## Actor input object example

```json
{
  "targets": [
    "best crm software",
    {
      "query": "beste laufschuhe",
      "country": "de",
      "language": "de"
    }
  ],
  "monitorKey": "air-fryer-content-watch",
  "mode": "changesOnly",
  "baselineMode": "emitSnapshot",
  "confirmationChecks": 2,
  "minRankDelta": 2,
  "minRelevance": 0,
  "includeMetadata": true
}
```

# Actor output Schema

## `current` (type: `string`):

Columns for confirmed suggestion lists. Lists appear on BASELINE and SNAPSHOT rows; other row types can appear without a list.

## `changes` (type: `string`):

New, lost, re-ranked and re-typed suggestions. For direct API exports add clean=true to omit empty projected baseline/status rows; Console already requests clean rows.

## `status` (type: `string`):

Failure-focused columns for all rows; filter the status field client-side.

## `runSummary` (type: `string`):

Target outcomes, change tallies, source requests and retries, noise-control settings and billing.

# 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 = {
    "targets": [
        {
            "query": "how to use air fryer",
            "externalId": "air-fryer-how",
            "country": "us",
            "language": "en",
            "vertical": "web"
        },
        {
            "query": "can air fryer",
            "externalId": "air-fryer-can",
            "country": "us",
            "language": "en",
            "vertical": "web"
        },
        {
            "query": "why air fryer",
            "externalId": "air-fryer-why",
            "country": "us",
            "language": "en",
            "vertical": "web"
        }
    ],
    "monitorKey": "air-fryer-content-watch",
    "mode": "changesOnly"
};

// Run the Actor and wait for it to finish
const run = await client.actor("automa-flow/google-autocomplete-rank-change-monitor").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 = {
    "targets": [
        {
            "query": "how to use air fryer",
            "externalId": "air-fryer-how",
            "country": "us",
            "language": "en",
            "vertical": "web",
        },
        {
            "query": "can air fryer",
            "externalId": "air-fryer-can",
            "country": "us",
            "language": "en",
            "vertical": "web",
        },
        {
            "query": "why air fryer",
            "externalId": "air-fryer-why",
            "country": "us",
            "language": "en",
            "vertical": "web",
        },
    ],
    "monitorKey": "air-fryer-content-watch",
    "mode": "changesOnly",
}

# Run the Actor and wait for it to finish
run = client.actor("automa-flow/google-autocomplete-rank-change-monitor").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 '{
  "targets": [
    {
      "query": "how to use air fryer",
      "externalId": "air-fryer-how",
      "country": "us",
      "language": "en",
      "vertical": "web"
    },
    {
      "query": "can air fryer",
      "externalId": "air-fryer-can",
      "country": "us",
      "language": "en",
      "vertical": "web"
    },
    {
      "query": "why air fryer",
      "externalId": "air-fryer-why",
      "country": "us",
      "language": "en",
      "vertical": "web"
    }
  ],
  "monitorKey": "air-fryer-content-watch",
  "mode": "changesOnly"
}' |
apify call automa-flow/google-autocomplete-rank-change-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automa-flow/google-autocomplete-rank-change-monitor"
        }
    }
}
```

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/07uQmK4SMPp5OCXjH/builds/P1VQQ2TRgyZRKpvWD/openapi.json
