• Mobile apps
  • Ratings
  • Competitors

iTunes Search API: how to get App Store ratings, versions and release dates for any app

Use the iTunes Search API to get any app's App Store rating, rating count, version and release date by country, with its limits, caching quirks and a tracker.

Author
Extenify Team
Published
Reading time
11 min read
Close-up of a coin-operated sightseeing binocular viewer on a waterfront promenade at sunset, with blurred people and water behind it

The iTunes Search API is the quickest way to read public App Store data for any app: its average rating, how many ratings it has, the current version, when that version shipped and what the release notes say. It needs no API key and no Apple developer account, which is why it shows up in everything from force-update checks to competitor dashboards. It also has quirks that trip up almost everyone who relies on it: ratings that differ by country, a rate limit Apple describes only as "approximately", and cached answers that can lag behind a release by hours.

This guide covers the two endpoints, the fields that matter for tracking, how ratings differ between storefronts, a small Node.js script that records a daily snapshot of your app and your competitors, and the limits you should design around.

Key takeaways

  • The iTunes Search API has two endpoints: /search to find apps by keyword and /lookup to fetch apps by ID or bundle ID. Both are free and need no key.
  • Apple says the API "is limited to approximately 20 calls per minute (subject to change)". Batch IDs, cache results and spread requests out.
  • Ratings are per country. The same app had 53,261 ratings in the US storefront and 4,723 in the UK when we tested. Always pass country and track each market separately.
  • Responses are cached. In our test, a lookup by bundle ID returned a version released an hour earlier while a lookup by numeric ID still returned the previous one. Confirm changes across two snapshots before alerting.
  • The API does not return downloads, revenue or review text. Pair it with App Store Connect for your own numbers and the reviews feed for written reviews.

What the iTunes Search API is

Apple documents the API on its Performance Partners site, originally for affiliates who link to store content. It covers music, books, podcasts and software, and the software results are the App Store. Two base URLs matter:

  • https://itunes.apple.com/search?term=... searches by keyword. Apple lists term, country, media, entity, attribute, limit (1 to 200, default 50), lang and a few more.
  • https://itunes.apple.com/lookup?id=... fetches specific items. Apple's own example is https://itunes.apple.com/lookup?id=909253, and its documented keys include id, upc, entity, limit and sort.

Two parameters that every app tracker uses are not in Apple's lookup table but work in practice: bundleId and country. We verified both on October 9, 2026. Because they are undocumented for lookup, wrap them in code that tolerates an empty result rather than assuming they will always behave.

There is no authentication, no SLA and no versioning. Apple can change the response at any time, so validate the fields you depend on.

Look up an app by ID or bundle ID

Every App Store URL ends with the app's numeric ID. In https://apps.apple.com/us/app/slack/id618783545, the ID is 618783545. Look it up for the US storefront:

curl -s "https://itunes.apple.com/lookup?id=618783545&country=us" \
  | jq '.results[0] | {trackName, version, averageUserRating, userRatingCount, currentVersionReleaseDate}'

If you only know the bundle identifier, use it instead:

curl -s "https://itunes.apple.com/lookup?bundleId=com.tinyspeck.chatlyio&country=us" \
  | jq '.results[0] | {trackId, version, userRatingCount}'

You can also pass several IDs in one request, separated by commas (id=618783545,310633997), which returns one result per app and saves calls against the rate limit. A wrong ID or an app that is not sold in that country returns {"resultCount": 0, "results": []} with a normal 200 status, so check resultCount instead of the HTTP status.

The fields that matter for app tracking

A software result has more than 40 fields. These are the ones worth storing:

Field What it holds Notes
trackId Numeric App Store ID Stable; use it as the key
bundleId Bundle identifier Stable across countries
averageUserRating Average star rating in this storefront Unrounded, such as 4.13411
userRatingCount Number of ratings in this storefront Ratings, not written reviews
averageUserRatingForCurrentVersion Average for the current version Usually equal to the overall value, see below
userRatingCountForCurrentVersion Ratings for the current version Same caveat
version Current version string Can lag behind a release, see caching
currentVersionReleaseDate When the current version was released ISO timestamp in UTC
releaseNotes "What's New" text for the current version Useful for competitor tracking
releaseDate First release of the app
fileSizeBytes Download size Returned as a string
minimumOsVersion Lowest supported iOS version Changes often signal dropped devices
price, formattedPrice, currency Price in the storefront's currency 0 and Free for free apps
primaryGenreName, genres App Store categories
artistId, sellerName Developer account ID and seller artistId finds the developer's other apps

The current-version rating fields look like they should show how the latest release is received, but for most apps they match the overall numbers. In App Store Connect, developers can reset the summary rating when they release a new version. Apple notes the reset applies to all countries at once, that "you won't be able to restore the previous rating", and that written reviews stay visible. Unless an app chose to reset, the current-version figures carry the full history. In our tests on five large apps, including WhatsApp, Instagram and TikTok, they were identical to the overall values. To see how a new release is rated, track the change in userRatingCount and averageUserRating from day to day instead.

Ratings are per country

The App Store has a separate storefront for each country, and ratings belong to the storefront where they were left. The same app, looked up minutes apart on October 9, 2026:

Storefront averageUserRating userRatingCount
United States (us) 4.13 53,261
Japan (jp) 3.76 11,463
United Kingdom (gb) 4.02 4,723
Germany (de) 4.17 3,763

Three consequences follow. Leaving out country gives you the US storefront, which may not be where your users are. A problem that only affects one market, such as a broken translation or a payment issue, shows up as a rating drop in that storefront only. And there is no single "global rating" in the API; if you want one, compute a weighted average across the countries you care about and say so on your dashboard. Our guide to reading review and rating trends explains why the rating count often tells you more than the average.

Search for competitors

The search endpoint finds apps by keyword. Set entity=software for iPhone and iPad apps, and always pass a country:

curl -s "https://itunes.apple.com/search?term=habit+tracker&entity=software&country=us&limit=10" \
  | jq -r '.results[] | "\(.trackId)\t\(.userRatingCount)\t\(.averageUserRating)\t\(.trackName)"'

The order of results is close to, but not guaranteed to match, what users see in App Store search, and we got fewer results than the limit we asked for. Use it to discover competitors and their IDs, then track those IDs with lookups rather than re-running searches.

To list every app from one developer, look up their artistId with entity=software. The first result is the developer, followed by their apps:

curl -s "https://itunes.apple.com/lookup?id=453420243&entity=software&country=us" \
  | jq -r '.results[] | select(.wrapperType == "software") | .trackName'

Build a daily App Store snapshot in Node.js

This script records one row per app and country per day and flags what changed since the previous run. It batches IDs into one request per country and waits between calls to stay well under Apple's limit.

// app-store-snapshot.mjs (Node.js 20+)
import { readFile, writeFile } from 'node:fs/promises';

const APPS = ['618783545', '310633997']; // your app first, then competitors
const COUNTRIES = ['us', 'gb', 'de', 'jp'];
const DB = './app-store-snapshots.json';
const PAUSE_MS = 4000; // about 15 calls per minute

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

async function lookup(ids, country) {
  const url = `https://itunes.apple.com/lookup?id=${ids.join(',')}&country=${country}`;
  const res = await fetch(url, { headers: { 'user-agent': 'app-snapshot/1.0' } });
  if (!res.ok) throw new Error(`lookup ${country} failed: ${res.status}`);
  const { results } = await res.json();
  return results.filter((r) => r.wrapperType === 'software');
}

const history = JSON.parse(await readFile(DB, 'utf8').catch(() => '[]'));
const day = new Date().toISOString().slice(0, 10);

for (const country of COUNTRIES) {
  const apps = await lookup(APPS, country);
  for (const app of apps) {
    const row = {
      day, country, id: String(app.trackId), name: app.trackName,
      rating: app.averageUserRating, ratings: app.userRatingCount,
      version: app.version, released: app.currentVersionReleaseDate,
      minOs: app.minimumOsVersion, price: app.price,
    };
    const prev = history.findLast((h) => h.id === row.id && h.country === country && h.day < day);
    if (prev && typeof prev.rating === 'number' && typeof row.rating === 'number') {
      if (row.version !== prev.version) console.log(`${row.name} [${country}] new version ${prev.version} -> ${row.version}`);
      if (row.rating < prev.rating - 0.05) console.log(`${row.name} [${country}] rating fell ${prev.rating.toFixed(2)} -> ${row.rating.toFixed(2)}`);
      if (row.ratings - prev.ratings > 3 * Math.max(1, prev.dailyGain ?? 1)) console.log(`${row.name} [${country}] unusual jump in ratings: +${row.ratings - prev.ratings}`);
      row.dailyGain = row.ratings - prev.ratings;
    }
    history.push(row);
  }
  await sleep(PAUSE_MS);
}

await writeFile(DB, JSON.stringify(history, null, 2));

Run it once a day from a scheduler you already have. For more than a few dozen apps, move the history into a real database and keep the same shape: one row per app, country and day. Ratings change slowly, so a sudden jump in ratings usually means a rating prompt went live in a new version, a feature on the App Store, or a wave of unhappy users. The rating average tells you which.

Caching and stale data

The most common complaint about the lookup endpoint on the Apple Developer Forums is a version that will not update. In one thread, a developer asks why the iTunes lookup API returns an old app version after an update, and finds that changing the client cache policy does not reliably fix it.

We saw the same thing on October 9, 2026: for one app, a lookup by bundle ID returned version 26.10.11, released about an hour earlier, while a lookup by numeric ID made minutes later still returned 26.10.10 from the day before. The rating count differed too: 53,261 with country=us and 53,164 for the same lookup without a country, which also resolves to the US store. Different query strings appear to be served from different cached copies.

Design around it:

  • Do not gate a force-update prompt on a single lookup. If your app blocks users until they update, a stale answer can lock them out or skip the prompt. Use your own backend flag for minimum versions.
  • Confirm before alerting. Treat a version or rating change as real once two consecutive snapshots agree, or once the release date moves forward.
  • Use one query form consistently. Pick lookup by ID or by bundle ID and stick with it, so your history does not jump between cached copies.
  • Cache on your side. Apple asks that "large websites should set up caching logic for the search and lookup requests," and a daily snapshot is plenty for ratings.

Limits and terms to respect

Apple's documentation states the rate limit as "approximately 20 calls per minute (subject to change)", so keep a margin and back off if you start getting errors. ID-based lookups are, in Apple's words, "faster and contain fewer false-positive results" than searches.

The API was built for promoting store content, and Apple's terms on the same page cover the promotional assets it returns: artwork and previews may be used "only to promote store content," and sound samples and other assets "must be proximate to a store badge." Reading ratings and versions for your own monitoring is a common use, but if you display artwork or screenshots publicly, read those terms first.

What the iTunes Search API cannot tell you

  • Downloads and revenue. Only App Store Connect has those, and only for your own apps.
  • Written reviews. Use the public customer reviews RSS feed or the App Store Connect API. Our guide to App Store review alerts shows both, with a script that posts new reviews to Slack.
  • Ranking positions. Search order in the API is not the App Store's ranking, and chart positions come from separate feeds.
  • Google Play. There is no public equivalent for Play. For your own Android apps, our guide to Google Play Console statistics covers the official exports.

If you also publish a browser extension, the situation is similar: the Chrome Web Store has no official stats API either, and our post on the Chrome Web Store stats API explains how to collect the public listing data responsibly.

Track App Store ratings without running a scraper

A daily lookup script is a good start, but it needs a scheduler, storage, per-country handling, de-duplicated alerts and someone to fix it when Apple changes a field. Extenify does that work for you. It is a unified dashboard that records public store listing data for App Store and Google Play apps, plus Chrome, Edge and Firefox extensions, every day, keeps the history, and sends App Store rating alerts to email, Slack, Telegram, Discord or Teams when ratings, rating counts or versions change for your apps and your competitors. Tracking one listing is free, and the pricing page shows what the paid plans add. To keep those alerts useful rather than noisy, see our guide to store change alerts your team will actually read.

Frequently asked questions

Is the iTunes Search API free, and do I need an API key?

It is free and needs no key or developer account. Apple documents it on its Performance Partners site. It also has no SLA, so build your code to handle empty or changed responses.

What is the iTunes Search API rate limit?

Apple says "approximately 20 calls per minute (subject to change)." Batch several app IDs into one lookup, cache results, and spread requests over time rather than sending bursts.

Why does the rating from the API differ from what I see on the App Store?

Most often because of the country. Ratings belong to each storefront, and a lookup without country returns the US store (prices come back in USD). The App Store page also rounds to one decimal, while the API returns the unrounded average.

Why does the iTunes lookup API return an old version of my app?

Responses are cached, and different query strings can hit different cached copies. A new version can take hours to appear everywhere. Do not rely on a single lookup for update checks; confirm across snapshots or use your own backend flag.

Can I get App Store reviews or download numbers from the iTunes Search API?

No. Reviews come from the customer reviews RSS feed or the App Store Connect API, and downloads are only available to the app's developer in App Store Connect.

How do I find an app's ID?

It is the number after id in the App Store URL, for example 618783545 in apps.apple.com/us/app/slack/id618783545. You can also search by name with the search endpoint and read trackId from the result.

Summary

The iTunes Search API gives you an app's rating, rating count, version, release date and release notes for any storefront with a single unauthenticated request. Use lookups by ID for tracking and search only for discovery, always pass a country, batch IDs, stay under roughly 20 calls a minute, and treat every answer as possibly cached. Record a daily snapshot per app and country, alert only on changes that hold, and pair it with App Store Connect and the reviews feed for the numbers the API does not expose.

Image credits

Put every store in one dashboard tonight.

Sign in with Google, paste one store link, and your unified view is live in under a minute. 7 days free from your first extension, no card required, and you never touch your extension's code.

Start free