# Search Autocomplete Scraper - Google, Bing, Pinterest, DDG (`scrapewise/search-autocomplete-scraper`) Actor

Keyword suggestions from Google, Bing, DuckDuckGo and Pinterest autocomplete in one run, with A-Z, 0-9 and question expansion, any language and country, engine count per suggestion, daily new-suggestion tracking and a name fixer. Error rows are free.

- **URL**: https://apify.com/scrapewise/search-autocomplete-scraper.md
- **Developed by:** [Scrapewise Data](https://apify.com/scrapewise) (community)
- **Categories:** SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.43 / 1,000 suggestion delivereds

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

## Search Autocomplete Scraper: Google, Bing, DuckDuckGo and Pinterest keyword suggestions

Get the **autocomplete suggestions of Google, Bing, DuckDuckGo and Pinterest in one run**, for any keyword,
language and country, **without an API key, an account or a browser**. Pinterest suggestions are what people type
into Pinterest search, the keywords that **Pinterest SEO** (pin titles, descriptions and boards) is built on. Expand each keyword with **A-Z**, **0-9**, **question
words** in the chosen language and your own words before or after it, and see **in how many engines** each
suggestion appears. Schedule it daily and get **only the suggestions that are new**: the earliest sign of a rising
search.

A second mode **fixes misspelled names**: give it `nubanc`, `disney plas` or `netflx` and it returns `nubank`,
`disney plus` and `netflix`, decided by a vote between the three engines. A name that the engines also suggest as
written is never "fixed".

### At a glance

- **Price per 1,000 suggestions, Free plan:** US$ 0.50 (down to US$ 0.425 on Gold and above)
- **Price per 1,000 names checked (canonicalize mode):** US$ 1.00
- **Fee per run start:** None
- **Engines in one run:** Google, Bing, DuckDuckGo, Pinterest (pick any)
- **Any language and country:** Yes (`language`, `country`)
- **A-Z, 0-9, question and custom word expansion:** Yes
- **Engine count per suggestion, optional merge across engines:** Yes
- **Only new suggestions since the last run (`onlyNew`):** Yes, free when nothing is new
- **Misspelled name to the right spelling, with the engines that agree:** Yes
- **Error rows (engine down, bad input, run timeout):** Free, with an `errorCode`; one engine failing never stops the others

### One real row

From a test run on 2026-10-06 (empty input, so the example keyword `iphone 17`, language `en`, country `us`):

```json
{
  "type": "suggestion",
  "keyword": "iphone 17",
  "suggestion": "iphone 17 pro max",
  "engine": "google",
  "position": 2,
  "seed": "iphone 17",
  "expansion": "base",
  "engines": ["google", "bing", "duckduckgo"],
  "engineCount": 3,
  "language": "en",
  "country": "us",
  "scrapedAt": "2026-10-06T21:44:41Z"
}
```

With `compareWithPreviousRun` or `onlyNew` every row also gets `"isNew": true | false` and `"firstSeenAt"`.

A row of canonicalize mode (input `nubanc`, same test day):

```json
{
  "type": "canonical",
  "input": "nubanc",
  "canonical": "nubank",
  "changed": true,
  "corrections": [{"from": "nubanc", "to": "nubank", "votes": 3, "responsesAgreeing": 3,
                   "engines": ["google", "bing", "duckduckgo"], "votesForOriginal": 0}],
  "sourcesAgreeing": 3,
  "enginesAgreeing": ["google", "bing", "duckduckgo"],
  "language": "en",
  "country": "us",
  "scrapedAt": "2026-10-06T21:44:45Z"
}
```

### What you can do with it

- **SEO and content:** hundreds of long-tail keywords and real questions per topic in seconds ("what ai agents are
  free", "how ai agents work"), for article ideas, FAQ sections and keyword clusters.
- **Trend spotting:** schedule your brand, product or category every morning with `onlyNew` and get only the
  suggestions that appeared since yesterday.
- **Marketplaces and e-commerce:** see what shoppers type after your product name, in each country and language,
  before you write titles and ads.
- **Brand monitoring:** watch what people attach to your brand ("... login", "... refund", "... vs ...") across
  three engines at once.
- **Pinterest marketing:** the searches people type into Pinterest for your niche, to title pins and boards
  with the words that get found.
- **Data cleaning:** a column of brand or product names written five different ways becomes one spelling, with how
  many engines agree, for CRM, survey and transcription cleanup.

### Input

| Field | What it does |
|---|---|
| `keywords` | Seed keywords, one per line (`iphone 17`, `ai agents`). In canonicalize mode, the misspelled names |
| `mode` | `suggestions` (default) or `canonicalize` |
| `engines` | Any of `google`, `bing`, `duckduckgo`, `pinterest` (when left out: the first three) |
| `language` | Two-letter code (`en`, `es`, `de`, `fr`, `it`, `ja`...), or a locale like `en-GB` |
| `country` | Two-letter code (`us`, `gb`, `de`, `in`, `au`...) |
| `expandAlphabet` | Also query `keyword a` ... `keyword z` |
| `expandNumbers` | Also query `keyword 0` ... `keyword 9` |
| `expandQuestions` | Also query the question words of the language before the keyword |
| `prefixes`, `suffixes` | Your own words before or after each keyword (`best`, `vs`, `near me`, `2026`) |
| `dedupeAcrossEngines` | One row per suggestion instead of one per engine and suggestion |
| `maxItems` | Max suggestion rows per keyword, 0 = no limit |
| `contextWords` | Canonicalize mode: topic words that help pick the right name (`bank`, `streaming`) |
| `compareWithPreviousRun` | Add `isNew` and `firstSeenAt` to every row |
| `onlyNew` | Deliver only suggestions not delivered before for the same keyword |
| `proxyConfiguration` | Default Apify Proxy (datacenter) |

Example: every question people ask about a topic, merged across engines:

```json
{
  "keywords": ["ai agents", "world cup 2026"],
  "expandQuestions": true,
  "expandAlphabet": true,
  "dedupeAcrossEngines": true
}
```

Example: daily new suggestions for a brand in the UK:

```json
{
  "keywords": ["taylor swift"],
  "language": "en",
  "country": "gb",
  "onlyNew": true
}
```

Example: fix a list of misspelled names:

```json
{
  "mode": "canonicalize",
  "keywords": ["nubanc", "disney plas", "netflx", "spotfy", "amazn prime"]
}
```

### Output fields

**Suggestion rows** (`type: "suggestion"`): `keyword` (your input), `suggestion`, `engine`, `position` (1 = top of
that engine's list), `seed` (the exact query typed, for example `how ai agents`), `expansion` (`base`, `alphabet`,
`number`, `question`, `prefix`, `suffix`), `engines` and `engineCount` (every engine that suggested it for this
keyword, through any expansion), `isNew` and `firstSeenAt` (with the comparison on), `language`, `country`,
`scrapedAt`.

Each engine's suggestion comes once per keyword, at the first query that returned it. When an engine just echoes
your own query back, that row is dropped and not charged.

**Canonical rows** (`type: "canonical"`): `input`, `canonical`, `changed`, `corrections` (each word changed, with
its votes and the votes the original word got), `sourcesAgreeing` and `enginesAgreeing` (engines that voted for the
new spelling, or that confirm the original when nothing changed).

**Error rows** (`type: "error"`, free): `errorCode` is one of `ENGINE_FAILED` (that engine did not answer any query
of the keyword; the other engines are still delivered), `ENGINE_PARTIAL`, `INVALID_INPUT`, `TIMEOUT_TOO_SHORT`,
`PARTIAL_TIMEOUT`, `NOT_REACHED` (the run timeout came before that keyword) and `UNEXPECTED`.

### Pinterest keyword suggestions

Add `pinterest` to `engines` to get the suggestions Pinterest shows while someone types in its search box: the
long-tail keywords for pin titles, pin descriptions, board names and Pinterest ads. Every expansion works the same
way (A-Z, 0-9, questions, your own words), and `engineCount` shows which Pinterest keywords are also searched on
Google and Bing.

```json
{
  "keywords": ["home decor", "wedding nails"],
  "engines": ["pinterest"],
  "expandAlphabet": true
}
```

- About 10 to 12 suggestions per query; with A-Z, about 250 to 300 Pinterest keywords per seed keyword.
- `language` sets Pinterest's locale: `de` returns German searches (`pizzateig rezept`), `pt` Portuguese
  (`pizza caseira`). In our tests Pinterest gave the same list for every country of one language, so `country`
  changes little there.
- Only search suggestions are returned. Profiles that Pinterest mixes into its suggestion box are left out.
- When the `engines` field is left out, the run reads Google, Bing and DuckDuckGo, so existing scheduled runs and
  API calls keep their rows and cost. The Console form starts with all four checked.

### How the name fixer decides

Each word of a name (3+ letters) is typed alone and together with its neighbour in the name and your context words.
Every engine answer is one vote: a word from the suggestions that sounds like yours (same letters after folding
accents, double letters, `ph`/`f`, `y`/`i`, `c`/`k`) gets a vote, worth double when it came with context. The answers
that contain **your own word** vote for keeping it. The new spelling wins only when it has more votes than the
original, so real names, plurals and suffixes (`AppFile` stays `AppFile`, not `Appfiles`) are left alone. Works for
names in Latin script.

### Daily monitoring

With `onlyNew` (or `compareWithPreviousRun`) the Actor keeps, per keyword, language, country and set of engines, the
suggestions it delivered, in a named key-value store in your account (`search-autocomplete-scraper-state`). The first
run is the baseline: everything is delivered and `isNew` stays empty. From the second run on, `isNew: true` marks
what was not there before. Suggestions not seen for 60 days are forgotten. Delete the store to start over.

Autocomplete changes a little between requests, so a handful of new rows on a quiet day is normal; a suggestion that
shows up in two or more engines (`engineCount`) is the stronger signal.

### Speed and cost

One keyword without expansion is 1 query per engine, about 25 to 40 rows across Google, Bing and DuckDuckGo,
plus about 11 from Pinterest. In a test on 2026-10-20, one keyword with A-Z in all four engines gave 1,252 rows in
5 seconds (Pinterest 272, Bing 527, Google 248, DuckDuckGo 205). With A-Z, 0-9 and
questions it is about 50 queries per engine and usually 500 to 1,500 rows (fewer with `dedupeAcrossEngines`). In our
tests 15 keywords with every expansion delivered about 10,000 suggestions in 22 seconds. Use `maxItems` to cap the
rows per keyword.

### Notes

- Google's suggestions also depend a bit on where the request comes from; `country` sets the engine parameters and
  the residential fallback runs from that country.
- Pinterest is asked at a gentler pace than the search engines, so it adds a few seconds per keyword.
- DuckDuckGo suggestions are often close to Bing's; the `engines` field shows where each one came from.
- The run stops a few seconds before its timeout and keeps everything already delivered; the keywords it did not
  reach get a free `NOT_REACHED` row.
- Only public autocomplete text is collected. No personal data.

### Changelog

- **2026-10-20:** Pinterest added as a fourth engine (`engines: ["pinterest"]`), with every expansion, engine count,
  merge and only-new tracking. Default engines when the field is left out stay Google, Bing and DuckDuckGo.
- **2026-10-06:** First version: Google, Bing and DuckDuckGo suggestions, A-Z, 0-9 and question expansion, name fixer.

# Actor input Schema

## `keywords` (type: `array`):

Seed keywords, one per line (for example iphone 17, ai agents, protein powder). Each keyword is typed into every engine chosen below and its suggestions come back as rows with the engine, position and the exact query typed. In Canonicalize mode, put the misspelled names here instead (for example nubanc, disney plas, netflx). Leave empty to run the example keyword. Also accepts 'names', 'queries', 'searchTerms' or 'keyword'.

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

Suggestions (default): every autocomplete suggestion for each keyword, charged per suggestion row. Canonicalize: each keyword is a name typed or transcribed wrong, and the Actor returns the right spelling decided by a vote between the engines (the original word wins when the engines also suggest it, so a real name is never 'fixed'), charged once per name.

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

Which autocomplete to read: Google, Bing, DuckDuckGo and Pinterest. When this field is left out (API calls), the run reads Google, Bing and DuckDuckGo; add Pinterest for the searches people type into Pinterest (Pinterest SEO, pin titles and boards). Only search suggestions are returned, never profiles. Each engine adds its own rows (or its vote in Canonicalize mode), so fewer engines means fewer rows and a lower cost. An engine that fails gets a free error row and the others are still delivered. Also accepts 'ddg' for DuckDuckGo.

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

Two-letter language code for the suggestions (default en; for example es, de, fr, it, pt, ja). A locale such as en-GB or pt-BR also sets the country. It also picks the question words used by 'Question expansion'. Also accepts 'hl'.

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

Two-letter country code (default us; for example gb, de, fr, es, in, au). Sets Google's gl, Bing's market, DuckDuckGo's region and Pinterest's locale, so suggestions match what people in that country type. Empty means the language's main country. Also accepts 'gl'.

## `expandAlphabet` (type: `boolean`):

Also types 'keyword a', 'keyword b' ... 'keyword z': 26 more queries per engine, usually 150 to 300 more suggestions per keyword in total. The classic long-tail keyword research method. Off by default; each extra suggestion is charged as a row, so set 'Max suggestions per keyword' to cap it.

## `expandNumbers` (type: `boolean`):

Also types 'keyword 0' ... 'keyword 9': 10 more queries per engine, which surface years, sizes, versions and model numbers (for example 'iphone 17 pro max'). Off by default.

## `expandQuestions` (type: `boolean`):

Also types the question words of the chosen language before the keyword (what, how, why, when, where, who, which, can, is, are, does, will in English; qué, cómo, por qué in Spanish; was, wie, warum in German...). Returns the questions people ask about the topic, useful for FAQ and content ideas. Off by default.

## `prefixes` (type: `array`):

Your own context words typed before each keyword, one per line (for example best, cheap, buy). Each word is one more query per engine and keyword. Leave empty for none.

## `suffixes` (type: `array`):

Your own context words typed after each keyword, one per line (for example vs, for, near me, review, 2026). Each word is one more query per engine and keyword. Leave empty for none.

## `dedupeAcrossEngines` (type: `boolean`):

Off (default): one row per engine and suggestion, so you see each engine's own position. On: one row per keyword and suggestion, and the engines field lists every engine that suggested it, which means fewer rows and a lower cost. Either way engineCount tells in how many engines the suggestion appeared, and each engine's suggestion comes only once per keyword even when several expansions return it.

## `maxItems` (type: `integer`):

Stop delivering suggestions for a keyword after this many rows (for example 100). 0 (default) means no limit: one keyword with every expansion and three engines gives roughly 500 to 1,500 rows. Suggestions past the limit are not charged. Also accepts 'maxSuggestionsPerKeyword'.

## `contextWords` (type: `array`):

Canonicalize mode only: topic words that help the engines guess the right name, one per line (for example bank, streaming, football). Each word is typed together with the name, and a vote with context counts double. Leave empty to vote on the name alone.

## `compareWithPreviousRun` (type: `boolean`):

For scheduled runs. Remembers every suggestion delivered for each keyword (with the same language, country and engines) in a named key-value store in your account ('search-autocomplete-scraper-state') and adds isNew and firstSeenAt to every row: isNew true means the suggestion was not there in earlier runs, a sign of a new trend. The first run of a keyword only saves the baseline (isNew empty). Suggestions not seen for 60 days are forgotten. Same price per row.

## `onlyNew` (type: `boolean`):

Delivers only suggestions that were not delivered in earlier runs of the same keyword, and turns on the comparison above by itself. The first run delivers everything as the baseline. Seen suggestions are skipped and not charged, so a quiet day costs nothing. Off by default.

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

The default Apify Proxy (datacenter) works for all four engines. A failing IP is dropped and another is tried; if an engine keeps failing on datacenter IPs, that engine moves to the residential group by itself when your account has it. Keep the default.

## Actor input object example

```json
{
  "keywords": [
    "iphone 17",
    "ai agents"
  ],
  "mode": "suggestions",
  "engines": [
    "google",
    "bing",
    "duckduckgo",
    "pinterest"
  ],
  "language": "en",
  "country": "us",
  "expandAlphabet": false,
  "expandNumbers": false,
  "expandQuestions": false,
  "dedupeAcrossEngines": false,
  "maxItems": 0,
  "compareWithPreviousRun": false,
  "onlyNew": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

## `resultsCsv` (type: `string`):

No description

# 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 = {
    "keywords": [
        "iphone 17",
        "ai agents"
    ],
    "engines": [
        "google",
        "bing",
        "duckduckgo",
        "pinterest"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapewise/search-autocomplete-scraper").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 = {
    "keywords": [
        "iphone 17",
        "ai agents",
    ],
    "engines": [
        "google",
        "bing",
        "duckduckgo",
        "pinterest",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("scrapewise/search-autocomplete-scraper").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 '{
  "keywords": [
    "iphone 17",
    "ai agents"
  ],
  "engines": [
    "google",
    "bing",
    "duckduckgo",
    "pinterest"
  ]
}' |
apify call scrapewise/search-autocomplete-scraper --silent --output-dataset

```

## MCP server setup

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

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/U2E0bsHKTCVczxtM5/builds/3Z7xjUiTEJa5wbJRN/openapi.json
