# App Store & Google Play Reviews Scraper + Sentiment Analysis (`integrative_tangent/app-reviews-intelligence`) Actor

Scrape iOS App Store and Google Play reviews, then get what the reviews actually mean: sentiment per review, complaints ranked by how much they hurt, which release broke things, and a topic-by-topic comparison against competitor apps. Works in 6 languages. No login, no API key.

- **URL**: https://apify.com/integrative\_tangent/app-reviews-intelligence.md
- **Developed by:** [Luis Segura](https://apify.com/integrative_tangent) (community)
- **Categories:** Developer tools, SEO tools, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.14 / 1,000 reviews

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## App Store & Google Play Reviews — Sentiment, Topics & Competitor Comparison

Scrape iOS and Android reviews **and find out what they actually mean**: which complaint is costing you the most, which release broke things, and where competitors beat you — topic by topic.

**No login. No API key. No cookies. No headless browser.**

---

### Why this one and not a plain review scraper

Most review scrapers hand you rows of text and stop there. Then you paste 2,000 reviews into a spreadsheet and read them yourself.

This one does the reading:

| | Plain scrapers | This actor |
|---|---|---|
| Raw reviews | ✅ | ✅ |
| Sentiment per review | ❌ | ✅ |
| Topic detection (18 categories) | ❌ | ✅ |
| Complaints ranked by impact | ❌ | ✅ |
| Which release broke things | ❌ | ✅ |
| Month-over-month trend | ❌ | ✅ |
| Head-to-head vs competitors | ❌ | ✅ |
| Non-English reviews scored correctly | ❌ | ✅ 6 languages |

---

### What You Get

Three kinds of row in one dataset.

#### 1. `review` — one per review

| Field | Description |
|---|---|
| `platform` | `ios` or `android` |
| `appId`, `appName`, `storeUrl` | Which app |
| `country` | Storefront the review came from |
| `reviewId`, `userName`, `url` | Identity |
| `date` | `YYYY-MM-DD` — present on both stores in practice |
| `rating` | 1–5 stars |
| `title`, `text` | The review itself |
| `version` | App version the review was left on |
| `thumbsUp` | Helpful votes |
| `developerReply` | Developer's response (Google Play only) |
| `sentimentScore` | −5 to +5 |
| `sentimentLabel` | `positive` / `negative` / `neutral` / `mixed` |
| `sentimentTopics` | e.g. `["crashes_bugs","ads"]` |
| `sentimentLang` | Language used to score it |
| `sentimentSource` | `text` (measured from the words) or `rating` (derived from the stars) |

#### 2. `app_summary` — one per app

| Field | Description |
|---|---|
| `storeRating`, `storeRatingCount` | Lifetime store numbers |
| `sampleAvgRating`, `avgSentiment`, `negativePct` | The scraped sample |
| `ratingDistribution` | Reviews per star, 1–5 |
| `topComplaints` | **Ranked by pain, not by frequency** — with verbatim quotes |
| `topPraise` | What people love, for your store listing copy |
| `topTopics` | All topics with mentions, %, sentiment and avg stars |
| `byVersion` | Per release: reviews, stars, sentiment, % negative, top complaint |
| `byMonth` | Same, month by month |
| `worstVersion` | The release that's clearly worse than your own baseline |

#### 3. `comparison` — one row when you pass 2+ apps

| Field | Description |
|---|---|
| `apps` | Every app's rating, sentiment and % negative side by side |
| `byTopic` | Per topic: each app's mentions and sentiment, plus `bestApp` / `worstApp` |
| `weaknessesVsCompetitors` | Topics where **you** trail the best competitor, with the gap |
| `strengthsVsCompetitors` | Topics where you lead |

The **first app you list is treated as yours**. Everything after it is a competitor.

---

### Topics detected

`crashes_bugs` · `performance_speed` · `ui_ux_design` · `pricing_subscription` · `ads` · `login_account` · `customer_support` · `features_missing` · `updates_regression` · `privacy_security` · `notifications` · `battery_data` · `content_quality` · `onboarding` · `gamification_rewards` · `brand_controversy` · `content_moderation` · `effectiveness_results`

The last four were added after analyzing 1,000 live reviews and finding they were the biggest uncovered clusters — engagement mechanics (streaks, energy, lives), reputation events and review-bombing, audience-appropriateness, and whether the product actually delivers its promised outcome.

---

### How to Use It

#### Audit your own app

```json
{
  "appleAppIds": ["https://apps.apple.com/us/app/my-app/id123456789"],
  "googleAppIds": ["com.mycompany.myapp"],
  "countries": ["us", "gb"],
  "maxReviewsPerApp": 500
}
````

#### Find what to fix first — angry reviews only

```json
{
  "googleAppIds": ["com.mycompany.myapp"],
  "minRating": 1,
  "maxRating": 2,
  "maxReviewsPerApp": 300
}
```

Read `topComplaints[0]` in the summary row. That's your sprint.

#### Beat your competitors

```json
{
  "appleAppIds": ["id111111111", "id222222222", "id333333333"],
  "maxReviewsPerApp": 400,
  "compareApps": true
}
```

`weaknessesVsCompetitors` tells you exactly where you lose and to whom.

#### Scan a category you're thinking of entering

```json
{
  "searchTerm": "habit tracker",
  "searchPlatform": "both",
  "maxAppsFromSearch": 4,
  "maxReviewsPerApp": 200
}
```

Every app's top complaints in one run — that's your product gap analysis.

#### Go international

```json
{
  "googleAppIds": ["com.mycompany.myapp"],
  "countries": ["us", "es", "br", "de", "fr", "it"],
  "maxReviewsPerApp": 1200
}
```

Reviews are scored in their own language, so a Spanish 1-star reads as negative — not as noise.

***

### Sample Output

An `app_summary` row, trimmed:

```json
{
  "type": "app_summary",
  "platform": "ios",
  "appName": "My App",
  "storeRating": 3.1,
  "storeRatingCount": 5200,
  "reviewsAnalyzed": 400,
  "sampleAvgRating": 2.6,
  "negativePct": 60,
  "worstVersion": "4.0.0",
  "topComplaints": [
    {
      "topic": "crashes_bugs",
      "mentions": 240,
      "mentionPct": 60,
      "avgSentiment": -4,
      "avgRating": 1.1,
      "negativeMentions": 236,
      "painScore": 468.2,
      "sampleComplaints": [
        "Since the update it crashes every time I open it.",
        "Crashes on launch, completely unusable now."
      ]
    }
  ],
  "byVersion": [
    { "version": "4.0.0", "reviews": 240, "avgRating": 1.0, "negativePct": 100, "topComplaint": "crashes_bugs" },
    { "version": "3.2.0", "reviews": 160, "avgRating": 5.0, "negativePct": 0, "topComplaint": null }
  ]
}
```

A `comparison` row, trimmed:

```json
{
  "type": "comparison",
  "weaknessesVsCompetitors": [
    { "topic": "crashes_bugs", "gap": -5.0, "bestApp": "Rival App" },
    { "topic": "customer_support", "gap": -1.4, "bestApp": "Rival App" }
  ],
  "strengthsVsCompetitors": [
    { "topic": "pricing_subscription", "gap": 0.9, "nextBestApp": "Rival App" }
  ]
}
```

***

### Use Cases

- **Product managers** — what to fix first, backed by counts instead of the loudest tweet
- **Release triage** — `worstVersion` tells you which build regressed, before the rating tanks
- **ASO / marketing** — `topPraise` is your store-listing copy, in your users' own words
- **Competitive research** — where rivals are beaten, and on which topic
- **Due diligence** — sentiment trend of an app you're about to acquire or invest in
- **Support teams** — recurring complaints, ranked, with verbatim quotes

***

### Pricing & Cost

Pay per event. You pay for what you pull, not for compute time.

| Event | Price |
|---|---|
| Actor start | $0.00005 |
| Review scraped | $0.0002 (**$0.20 per 1,000 reviews**) |
| App intelligence report | $0.03 per app |
| Competitor comparison | $0.05 per run |

Real examples:

| What you run | Cost |
|---|---|
| 200 reviews, 1 app | **$0.07** |
| 1,000 reviews, 1 app | **$0.23** |
| 3 apps × 500 reviews + comparison | **$0.44** |
| 5,000 reviews across 6 storefronts, 1 app | **$1.03** |

Set `analyze: false` to skip the reports and pay for raw reviews only.

***

### Limitations — stated honestly

- **Apple caps its review feed at ~500 reviews per storefront.** That's Apple's limit, not ours. Apple genuinely returns a different review set per storefront, so adding `countries` is the way to a bigger sample — measured on live data, four Apple storefronts gave 400 distinct reviews with zero overlap.
- **Google Play works the opposite way: it segments by language, not by storefront.** Asking for `es` and `br` with the same language returns the identical review set. The actor maps each storefront to the language spoken there and skips any storefront whose language is already covered, and it deduplicates by review ID across the whole app — so you are never billed twice for the same review. Practically: listing 6 storefronts for an Android app that only has English reviews will still return one English sample, not six.
- **Apple's feed does not always include a review date.** In practice it usually does — a live 800-review Apple sample came back 100% dated — but it is not contractually guaranteed. When it's missing, `date` is `null` and `byMonth` stays empty; `byVersion` still works.
- **Apple's feed has no developer replies.** Google Play does, on about 16% of reviews in a live sample.
- **Not every review can be assigned a topic.** Roughly 55% of reviews in a live 1,000-review sample matched at least one topic; the rest were too short to classify. A quarter of real store reviews are seven words or fewer ("Good", "I love it", "trash"), and no keyword taxonomy can extract a theme from those. Topic coverage rises steeply with length: 16% of 60+ word reviews go untagged versus 90% of 1–3 word reviews. This matters for how you read `topComplaints` — it ranks the complaints among reviews that *said something specific*, which is the useful population anyway, but it is not a census of all negative reviews.
- **Sentiment is lexicon-based**, in English, Spanish, Portuguese, French, German and Italian. It handles negation ("never crashes" is praise) and clause breaks ("never crashes but the ads are awful" is a complaint).
- **Not every review can be scored from its words.** Plenty of real reviews carry no scorable vocabulary at all — *"Idk why i can't crate my avatar"* is a furious 1-star with nothing a lexicon can grab, and reviews in unsupported languages are the same story. Those rows are scored from the star rating instead, and `sentimentSource` says `rating` so you know. Filter on `sentimentSource == "text"` when you want only text-measured rows. Scoring them this way rather than dropping them is deliberate: leaving them out would compute every app-level average over only the dramatically-worded reviews, which skews the whole picture toward the extremes.
- **Sarcasm is not detected.** No lexicon method detects it.
- **`worstVersion` needs volume.** Version buckets under 5 reviews are ignored on purpose, so one angry user can't flag a healthy release.

***

### Legal

Reads only public review data that both stores publish openly — no login, no authentication bypass, no personal data beyond the public display name attached to each review. Review text belongs to its authors and to the store; use it in line with Apple's and Google's terms and with the privacy law in your jurisdiction.

***

### Support

Found a bug or need a field that isn't here? Open an issue on the actor's Issues tab — issues get answered.

# Actor input Schema

## `appleAppIds` (type: `array`):

Numeric App Store IDs or full store URLs. Both work: `310633997` or `https://apps.apple.com/us/app/whatsapp-messenger/id310633997`

## `googleAppIds` (type: `array`):

Package names or full store URLs. Both work: `com.whatsapp` or `https://play.google.com/store/apps/details?id=com.whatsapp`

## `searchTerm` (type: `string`):

Find apps by name instead of pasting IDs. Useful when you want to compare against competitors you can't name exactly.

## `searchPlatform` (type: `string`):

Which store to search in. Use "both" to compare the same product across iOS and Android.

## `maxAppsFromSearch` (type: `integer`):

Top N results per store. Keep it small — every extra app costs reviews.

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

Two-letter country codes, lowercase: `us`, `gb`, `de`, `es`, `br`, `fr`, `it`, `mx`. More storefronts = a bigger and more international sample. Apple caps each storefront at ~500 reviews, so adding countries is the way past that ceiling.

## `maxReviewsPerApp` (type: `integer`):

Total across all storefronts. 200 is enough to see the main themes; 500+ gives reliable per-version breakdowns.

## `minRating` (type: `integer`):

Set to 1 and max to 2 to analyze only angry reviews — the fastest way to find what to fix.

## `maxRating` (type: `integer`):

Upper bound of the star filter. Leave at 5 unless you are isolating a rating band.

## `analyze` (type: `boolean`):

Turn off to get raw reviews only, at the lowest possible cost.

## `compareApps` (type: `boolean`):

When you pass 2+ apps, adds a comparison row scoring every topic across all of them. The first app you list is treated as yours.

## `outputReviews` (type: `boolean`):

Turn off if you only want the summary and comparison rows.

## `includeReviewText` (type: `boolean`):

Turn off to keep ratings, sentiment and topics but drop the raw text.

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

Two-letter language code used for Google Play requests. Sentiment is auto-detected per review regardless of this setting.

## Actor input object example

```json
{
  "appleAppIds": [
    "https://apps.apple.com/us/app/whatsapp-messenger/id310633997"
  ],
  "googleAppIds": [],
  "searchTerm": "habit tracker",
  "searchPlatform": "both",
  "maxAppsFromSearch": 3,
  "countries": [
    "us"
  ],
  "maxReviewsPerApp": 200,
  "minRating": 1,
  "maxRating": 5,
  "analyze": true,
  "compareApps": true,
  "outputReviews": true,
  "includeReviewText": true,
  "language": "en"
}
```

# 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 = {
    "appleAppIds": [
        "https://apps.apple.com/us/app/whatsapp-messenger/id310633997"
    ],
    "googleAppIds": [],
    "countries": [
        "us"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("integrative_tangent/app-reviews-intelligence").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 = {
    "appleAppIds": ["https://apps.apple.com/us/app/whatsapp-messenger/id310633997"],
    "googleAppIds": [],
    "countries": ["us"],
}

# Run the Actor and wait for it to finish
run = client.actor("integrative_tangent/app-reviews-intelligence").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "appleAppIds": [
    "https://apps.apple.com/us/app/whatsapp-messenger/id310633997"
  ],
  "googleAppIds": [],
  "countries": [
    "us"
  ]
}' |
apify call integrative_tangent/app-reviews-intelligence --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=integrative_tangent/app-reviews-intelligence",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "App Store & Google Play Reviews Scraper + Sentiment Analysis",
        "description": "Scrape iOS App Store and Google Play reviews, then get what the reviews actually mean: sentiment per review, complaints ranked by how much they hurt, which release broke things, and a topic-by-topic comparison against competitor apps. Works in 6 languages. No login, no API key.",
        "version": "1.1",
        "x-build-id": "AtOQ1aHZT7V6JOHEC"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/integrative_tangent~app-reviews-intelligence/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-integrative_tangent-app-reviews-intelligence",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/integrative_tangent~app-reviews-intelligence/runs": {
            "post": {
                "operationId": "runs-sync-integrative_tangent-app-reviews-intelligence",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/integrative_tangent~app-reviews-intelligence/run-sync": {
            "post": {
                "operationId": "run-sync-integrative_tangent-app-reviews-intelligence",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "appleAppIds": {
                        "title": "App Store apps",
                        "type": "array",
                        "description": "Numeric App Store IDs or full store URLs. Both work: `310633997` or `https://apps.apple.com/us/app/whatsapp-messenger/id310633997`",
                        "items": {
                            "type": "string"
                        }
                    },
                    "googleAppIds": {
                        "title": "Google Play apps",
                        "type": "array",
                        "description": "Package names or full store URLs. Both work: `com.whatsapp` or `https://play.google.com/store/apps/details?id=com.whatsapp`",
                        "items": {
                            "type": "string"
                        }
                    },
                    "searchTerm": {
                        "title": "Or search by name",
                        "type": "string",
                        "description": "Find apps by name instead of pasting IDs. Useful when you want to compare against competitors you can't name exactly."
                    },
                    "searchPlatform": {
                        "title": "Search which store",
                        "enum": [
                            "both",
                            "ios",
                            "android"
                        ],
                        "type": "string",
                        "description": "Which store to search in. Use \"both\" to compare the same product across iOS and Android.",
                        "default": "both"
                    },
                    "maxAppsFromSearch": {
                        "title": "Apps to take from search",
                        "minimum": 1,
                        "maximum": 12,
                        "type": "integer",
                        "description": "Top N results per store. Keep it small — every extra app costs reviews.",
                        "default": 3
                    },
                    "countries": {
                        "title": "Storefronts",
                        "type": "array",
                        "description": "Two-letter country codes, lowercase: `us`, `gb`, `de`, `es`, `br`, `fr`, `it`, `mx`. More storefronts = a bigger and more international sample. Apple caps each storefront at ~500 reviews, so adding countries is the way past that ceiling.",
                        "default": [
                            "us"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxReviewsPerApp": {
                        "title": "Max reviews per app",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Total across all storefronts. 200 is enough to see the main themes; 500+ gives reliable per-version breakdowns.",
                        "default": 200
                    },
                    "minRating": {
                        "title": "Minimum stars",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "integer",
                        "description": "Set to 1 and max to 2 to analyze only angry reviews — the fastest way to find what to fix.",
                        "default": 1
                    },
                    "maxRating": {
                        "title": "Maximum stars",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "integer",
                        "description": "Upper bound of the star filter. Leave at 5 unless you are isolating a rating band.",
                        "default": 5
                    },
                    "analyze": {
                        "title": "Run sentiment & topic analysis",
                        "type": "boolean",
                        "description": "Turn off to get raw reviews only, at the lowest possible cost.",
                        "default": true
                    },
                    "compareApps": {
                        "title": "Compare apps head to head",
                        "type": "boolean",
                        "description": "When you pass 2+ apps, adds a comparison row scoring every topic across all of them. The first app you list is treated as yours.",
                        "default": true
                    },
                    "outputReviews": {
                        "title": "Include individual review rows",
                        "type": "boolean",
                        "description": "Turn off if you only want the summary and comparison rows.",
                        "default": true
                    },
                    "includeReviewText": {
                        "title": "Include review text",
                        "type": "boolean",
                        "description": "Turn off to keep ratings, sentiment and topics but drop the raw text.",
                        "default": true
                    },
                    "language": {
                        "title": "Google Play language",
                        "type": "string",
                        "description": "Two-letter language code used for Google Play requests. Sentiment is auto-detected per review regardless of this setting.",
                        "default": "en"
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
