# App Revenue & Downloads Estimator: App Store & Google Play (`steadyscrape/app-revenue-downloads-estimator`) Actor

Estimate app downloads and revenue for App Store and Google Play apps: Google Play's exact install count, installs gained between runs, App Store chart ranks, ratings and in-app purchase prices, with low/mid/high bands and the method. Export to JSON, CSV or Excel, or via API.

- **URL**: https://apify.com/steadyscrape/app-revenue-downloads-estimator.md
- **Developed by:** [Steady Scrape](https://apify.com/steadyscrape) (community)
- **Categories:** Developer tools, Business, SEO tools
- **Stats:** 4 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 app estimates

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/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

## App Revenue & Downloads Estimator: App Store & Google Play

**App Revenue & Downloads Estimator** gives you monthly download and revenue estimates for any App Store or Google Play app,
built from what the stores publish and nothing else: **Google Play's exact lifetime install count** (the page shows
"50M+", the data behind it says 70,564,050), installs gained between your runs, App Store top chart positions, ratings,
prices and in-app purchase prices. Every estimate comes as a **low / mid / high band** with the method and the numbers
it rests on written out, so you can check it, recompute it or throw it away. Export to JSON, CSV or Excel, or via API.

This is an unofficial tool. It is not affiliated with, endorsed by or connected to Apple, Google or any app intelligence
company. The estimates are estimates from public store signals, not Apple's or Google's data; only Google Play's install
count is a store number.

### What the app downloads and revenue estimator returns

One row per app and country:

- **Google Play exact installs**: the lifetime count Google keeps behind the "10M+" bucket, worldwide, and its average a day since release.
- **Installs and ratings gained since your last run** (turn on *Track changes*): measured, not modelled. Run it weekly and you get a real downloads-per-day series for any Google Play app.
- **App Store chart positions**: the app's place in the top 200 free or paid iPhone chart of all apps (or all games) and of its category, in every country you ask, plus the chart badge on its page.
- **Google Play chart badge**: "#6 top grossing in Health & Fitness", "#1 top paid in Arcade", when Google shows one.
- **Prices and in-app purchases**: the App Store's top in-app purchases with their prices, Google Play's in-app price range, and a typical price.
- **Ratings**: count, average and the 1–5 star histogram.
- **Estimated monthly downloads** (low, mid, high, method, basis) and every other method that applied, in `downloadEstimates`.
- **Estimated monthly revenue** (gross) and **proceeds** after the store's fee, in the store's currency for that country.

### Use cases

- **App market research**: size a category or a competitor before you build, from the top charts down.
- **Competitor tracking**: schedule a weekly run with *Track changes* and watch a rival's Google Play installs a week.
- **UA and ASO teams**: see where an app ranks in each country and what that rank means in downloads.
- **Investors and acquirers**: a first, transparent read on an app's scale before buying data or asking for metrics.
- **App lists**: estimate the top 200 free or paid apps of any App Store chart in one run.

### How to estimate app downloads and revenue

1. Add apps: App Store links or ids (`https://apps.apple.com/us/app/calm/id571800810`, `571800810`) and Google Play links
   or package names (`https://play.google.com/store/apps/details?id=com.calm.android`, `com.calm.android`).
2. Pick countries (two-letter codes, `us` by default).
3. Optionally pick an App Store chart (for example *All Games*, *Top free*, 100 apps).
4. Optionally turn on *Track changes* and schedule the run.

#### Input example

```json
{
    "apps": ["https://play.google.com/store/apps/details?id=com.calm.android", "https://apps.apple.com/us/app/calm/id571800810"],
    "countries": ["us"],
    "appStoreChart": "6014",
    "chartType": "top-free",
    "chartLimit": 100,
    "trackChanges": false
}
```

#### Output example

A Google Play row (shortened):

```json
{
    "status": "ok",
    "store": "googlePlay",
    "appId": "com.calm.android",
    "country": "us",
    "name": "Calm - Sleep, Meditate, Relax",
    "price": 0,
    "currency": "USD",
    "inAppPurchases": { "minPrice": 0.99, "maxPrice": 399.99, "typicalPrice": 19.9, "priceRange": "$0.99 - $399.99 per item", "items": [] },
    "ratingCount": 616843,
    "releasedAt": "2014-07-31T05:50:57.000Z",
    "installs": { "exact": 70564050, "bucket": "50,000,000+", "minimum": 50000000, "averagePerDay": 15772.03 },
    "chartPositions": [{ "chart": "top-grossing", "genre": "health & fitness", "genreId": null, "position": 6, "source": "googlePlayPage" }],
    "changes": null,
    "estimatedMonthlyDownloads": {
        "low": 384049,
        "mid": 960122,
        "high": 1680214,
        "method": "lifetimeInstalls",
        "scope": "worldwide",
        "basis": "Google Play's exact count of 70,564,050 installs over 4,474 days since release is 15,772 a day on average; recent months run at 0.8×–3.5× (mid 2×) the lifetime average, as measured on 10 large Google Play apps."
    },
    "estimatedMonthlyRevenue": { "low": 152851.5, "mid": 1337449.95, "high": 8359064.65, "currency": "USD", "method": "inAppPurchases", "basis": "…" },
    "estimatedMonthlyProceeds": { "low": 106996.05, "mid": 936214.96, "high": 7105204.95, "currency": "USD", "basis": "…" },
    "notes": ["Google Play counts installs worldwide: the revenue estimate prices every download at this country's price."]
}
```

An app that cannot be read is a free row: `{ "status": "notFound" | "notSoldInCountry" | "blocked", "store", "appId", "country", "message" }`
(`notSoldInCountry` also covers a Google Play page without an offer: pre-registration, or not released there yet). An entry
that is not an app id, package name or store link is one free row `{ "status": "invalidApp", "input", "message" }`, and the
other apps still run.

### Output fields

| field | what it is |
|---|---|
| `status` | `ok` for an estimate; `notFound`, `notSoldInCountry`, `blocked` or `invalidApp` for a free row with a `message` |
| `store`, `appId`, `url`, `country`, `countryName` | which app, where |
| `name`, `developer`, `icon`, `genre`, `genreId` | the listing |
| `price`, `currency`, `free` | the price in that country's store |
| `containsAds` | Google Play's "Contains ads" (null on the App Store, which does not say) |
| `hasInAppPurchases`, `inAppPurchases` | `minPrice`, `maxPrice`, `typicalPrice`, Google Play's `priceRange` text, the App Store's `items` (name, price, priceValue) |
| `rating`, `ratingCount`, `ratingHistogram` | ratings in that storefront (App Store) or worldwide (Google Play) |
| `releasedAt`, `updatedAt`, `ageDays` | release, last update, days since release |
| `installs` | Google Play only: `exact` lifetime installs, `bucket`, `minimum`, `averagePerDay` |
| `chartPositions` | `chart` (top-free, top-paid, top-grossing), `genre`, `genreId`, `position`, `source` |
| `changes` | with *Track changes*: `previousRunAt`, `days`, `installsGained`, `installsPerDay`, `ratingsGained`, `ratingsPerDay` |
| `estimatedMonthlyDownloads` | `low`, `mid`, `high`, `method`, `scope` (worldwide or country), `basis` |
| `downloadEstimates` | every method that applied, best first |
| `estimatedMonthlyRevenue` | gross store sales a month: `low`, `mid`, `high`, `currency`, `method`, `basis` |
| `estimatedMonthlyProceeds` | what the developer keeps after the store's fee |
| `notes` | what is missing or assumed for this row |

### How the estimates are made

Downloads, best method first:

| method | store | how |
|---|---|---|
| `installsDelta` | Google Play | Measured: exact installs gained since your previous run ÷ days. Google updates its count in steps, so windows under 7 days get a 0.5×–2× band. |
| `lifetimeInstalls` | Google Play | Exact installs ÷ days since release, times 0.8×–3.5× (mid 2×): the ratio of the last 13 months to the lifetime average, measured on 10 large apps from their exact counts a year apart (Clash of Clans 0.8×, Calm 1.06×, Duolingo 2.7×, Minecraft 3.5×). Apps under a year old: 0.5×–2×. |
| `chartRank` | App Store, US | The app's position in the US top free or top paid chart of all apps (or all games) on the rank–demand power law (Garg & Telang, MIS Quarterly 2013), anchored at ~156,000 downloads a day for #1 and ~52,000 for #10 of the free apps chart, half that for games (Sensor Tower, 2022), and ~4,000 for #10 paid (Distimo, 2013, scaled down 0.25–1×). An app only in its category chart is mapped onto the whole chart through the apps in both. |
| `ratingsDelta` | App Store | Ratings gained since your previous run, at 2–10 % (mid 5 %) ratings per download. |
| `lifetimeRatings` | App Store | Ratings in that storefront ÷ 2–10 % ratings per download, averaged over the app's life, times the recent-to-lifetime ratio above. |

Revenue: each paid download pays its price, plus in-app revenue per download of 2–25 % (mid 7 %) of the typical in-app
price, renewals and repeat purchases included (a subscription leader like Duolingo, with 2025 bookings guided past
US$1B on ~16.5M Google Play installs a month, sits near the top). Proceeds keep 70–85 % of that after the store's fee.
Ad revenue is not estimated.

Every number above is in each row's `basis`, so a row can always be read on its own.

### Limits

- **These are estimates**, built from public signals. The bands are wide on purpose; the method tells you how much to trust each one. Only Google Play's install count is a store number.
- Google Play counts installs **worldwide**; a Google Play revenue estimate prices every download at the price of the country you asked.
- Chart-rank estimates are made for the **US** only, where the published anchors are; elsewhere chart positions are listed and downloads come from ratings.
- Apple shows only top free and top paid charts on the web, so there are **no top grossing ranks** for the App Store.
- The App Store's charts go 200 deep; an app outside them gets its downloads from ratings.
- Pacing is one request a second per store; 100 App Store apps take about two minutes.

### Pricing

US$0.003 per app estimate (one app in one country). Apps not found, not sold in that country, not read because a
store refused, and entries that are not apps are free rows.

### Is it legal?

The Actor reads public store pages any visitor sees, without logging in, at a polite pace, and only the paths the stores'
robots.txt allows. It reads no personal data. Check that your use of the results complies with the stores' terms and the
laws that apply to you.

### FAQ

**Why a band and not one number?** Because no public signal gives one number. A band with its method is honest; a
single figure from an unknown model is not.

**How do I get measured downloads?** Turn on *Track changes* and schedule the Actor (weekly works best). From the second
run on, Google Play apps carry `installsDelta`: the installs Google itself counted between your runs.

**Can I use my own assumptions?** Yes: every row carries the raw signals (exact installs, ratings, chart positions,
prices), so you can apply your own ratios in a spreadsheet.

# Actor input Schema

## `apps` (type: `array`):

App Store links or app ids ("https://apps.apple.com/us/app/calm/id571800810", "571800810") and Google Play links or package names ("https://play.google.com/store/apps/details?id=com.calm.android", "com.calm.android"). One estimate per app and country.

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

Two-letter country codes ("us", "gb", "de", "jp"…). App Store ratings, charts and prices are per country; Google Play installs are worldwide and its prices per country. Downloads from chart ranks are estimated in the US only, where the published anchors are.

## `appStoreChart` (type: `string`):

Also estimate the top apps of an App Store iPhone chart in each country, e.g. the top 100 free games in the US.

## `chartType` (type: `string`):

Top free or top paid. Apple shows no top grossing chart on the web.

## `chartLimit` (type: `integer`):

How many of the chart's top apps to estimate, 1 to 200.

## `trackChanges` (type: `boolean`):

Remember each app's install and rating counts, and on the next run report what it gained since: measured Google Play installs a day, App Store ratings a day, and downloads from them. Run it on a schedule (weekly is best: Google updates its count in steps). Uses a key-value store named steadyscrape-app-revenue-downloads-estimator-state in your account.

## Actor input object example

```json
{
  "apps": [
    "https://play.google.com/store/apps/details?id=com.calm.android",
    "https://apps.apple.com/us/app/calm/id571800810"
  ],
  "countries": [
    "us"
  ],
  "appStoreChart": "",
  "chartType": "top-free",
  "chartLimit": 25,
  "trackChanges": false
}
```

# Actor output Schema

## `estimates` (type: `string`):

No description

## `summary` (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 = {
    "apps": [
        "https://play.google.com/store/apps/details?id=com.calm.android",
        "https://apps.apple.com/us/app/calm/id571800810"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("steadyscrape/app-revenue-downloads-estimator").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 = { "apps": [
        "https://play.google.com/store/apps/details?id=com.calm.android",
        "https://apps.apple.com/us/app/calm/id571800810",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("steadyscrape/app-revenue-downloads-estimator").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 '{
  "apps": [
    "https://play.google.com/store/apps/details?id=com.calm.android",
    "https://apps.apple.com/us/app/calm/id571800810"
  ]
}' |
apify call steadyscrape/app-revenue-downloads-estimator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,steadyscrape/app-revenue-downloads-estimator"
        }
    }
}
```

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/Me5KHbrPZU6ND0sGH/builds/3fZO6yfctYG7VqfWr/openapi.json
