App Store Keyword Rank Tracker (ASO): 175 Countries avatar

App Store Keyword Rank Tracker (ASO): 175 Countries

Pricing

from $2.00 / 1,000 results

Go to Apify Store
App Store Keyword Rank Tracker (ASO): 175 Countries

App Store Keyword Rank Tracker (ASO): 175 Countries

App Store keyword rank tracker: your app's and competitors' rank for any keyword in all 175 App Store countries. One row per keyword and country with the top apps and competition signals. Schedule it daily for rank history.

Pricing

from $2.00 / 1,000 results

Rating

0.0

(0)

Developer

mochi

mochi

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

App Store keyword rank tracker: your app's and competitors' rank for any keyword in all 175 App Store countries. Give it keywords, countries and the apps you want to follow. For every keyword in every country it writes one row with the rank of each tracked app (1 to 200, or null when the app is not in Apple's top 200), the top apps for that search and a few honest competition figures.

Price: Pay per result, at the rate shown in the pricing panel of this page, plus a very small per-run start fee. You are charged only for the results delivered.

What you get

  • One row per keyword per country, with every tracked app in it. Track your app and its competitors together: each row lists tracked, one entry per app with its rank in that country for that keyword. A row is one result, however many apps you track.
  • Competition signals on each row, from the same answer. The top-10 average and median rating count, the paid-app count in the top 10 and the top-10 average stars. They are plain figures from Apple's data, with no invented "difficulty score".
  • Built for daily tracking. Schedule the same input every day with an Apify Schedule and chart the ranks from scrapedAt. The actor keeps no memory between runs: every run is a fresh set of rows.

How the rank is measured

Ranks come from Apple's public App Store search API (iPhone and universal apps), asked once per keyword and country, with the first 200 results. The rank is the position of the app in that list.

This is the App Store search API ranking, not a device ranking. It matches the App Store's own web search closely but not always exactly. We checked "habit tracker" in the US on 2026-10-17: all 11 apps of the App Store web search were among the API's first 12, with small swaps (the web's number 2 was the API's number 4, the web's number 3 the API's number 2). What the App Store shows on a phone can also differ by device, language and personalisation. Use it to follow changes over time, not to settle a dispute about one exact position.

Input

fieldmeaningdefault
Keywordssearch terms to check, for example habit tracker, budget apphabit tracker
Countriestwo-letter App Store codes (us, gb, de, jp ...); ["all"] = all 175 storefrontsus
Apps to trackyour app and competitors: App Store IDs (1438388363) or App Store linksnone
Top apps per rowhow many top-ranked apps to list in each row (0 to 200; 0 = none)10
Max rows1 to 20000; a hard cap, and the number of rows you pay for1000

Starting the actor without changing anything checks "habit tracker" in the US: one row.

Every keyword is checked in every country, keywords in the outer loop, countries in the inner one: all countries of the first keyword, then the second keyword, and so on. If "Max rows" is smaller than keywords times countries, the run stops after that many rows and the summary says how many checks were left (checksNotRun). An unknown country code (for example uk; the code for the United Kingdom is gb) stops the run before it starts, with a plain message.

How long a run takes

The actor is polite to Apple. It sends one request at a time and never more than 18 requests a minute for the whole run, which is one request every 3.3 seconds, the app lookup and any retries included. Apple's documentation for its search API mentions about 20 calls a minute, and the actor stays under that on purpose, so that Apple does not refuse a long run.

In practice Apple usually needs 3 to 6 seconds to answer a search with 200 results, which is slower than the 3.3 seconds, so a run does about 12 requests a minute: plan for about 5 seconds per row. Each row is one search request, so the time is in proportion to the number of rows:

  • 15 rows (3 keywords in 5 countries) take about 1.3 minutes.
  • 100 rows take about 8.5 minutes.
  • 1,000 rows, the default cap, take about 86 minutes.
  • All 175 countries for one keyword take about 15 minutes.
  • 10 keywords in all 175 countries are 1,750 rows and take about 2.5 hours.

Give a run of more than about 600 rows a time limit that covers 5 seconds a row (Run options, Timeout; or timeout=7200 in the API call, which covers about 1,400 rows). If the time limit comes first, the run stops cleanly: terminationReason: "time_budget", complete: false, the rows written so far are in the dataset and RUN_SUMMARY says how many checks were not made. You can also split a big grid over several runs; each run keeps to its own pace.

If Apple refuses a request (for example with HTTP 403, or 429 for too many requests), the run stops at once with terminationReason: "blocked", keeps the rows it has already written, and does not try again or work around the refusal. If it refused before any row was written, the run is marked failed. Network errors and server errors (HTTP 5xx) are retried three times (after 2, 4 and 8 seconds, at the same pace); a check that still gets no answer is listed in problems and the run goes on, and three such checks in a row stop the run.

If the platform moves the run to another server, the run restarts itself and carries on: the rows already in the dataset are never requested, written or charged a second time.

Output

One row per keyword and country. Fields: keyword, country, countryName, resultCount, tracked, topApps, top10AvgRatingCount, top10MedianRatingCount, top10PaidCount, top10AvgRating, scrapedAt.

  • resultCount: how many apps Apple returned for the search (at most 200).
  • tracked: one entry per app you track, in the order you gave them: appId, appName and rank. The rank is the 1-based position in Apple's list, or null when the app is not among the first 200 results (or not sold in that country). The appName comes from Apple's US lookup, so it is the same in every country; an app the lookup does not know takes its name from the search result where it appears, otherwise it is null.
  • topApps: the first "Top apps per row" apps: rank, appId, appName, developer, rating, ratingCount, price, currency, genre, releaseDate, lastUpdated, url. Names, prices and currencies are those of that country's own store, so a name can be translated. A field Apple leaves out is null.
  • top10AvgRatingCount, top10MedianRatingCount: the mean (rounded to a whole number, an exact half to the even number) and the median of the rating counts of ranks 1 to 10. A high number means entrenched apps.
  • top10PaidCount: how many of ranks 1 to 10 cost money (price above 0).
  • top10AvgRating: the mean stars of ranks 1 to 10, to two decimals. Apps without ratings count as 0 ratings and 0 stars in the two averages and the median; with fewer than 10 results the figures use the results there are. When Apple finds no apps at all (resultCount is 0) they are null (and the paid count 0).
  • scrapedAt: when the row was made (UTC).

Example (one row, shortened to two top apps):

{
"keyword": "habit tracker",
"country": "us",
"countryName": "United States",
"resultCount": 192,
"tracked": [
{"appId": "1438388363", "appName": "Habit Tracker", "rank": 1},
{"appId": "1528595748", "appName": "Finch: Self-Care Pet", "rank": 4},
{"appId": "1232780281", "appName": "Notion: Notes, Tasks, AI", "rank": null}
],
"topApps": [
{"rank": 1, "appId": "1438388363", "appName": "Habit Tracker", "developer": "Inner Grow Limited", "rating": 4.79129, "ratingCount": 148007, "price": 0, "currency": "USD", "genre": "Productivity", "releaseDate": "2019-01-31T09:10:14Z", "lastUpdated": "2026-10-15T06:46:50Z", "url": "https://apps.apple.com/us/app/habit-tracker/id1438388363?uo=4"},
{"rank": 2, "appId": "6443918070", "appName": "Habit Tracker - HabitKit", "developer": "Sebastian Roehl", "rating": 4.843, "ratingCount": 2484, "price": 0, "currency": "USD", "genre": "Productivity", "releaseDate": "2022-11-26T08:00:00Z", "lastUpdated": "2026-10-13T07:41:12Z", "url": "https://apps.apple.com/us/app/habit-tracker-habitkit/id6443918070?uo=4"}
],
"top10AvgRatingCount": 106592,
"top10MedianRatingCount": 13415,
"top10PaidCount": 0,
"top10AvgRating": 4.79,
"scrapedAt": "2026-10-17T18:00:00.000Z"
}

Only public data is read: Apple's public search and lookup interfaces, with no login, no account and no cookies. The rows contain app names, developers' public App Store names, ratings and links; no personal contact details.

Limits you should know

  • Apple's search API serves at most 200 apps per search. A null rank means "not in the top 200" for that keyword in that country, not "not found anywhere".
  • Only iPhone and universal apps are searched (Apple's software search); apps made for iPad only may be missing from the list.
  • Ranks are per country: the actor asks each storefront with its own country code. Apple's results move during the day; a second run an hour later can differ.
  • Apple matches loosely, but a made-up word can return no apps at all (on 2026-10-23 one returned 1 app in the US and 0 in Germany). If it happens, the row has resultCount 0 (no apps, empty topApps, null ranks) and counts as a result like any other row. When more than 30% of the rows of a run have no apps, RUN_SUMMARY says so in note, because Apple may also answer with empty lists when it is busy: run again later if you expected results.
  • If Apple's search API rejects a country with HTTP 400, that check is skipped (no row), listed in problems and counted in checksRejected.
  • Tracked apps: you may list as many as you like; the lookup that names them is one request per 50 apps.

Run summary

The key-value store record RUN_SUMMARY holds:

  • complete: true for finished and max_results, false for every other ending.
  • terminationReason: finished (every check of the grid was made), max_results (your "Max rows" was reached; checksNotRun says how many checks of the grid were left), charge_limit (your maximum cost per run was reached), time_budget (the run timeout was near), blocked (Apple refused a request), request_failed (one or more checks got no answer after the retries, so the result is partial) or invalid_input (the input was unusable; nothing was written).
  • rowsPushed, checksPlanned, checksNotRun, checksRejected, checksFailed, emptyResults (rows with no apps), requests, retries, seconds, requestsPerMinuteLimit (18).
  • problems: up to 50 short sentences about checks that were skipped or failed. note: null, or a plain sentence about rejected countries or many empty answers. error: null, or why the run stopped.
  • restarts: only after the platform restarted the run; the last key.

requests and retries count the requests the run made; after a platform restart they can miss the last requests of the earlier container.

Measured on the platform

Measured on 2026-10-23, at 256 MB unless stated. Apple's answer times depend on the day; the numbers about requests and refusals are the ones to trust.

  • Pace: all 175 storefronts for one keyword ("habit tracker", one tracked app): 175 rows from 176 requests (one lookup and 175 searches) in 902 seconds, which is 11.7 requests a minute or 5.1 seconds a row, under the 18 a minute cap because Apple usually took 3 to 8 seconds to answer a search with 200 results. No refusal, no retry, no storefront rejected, no empty answer. Each storefront returned 179 to 199 apps. Every field of every row, and of every entry in topApps, was filled (100%).
  • 3 keywords in 5 countries, one tracked app (15 rows): 15 rows from 16 requests in 79 seconds (53 seconds on a second run, when Apple answered faster), each with resultCount above 0 (179 to 193), 10 apps in topApps and one tracked entry; the app ranked 1 for "habit tracker" in all five countries.
  • Default input (nothing changed): one row for "habit tracker" in the US, in 2 seconds.
  • Max rows 1 with 2 keywords in 2 countries: exactly one row, terminationReason: "max_results", checksNotRun: 3.
  • Time limit: 100 keywords with a 45-second run timeout: the run stopped by itself after 36 seconds with 8 to 10 rows (two runs), terminationReason: "time_budget", complete: false, and wrote RUN_SUMMARY.
  • Platform restart: a 40-row run was restarted twice by the platform (after 13 and 26 rows) and another once (after 16 rows): each ended with 40 rows in the dataset, 40 different keyword-country pairs, no duplicate, rowsPushed 40 in RUN_SUMMARY and restarts 2 and 1.
  • Wrong input: no keyword, an unknown country code (zz) or an app that is not an ID or link (notion) fail the run in about a second with the plain message and write no row.
  • Memory: these runs had 256 MB; the peak was 121 MB over the 175-row run, 84 MB for 15 rows, and 71 MB for 20 rows that each list 200 top apps and 100 tracked apps.

Keywords: aso, app store optimization, keyword rank tracker, app store keyword ranking, app ranking tracker, ios keyword rank, aso tool, app store search rank, competitor app ranking.