# ASO Keyword Research: App Store & Google Play Keyword Tool (`spokentext/aso-keyword-research`) Actor

App Store and Google Play keyword research: popularity, difficulty and opportunity scores for each keyword, store search suggestions, the top-ranking apps and your app's rank. No login, no API key. Pay per keyword.

- **URL**: https://apify.com/spokentext/aso-keyword-research.md
- **Developed by:** [clement](https://apify.com/spokentext) (community)
- **Categories:** SEO tools, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.00 / 1,000 keyword analyseds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What is ASO Keyword Research?

**ASO Keyword Research** is an **App Store and Google Play keyword tool**. Give it the search terms you are considering for your app, and for each keyword and store you get:

- a **popularity** score, from how quickly the store suggests the keyword while typing
- a **difficulty** score, from how strong the apps already ranking are
- an **opportunity** score that combines both
- the store's **search suggestions**, to discover related keywords
- the **top 10 apps** for the keyword, with ratings and ratings counts
- **your app's rank**, and your competitors' ranks

It is built for app developers, App Store Optimization (ASO) specialists, app marketers and agencies choosing keywords for app titles, subtitles and keyword fields.

### Why use it?

- **Both stores in one run:** App Store (iPhone and iPad) and Google Play (Android).
- **Find keywords worth targeting:** the opportunity score ranks keywords that are searched often but where the top apps are weak.
- **Discover related keywords:** switch on **Also analyse the store's suggestions** to score what the store suggests for each keyword.
- **Track rankings:** add your app and your competitors, and schedule the run weekly.
- **Transparent scores:** every formula is explained below; no black box.
- **No login, no API key:** data comes from the stores' public search.

Because it runs on Apify, you also get scheduling, API access, integrations (Make, Zapier, n8n, Google Sheets) and exports to JSON, CSV or Excel.

### How the scores work

| Score | How it is computed |
|---|---|
| **Popularity** (0 to 100) | The fewest letters a shopper must type before the store suggests the keyword. Suggested after 2 letters gives 100; only when typed in full gives close to 0; never suggested gives 0. Stores suggest what people search most, so this tracks search popularity. |
| **Difficulty** (0 to 100) | 20 × log10 of the median ratings count of the top 10 apps, capped at 100. A median of 100 ratings gives 40, 10,000 gives 80, 100,000 or more gives 100. |
| **Opportunity** (0 to 100) | Popularity × (100 − difficulty) / 100. |

Popularity is an estimate from public suggestions, not Apple's or Google's internal search volume.

### How to use it

1. Enter your **keywords**, one per line, as a user would type them.
2. Choose the **stores** and the **country** (and the Google Play language).
3. Optionally add **your apps** (App Store IDs or links, Google Play package names or links) and your competitors.
4. Optionally switch on **Also analyse the store's suggestions** to discover related keywords.
5. Click **Start** and open the **Output** tab. Sort by **Opportunity** to find the best keywords.

### How much does it cost?

You pay per keyword analysed in one store: **$0.01** at the Bronze tier, less at Silver and Gold. A keyword analysed in both stores is two analyses.

| Usage | Cost (Bronze) |
|---|---|
| 20 keywords in both stores | $0.40 |
| 20 keywords in both stores, with 5 suggestions each | $2.40 |
| 50 keywords in one store, every week for a month | $2.00 |

Keywords that fail are not charged.

### Input example

```json
{
    "keywords": ["habit tracker", "sourdough timer", "photo editor"],
    "stores": ["apple", "google"],
    "country": "us",
    "language": "en",
    "yourApps": ["1453958021", "com.example.app"],
    "analyseSuggestions": true,
    "suggestionsPerKeyword": 2
}
```

### Output example

Real results captured on 2026-11-05 (US stores):

| Keyword | Store | Popularity | Difficulty | Opportunity |
|---|---|---|---|---|
| habit tracker | App Store | 92 | 83 | 16 |
| habit tracker widget | App Store | 74 | 43 | 42 |
| habit tracker | Google Play | 92 | 82 | 17 |
| sourdough timer | App Store | 36 | 6 | 34 |
| sourdough timer | Google Play | 36 | 35 | 23 |
| photo editor | App Store | 100 | 100 | 0 |

"habit tracker widget" is searched almost as early as "habit tracker" but faces far weaker apps: a better target.

One row (top apps shortened to 2):

```json
{
    "keyword": "habit tracker",
    "store": "App Store",
    "country": "us",
    "popularity": 92,
    "lettersTyped": 3,
    "difficulty": 83,
    "opportunity": 16,
    "medianRatingsTop10": 13517,
    "appsFound": 47,
    "yourApps": [{ "appId": "1453958021", "rank": null, "name": null }],
    "topApps": [
        { "rank": 1, "appId": "1438388363", "name": "Habit Tracker", "developer": "Inner Grow Limited", "rating": 4.79, "ratingsCount": 148558, "url": "https://apps.apple.com/us/app/habit-tracker/id1438388363" },
        { "rank": 2, "appId": "6443918070", "name": "Habit Tracker - HabitKit", "developer": "Sebastian Roehl", "rating": 4.84, "ratingsCount": 2539, "url": "https://apps.apple.com/us/app/habit-tracker-habitkit/id6443918070" }
    ],
    "suggestions": ["habit tracker free", "habit tracker", "habit tracker widget", "habit tracker with friends", "habit tracker and planner"],
    "seedKeyword": null,
    "status": "ok"
}
```

| Field | Meaning |
|---|---|
| `popularity`, `lettersTyped` | Popularity score, and the fewest letters after which the store suggests the keyword |
| `difficulty`, `medianRatingsTop10` | Difficulty score, and the median ratings count it comes from |
| `opportunity` | Popularity × (100 − difficulty) / 100 |
| `appsFound` | Apps returned by the search, up to the search depth |
| `yourApps` | Rank of each of your apps, or `null` if not within the search depth |
| `topApps` | The 10 first apps, with developer, rating and ratings count |
| `suggestions` | What the store suggests for the full keyword |
| `seedKeyword` | For a suggestion analysed in turn, the keyword it came from |

### FAQ

#### Are these Apple's and Google's official search volumes?

No. Neither store publishes search volume. Popularity is estimated from the order of the stores' public search suggestions, the method many ASO tools use. Use it to compare keywords with each other.

#### How accurate are the ranks?

App Store ranks come from Apple's public search API, which closely follows App Store search but can differ slightly from what a given iPhone shows. Google Play ranks come from Google Play's public search page. Both can vary by country, language and device.

#### Which countries are supported?

Google Play: any country. App Store: 48 countries, including the US, UK, Canada, Australia, most of Europe, Japan, Korea, Brazil, Mexico and India.

#### Can I track my rankings over time?

Yes. Add your apps, save the run as a task and schedule it weekly; compare `yourApps` from run to run.

### Limits

- Up to 200 keywords per run, and up to 200 search results read per keyword.
- Ratings counts come from the top 10 apps only, which is what the difficulty score needs.

### Other Actors you may find useful

| Actor | What it does |
|---|---|
| [App Store Reviews Scraper + AI Review Analysis](https://apify.com/spokentext/app-store-reviews) | Reviews of any iPhone app, with an AI report of themes, bugs and feature requests |
| [Google Play Reviews Scraper & Exporter + AI Review Analysis](https://apify.com/spokentext/google-play-reviews) | The same for Android apps |
| [Keyword Search Volume Checker](https://apify.com/spokentext/keyword-search-volume) | Google search volume for web keywords |

### Run it from the API

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")
run = client.actor("spokentext/aso-keyword-research").call(run_input={
    "keywords": ["habit tracker", "sourdough timer"],
    "stores": ["apple", "google"],
})
rows = client.dataset(run["defaultDatasetId"]).list_items().items
for row in sorted(rows, key=lambda r: r.get("opportunity") or 0, reverse=True):
    print(row["keyword"], row["store"], row["opportunity"])
```

This Actor is an independent tool. It is not affiliated with or endorsed by Apple or Google; their names only describe the stores it reads.

### Feedback

Something failed or gave a wrong result? Open an issue in the **Issues** tab of this page, with the error message from your results: every report is read and fixed. If the Actor saved you time, a rating helps others find it.

# Actor input Schema

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

The search terms to analyse, one per line, as a user would type them in the store. Up to 200 per run.

## `stores` (type: `array`):

The stores to analyse each keyword in.

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

Two-letter country code of the store, such as us, gb, fr or de.

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

Language of Google Play suggestions and results, such as en, fr or de.

## `yourApps` (type: `array`):

App Store IDs or links, and Google Play package names or links. Their rank is reported for every keyword.

## `searchDepth` (type: `integer`):

How many search results to read per keyword when looking for your apps.

## `analyseSuggestions` (type: `boolean`):

Score the search suggestions of each keyword too, to discover related keywords. Each one is charged as a keyword.

## `suggestionsPerKeyword` (type: `integer`):

Used when the option above is on.

## Actor input object example

```json
{
  "keywords": [
    "habit tracker",
    "sourdough timer",
    "photo editor"
  ],
  "stores": [
    "apple",
    "google"
  ],
  "country": "us",
  "language": "en",
  "yourApps": [],
  "searchDepth": 50,
  "analyseSuggestions": false,
  "suggestionsPerKeyword": 5
}
```

# Actor output Schema

## `keywords` (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": [
        "habit tracker",
        "sourdough timer",
        "photo editor"
    ],
    "stores": [
        "apple",
        "google"
    ],
    "yourApps": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("spokentext/aso-keyword-research").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": [
        "habit tracker",
        "sourdough timer",
        "photo editor",
    ],
    "stores": [
        "apple",
        "google",
    ],
    "yourApps": [],
}

# Run the Actor and wait for it to finish
run = client.actor("spokentext/aso-keyword-research").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": [
    "habit tracker",
    "sourdough timer",
    "photo editor"
  ],
  "stores": [
    "apple",
    "google"
  ],
  "yourApps": []
}' |
apify call spokentext/aso-keyword-research --silent --output-dataset

```

## MCP server setup

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

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/AZyHdhBDFP1pPxC59/builds/fnqkTAlNFEuc2GNqt/openapi.json
