# Etsy Keyword Research Tool — Bulk Autocomplete & Long-Tail (`astravalabs/etsy-keyword-research-tool`) Actor

Bulk Etsy keyword research from search autocomplete. Expand seeds into
long-tail keywords with ranks and ready-to-open search URLs. No per-run fee.

- **URL**: https://apify.com/astravalabs/etsy-keyword-research-tool.md
- **Developed by:** [Astrava Labs](https://apify.com/astravalabs) (community)
- **Categories:** E-commerce, SEO tools, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.65 / 1,000 etsy keyword suggestions

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Etsy Keyword Research Tool

Get the exact autocomplete suggestions Etsy's own search box shows shoppers — the same dropdown you see typing into etsy.com/search, pulled programmatically for as many seed terms as you want, in a single run.

No proxy setup required. No captcha-solving service needed. Proxies are bundled — just provide seed keywords and run.

**Pricing: $2.65 per 1,000 suggestions. No per-run start fee, no compute charges.** You pay for saved suggestions and nothing else. Duplicates are dropped before they reach your dataset, so you never pay for the same keyword twice.

### Quick start

```json
{
  "keywords": ["candle", "mug", "gift"]
}
````

Three seeds, each expanded across the alphabet — roughly 350–380 suggestions per seed, in seconds.

### Why this one

**Batch your seeds.** Pass an array of keywords and get them all in one run. Most Etsy keyword actors take a single keyword per run, which means a separate run — and a separate start fee — for every term you want to research.

**No start fee.** Runs that charge a flat fee before returning anything punish exactly the workflow keyword research demands: many small, exploratory runs. We charge per saved suggestion, full stop.

**Long-tail expansion on by default.** Each seed is also queried followed by every letter (`gift a`, `gift b`, …) and the dropdowns are merged. It's the trick power users do by hand, and it turns `gift` from 14 suggestions into 372. Set `expandPrefixes: false` if you only want the seed's own dropdown.

**Specific seeds expand too.** `handmade candle` yields 238 suggestions, `custom dog painting` yields 271 — 14–27× the base dropdown, whether your seed is one word or four. Many autocomplete scrapers return nothing at all for a multi-word prefix; this one matches what Etsy's own search box shows a shopper mid-type.

**Spend caps that actually bind, on by default.** `maxTotalResults` defaults to 2000 suggestions, so a run can never surprise you no matter how many seeds you paste in. `maxSuggestionsPerSeed` bounds each seed instead. Rows beyond a cap are never saved and never billed — you know your ceiling before you start.

**Every language, no configuration.** Etsy's autocomplete completes the phrase you type, against a global index. Seed it with `kerze` and you get `kerzenständer gold`, `kerzenhalter wand`; seed it with `cadeau` and you get `cadeau nounou`, `cadeau personnalisé`. Nothing to configure — the language of your seed is the language of your results.

### What you get on every row

**`keyword`** — the seed term you provided.

**`suggestion`** — the exact autocomplete string Etsy's search box would show.

**`rank`** — 1-indexed emission order within the seed. A stable sort key, not a score.

**`source_rank`** — 1-indexed position within its own dropdown, i.e. Etsy's ordering. `candle art` is Etsy's **#1** suggestion for `candle a`, so its `source_rank` is 1 even though it's the 14th row of the seed. **This is the relevance signal** — sort by it to find the strongest term surfaced by each query.

**`search_url`** — a ready-to-click Etsy search URL for that suggestion.

**`prefix`** — the expansion character that surfaced this suggestion (empty for the seed's own dropdown; only meaningful when prefix expansion is on).

**`source_query`** — the exact query sent to Etsy that first surfaced this suggestion (the seed itself, or e.g. `handmade candle a`).

**`scraped_at`** — UTC timestamp.

### What you control

| Field | Default | Description |
|---|---|---|
| `keywords` | — | Seed terms to expand, any number, batched in one run |
| `expandPrefixes` | **true** | Also query each seed followed by every expansion character (`gift a`, `gift b`, …) and merge the dropdowns — 14–27× more long-tail per seed. Set to `false` for just the seed's own dropdown |
| `prefixCharacters` | a–z | Characters appended during expansion; edit to add digits or narrow the set |
| `maxSuggestionsPerSeed` | — | Optional cap on deduplicated suggestions kept per seed — a cost guardrail for expansion |
| `maxTotalResults` | **2000** | Cap on suggestions saved across the whole run. Once hit, remaining queries are skipped — rows beyond the cap are never saved or billed. Raise it for large sweeps |

### Use cases

**Deep long-tail sweeps.** The default. Each seed is pulled followed by every letter (`mushroom lamp a`, `mushroom lamp b`, …) — the same trick power users do by hand, harvesting 14–27× more suggestions per seed in one run.

```json
{
  "keywords": ["mushroom lamp", "cottagecore decor", "linen dress"]
}
```

**Just the dropdown.** Turn expansion off when you want exactly what a shopper sees when they type your seed, and nothing more.

```json
{
  "keywords": ["mushroom lamp"],
  "expandPrefixes": false
}
```

**Bounded spend.** `maxTotalResults` caps the run and defaults to 2000. Raise it for a big sweep, or lower it to hold a run to a known budget.

```json
{
  "keywords": ["mushroom lamp", "cottagecore decor", "linen dress"],
  "maxTotalResults": 500
}
```

Across many seeds, prefer `maxSuggestionsPerSeed` — seeds run in parallel and race for the run-wide budget, so `maxTotalResults` alone doesn't guarantee each seed gets an equal share.

```json
{
  "keywords": ["lamp", "decor", "dress", "candle", "mug"],
  "maxSuggestionsPerSeed": 100
}
```

**Find the strongest term per prefix.** Sort by `source_rank` and filter to `1` to get Etsy's top suggestion for every query it answered — 27 high-confidence terms per expanded seed, one per letter of the alphabet.

**Listing title & tag research.** Rank-ordered suggestions double as a ready-made source of search terms for titles and tags — pulled straight from what shoppers actually type.

**Non-English markets.** Seed in the language you sell in. Etsy completes the phrase you give it, so German seeds return German long-tail and French seeds return French — no locale setting, no separate run per market.

```json
{
  "keywords": ["kerze", "geschenk für sie", "cadeau personnalisé"]
}
```

**Bulk seed sweeps.** Run dozens of seed variants in one call — each gets its own rank-ordered suggestion set and a per-seed summary.

### Output

Results land in the **default dataset** — export as JSON, CSV, Excel, or JSONL from the Apify console or via API. The dataset holds only suggestion rows (one per suggestion).

Per-seed status is written to the **Key-Value Store** under the key `RUN_REPORT`, a single object with a `seeds` array (`keyword`, `queries` — how many autocomplete queries the seed fanned out into, `suggestions_count`, `completed` — false if any of the seed's queries permanently failed after retries) plus a `summary` of run totals. If a seed came back incomplete, you'll know which one — rather than silently receiving fewer keywords than you asked for. Keeping it out of the dataset means the dataset stays billable-per-suggestion with no meta rows mixed in.

### Sample row

```json
{
  "keyword": "candle",
  "suggestion": "candle art",
  "rank": 14,
  "source_rank": 1,
  "search_url": "https://www.etsy.com/search?q=candle+art",
  "prefix": "a",
  "source_query": "candle a",
  "scraped_at": "2026-07-05T12:00:00.000000+00:00"
}
```

The 14th row of the `candle` seed, and Etsy's **first** suggestion for `candle a`.

### What this Actor does not do

It returns Etsy's autocomplete suggestions — the real search phrases Etsy proposes to shoppers. It does not estimate search volume, competition scores, or listing performance. Those numbers are not published by Etsy, and tools that display them are modelling, not measuring.

***

> ⚠️ Unofficial. This actor is not affiliated with, endorsed by, or sponsored by Etsy, Inc. "Etsy" is a trademark of Etsy, Inc., used here for descriptive purposes only.

# Actor input Schema

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

Seed terms to expand via Etsy's search-box autocomplete. Broad or specific — both expand well.

## `expandPrefixes` (type: `boolean`):

For each seed, also query the seed followed by each expansion character ("gift a", "gift b", …) and merge the dropdowns. Uncovers 14–27× more long-tail suggestions per seed. On by default — turn it off for just the seed's own dropdown, or use the caps below to bound the result count.

## `prefixCharacters` (type: `string`):

Characters appended to each seed when "Expand prefixes" is on (each as " {char}"). Defaults to a–z; edit to add digits or narrow the set. Only used when expansion is enabled.

## `maxSuggestionsPerSeed` (type: `integer`):

Cap the number of (deduplicated) suggestions kept per seed. Cost guardrail for prefix expansion. Leave empty for unlimited.

## `maxTotalResults` (type: `integer`):

Cap the total number of suggestions the run will save and bill for, across every seed. Once reached, remaining queries are skipped — capped rows are never saved and never billed. Defaults to 2000; raise it for large sweeps. With many seeds, which seeds fill the cap is not guaranteed, so prefer maxSuggestionsPerSeed when you want an even split.

## Actor input object example

```json
{
  "keywords": [
    "candle"
  ],
  "expandPrefixes": true,
  "prefixCharacters": "abcdefghijklmnopqrstuvwxyz",
  "maxTotalResults": 2000
}
```

# Actor output Schema

## `suggestions` (type: `string`):

The dataset: one row per suggestion with rank, dropdown rank, and search URL.

## `runReport` (type: `string`):

Per-seed status (query count, suggestions, completed) and run totals.

# 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": [
        "candle"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("astravalabs/etsy-keyword-research-tool").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": ["candle"] }

# Run the Actor and wait for it to finish
run = client.actor("astravalabs/etsy-keyword-research-tool").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 '{
  "keywords": [
    "candle"
  ]
}' |
apify call astravalabs/etsy-keyword-research-tool --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=astravalabs/etsy-keyword-research-tool",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Etsy Keyword Research Tool — Bulk Autocomplete & Long-Tail",
        "description": "Bulk Etsy keyword research from search autocomplete. Expand seeds into\nlong-tail keywords with ranks and ready-to-open search URLs. No per-run fee.",
        "version": "0.0",
        "x-build-id": "stTvrOzl09dLWwYbo"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/astravalabs~etsy-keyword-research-tool/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-astravalabs-etsy-keyword-research-tool",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/astravalabs~etsy-keyword-research-tool/runs": {
            "post": {
                "operationId": "runs-sync-astravalabs-etsy-keyword-research-tool",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/astravalabs~etsy-keyword-research-tool/run-sync": {
            "post": {
                "operationId": "run-sync-astravalabs-etsy-keyword-research-tool",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "keywords"
                ],
                "properties": {
                    "keywords": {
                        "title": "Keywords",
                        "minItems": 1,
                        "type": "array",
                        "description": "Seed terms to expand via Etsy's search-box autocomplete. Broad or specific — both expand well.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "expandPrefixes": {
                        "title": "Expand prefixes (long-tail discovery)",
                        "type": "boolean",
                        "description": "For each seed, also query the seed followed by each expansion character (\"gift a\", \"gift b\", …) and merge the dropdowns. Uncovers 14–27× more long-tail suggestions per seed. On by default — turn it off for just the seed's own dropdown, or use the caps below to bound the result count.",
                        "default": true
                    },
                    "prefixCharacters": {
                        "title": "Prefix characters",
                        "type": "string",
                        "description": "Characters appended to each seed when \"Expand prefixes\" is on (each as \" {char}\"). Defaults to a–z; edit to add digits or narrow the set. Only used when expansion is enabled.",
                        "default": "abcdefghijklmnopqrstuvwxyz"
                    },
                    "maxSuggestionsPerSeed": {
                        "title": "Max suggestions per seed",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Cap the number of (deduplicated) suggestions kept per seed. Cost guardrail for prefix expansion. Leave empty for unlimited."
                    },
                    "maxTotalResults": {
                        "title": "Max total results (whole run)",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Cap the total number of suggestions the run will save and bill for, across every seed. Once reached, remaining queries are skipped — capped rows are never saved and never billed. Defaults to 2000; raise it for large sweeps. With many seeds, which seeds fill the cap is not guaranteed, so prefer maxSuggestionsPerSeed when you want an even split.",
                        "default": 2000
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
