# ASO Keyword Rank Tracker: App Store & Google Play (`glitchbound/aso-keyword-rank-tracker`) Actor

Track where apps rank for any keyword on the App Store and Google Play in 57 countries, and do ASO keyword research with each store's own keyword suggestions (autocomplete). Top results in store order, the rank of every app you track, and Google Play read in each country's language.

- **URL**: https://apify.com/glitchbound/aso-keyword-rank-tracker.md
- **Developed by:** [Daniel Meshulam](https://apify.com/glitchbound) (community)
- **Categories:** Developer tools, SEO tools, Automation
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 rank rows

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

## ASO Keyword Rank Tracker: App Store & Google Play

See **where any app ranks for any keyword** on the App Store and Google Play, in 57 countries. Get the top results as each store orders them, the rank of every app you track, and the keyword ideas each store suggests, with rating, installs, developer and price.

No API key, no login, no Apple or Google developer account.

### Why the ranks here are the store's ranks

Most keyword trackers read Apple's public Search API and report its order as the App Store ranking. It is not the same list. Measured on five keywords in September 2026, Apple's API put the right app in the right position for only **5 to 7 of the top 10** App Store results.

So this Actor reads the **App Store's own search page** for the top positions, which is the exact order a user sees (9 to 14 apps depending on the country, measured in all 57), and continues in Apple's API order below that. Every row says which it is:

| `rankSource` | What it means |
|---|---|
| `app-store-page` | the App Store's exact position |
| `itunes-search-api` | Apple's API order, used below the store page's top positions (approximate) |
| `google-play-page` | Google Play's exact position |

Two more things a naive tracker gets wrong, handled here:

- **App Store stories are not apps.** An editorial card in the results is skipped, so it does not push every app below it down a place.
- **In-app event cards are apps.** When the App Store shows an app's event card instead of its usual listing, that is still the app at that position, and it is ranked (`hasInAppEvent: true`).
- **Google Play ranks depend on the phone's language.** Read in English, "vpn" in Germany kept only **1 of its top 10** apps in the same position as the German ranking a German phone sees. So each country is read in its own language (German in Germany, pt-BR in Brazil, es-419 in Mexico), and every Play row says which in `language`. Set `language` to `en` to read every country in English instead.

### Track your apps

```json
{
  "keywords": ["meditation", "sleep sounds", "breathing exercises"],
  "stores": ["app-store", "google-play"],
  "countries": ["us", "gb", "de"],
  "trackApps": ["571800810", "com.calm.android"],
  "topN": 10
}
```

For every keyword, store and country you get:

- the **top 10** apps (`rowType: "top-result"`), your own flagged with `tracked: true`
- one row per **tracked app** (`rowType: "tracked-app"`) with its `rank`, or `rankStatus: "not-in-top-N"` when it is not there, where N is how deep that search actually went: up to 200 on the App Store (Apple usually returns 180 to 196) and 30 on Google Play

Set `topN` to 0 to get only your tracked apps: the cheapest way to run a daily rank check.

**App ids:** an App Store numeric id (`571800810`), an App Store bundle id (`com.calm.calmapp`), or a Google Play package name (`com.calm.android`). A numeric id is only looked for on the App Store, so a Play package is never reported as "not ranked" on a store it cannot be in.

### Keyword ideas

Turn on `includeSuggestions` and every keyword also returns what the store itself suggests while it is being typed, in the store's own order: the phrases real users are steered towards.

```json
{
  "keywords": ["medit"],
  "stores": ["app-store", "google-play"],
  "countries": ["us", "jp"],
  "topN": 0,
  "includeSuggestions": true
}
```

That run returns only ideas (`rowType: "suggestion"`), such as `meditation`, `meditation timer` and `mediterranean diet` on the US App Store, and `瞑想アプリ 無料` on the Japanese one. Each store answers in its own market's language. App Store suggestions cover 56 of the 57 countries; Bangladesh returns an unbilled note instead.

### What you get per row

```json
{
  "rowType": "top-result",
  "keyword": "meditation",
  "store": "app-store",
  "country": "US",
  "rank": 1,
  "rankSource": "app-store-page",
  "appId": "337472899",
  "bundleId": "com.spotlightsix.zentimer",
  "title": "Insight Timer: Meditate, Sleep",
  "subtitle": "Meditation & Anxiety Relief",
  "developer": "Insight Network Inc",
  "rating": 4.9,
  "ratingCount": 446397,
  "ageRating": "13+",
  "isEditorsChoice": true,
  "hasInAppEvent": true,
  "genre": "Health & Fitness",
  "price": 0,
  "currency": "USD",
  "depthChecked": 10,
  "exactPositions": 10,
  "checkedAt": "2026-09-16T10:00:00Z"
}
```

Google Play rows carry `installs` (e.g. `10,000,000+`), the listing `summary` and the `language` the store was read in (category names come back in that language, e.g. `Wetter` in Germany); App Store rows carry `subtitle`, `ratingCount`, `ageRating`, `isEditorsChoice` and `releaseDate`.

### Built to be scheduled

Ranks only mean something over time. Schedule this daily; every row has `checkedAt`, so consecutive runs become a rank history per keyword with no extra work. The **Your apps over time** view shows exactly that.

### Pricing

**$1.00 per 1,000 rows**, pay per result, lower on higher Apify plans. No subscription.

- A daily check of 20 keywords for one tracked app, in both stores and one country, is 40 rows a day: about **$1.20 a month**.
- A search that could not be read, and an input value that is not usable, each come back as an **unbilled** error row naming it.
- `maxItems` caps the whole run.

### Honest limits

- **Google Play ranks go to 30.** That is every app Google Play's search page lists; its old way of paging further no longer works. An app below 30 is reported as `not-in-top-30`.
- **App Store exact positions go as deep as the store page does** (9 to 14, depending on the country). Below that the order is Apple's API order, labelled `itunes-search-api`, which is close but not identical. Tracked apps are looked for in the top 200.
- **No search volume or difficulty scores.** Keyword popularity numbers come from Apple Search Ads or paid ASO suites; this Actor reports what the stores show, not an estimate.

### Input reference

| Field | What it does | Default |
|---|---|---|
| `keywords` | the search terms, up to 100 per run | required |
| `stores` | `app-store`, `google-play`, or both | both |
| `countries` | two-letter codes from the list below | `us` |
| `language` | Google Play only: read every country in this language (`en`, `de`, `pt-BR`) instead of its own | each country's own |
| `trackApps` | App Store numeric ids or bundle / package names | none |
| `topN` | top results per search, 0 to 50; 0 returns only tracked apps and ideas | 10 |
| `includeSuggestions` | also return each store's keyword ideas | off |
| `maxItems` | a ceiling on rows for the whole run | none |

### Countries

United States, United Kingdom, Canada, Australia, India, Germany, France, Spain, Italy, Netherlands, Sweden, Norway, Denmark, Finland, Poland, Portugal, Ireland, Austria, Switzerland, Belgium, Czechia, Romania, Hungary, Greece, Turkey, Saudi Arabia, United Arab Emirates, Egypt, South Africa, Nigeria, Kenya, Brazil, Mexico, Argentina, Colombia, Chile, Peru, Japan, South Korea, Taiwan, Hong Kong, Singapore, Malaysia, Thailand, Vietnam, Philippines, Indonesia, New Zealand, Russia, Ukraine, Kazakhstan, Pakistan, Bangladesh, Sri Lanka, Qatar, Kuwait, Morocco.

### Pairs with

- [Google Play Top Charts Scraper](https://apify.com/glitchbound/google-play-charts-scraper): the Top Free, Paid and Grossing charts
- [App Store Top Charts Scraper](https://apify.com/glitchbound/app-charts-scraper): the same for the App Store
- [App Store & Google Play Scraper](https://apify.com/glitchbound/app-store-scraper): full details for any app you found here
- [App Store & Google Play Reviews Scraper](https://apify.com/glitchbound/app-reviews-scraper): what users say about the apps that outrank you

### Use it from an AI agent

This Actor is a ready-made tool for Claude, ChatGPT, Cursor or any other MCP
client, through Apify's MCP server. Add it as a connector at:

```
https://mcp.apify.com?tools=glitchbound/aso-keyword-rank-tracker
```

In Cursor or VS Code the same address goes in `mcp.json`:

```json
{ "mcpServers": { "apify": { "url": "https://mcp.apify.com?tools=glitchbound/aso-keyword-rank-tracker" } } }
```

The first call asks you to sign in to Apify, or takes an API token. From then
on the agent sees this Actor's input fields and calls it directly.

### Feedback

If this saved you time, a review on the Actor's Store page helps other people
find it. If something is missing or wrong, the Issues tab on the same page is
the fastest way to reach me, and it gets read.

# Actor input Schema

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

Search terms, one per line, exactly as a user would type them in the store. Up to 100 per run.

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

Which stores to search. App Store ranks are exact for the top positions the store's own page shows (9 to 14, depending on the country) and continue in Apple's API order below that; Google Play ranks are exact to 30, which is all its search page lists.

## `countries` (type: `array`):

Storefronts to search in. Every country listed was checked against Google Play's own answer.

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

Leave empty to read each country in the language its phones use (German in Germany, pt-BR in Brazil), which is what decides the ranking there: in Germany only 1 of the top 10 for "vpn" held its position when read in English. Set a code such as en to read every country in that language instead. The App Store always answers in its storefront's own language.

## `trackApps` (type: `array`):

Apps whose rank you want for every keyword: an App Store numeric id (571800810), an App Store bundle id, or a Google Play package name (com.calm.android). Each returns one row per keyword, store and country, with its rank or 'not-in-top-N'. On the App Store a tracked app is looked for in the top 200.

## `topN` (type: `integer`):

How many of the top apps to return for each keyword, store and country. Set 0 to return only your tracked apps.

## `includeSuggestions` (type: `boolean`):

Also return what each store suggests while the keyword is being typed, in the store's own order: the phrases real users are steered to. One row per suggestion, charged like any row. App Store suggestions are available in 56 of the 57 countries (not Bangladesh).

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

A hard ceiling on rows for the entire run. The run stops cleanly when it is reached and nothing beyond that point is fetched or charged. Leave empty for no ceiling.

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

Proxy settings.

## Actor input object example

```json
{
  "keywords": [
    "meditation"
  ],
  "stores": [
    "app-store",
    "google-play"
  ],
  "countries": [
    "us"
  ],
  "trackApps": [
    "571800810",
    "com.calm.android"
  ],
  "topN": 10,
  "includeSuggestions": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Top results and tracked-app ranks per keyword, store and country.

# 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": [
        "meditation"
    ],
    "countries": [
        "us"
    ],
    "trackApps": [
        "571800810",
        "com.calm.android"
    ],
    "topN": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("glitchbound/aso-keyword-rank-tracker").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": ["meditation"],
    "countries": ["us"],
    "trackApps": [
        "571800810",
        "com.calm.android",
    ],
    "topN": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("glitchbound/aso-keyword-rank-tracker").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": [
    "meditation"
  ],
  "countries": [
    "us"
  ],
  "trackApps": [
    "571800810",
    "com.calm.android"
  ],
  "topN": 10
}' |
apify call glitchbound/aso-keyword-rank-tracker --silent --output-dataset

```

## MCP server setup

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

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/lGQnhaNPeH8idxKNl/builds/YF1rv2yBWROeOqZPq/openapi.json
