Apify actor · whoareyouanas/app-store-google-play-review-scraper
App Store & Google Play Reviews Scraper
Collect public Apple App Store and Google Play reviews with original text, ratings, dates, available versions, developer replies, and app context. Compare product feedback while preserving each store's field semantics.
Documentation checked 2026-10-29 · deployed build 0.1.7 · run through your Apify account
01 / Overview
Match the actor to the job.
Two app stores
Supply iOS and Android app URLs or IDs in one research input.
Filter the review sample
Use storefronts, languages, ratings, dates, keywords, versions, and reply filters.
Keep collection context
Retain app metadata, source payloads, and a collection report for coverage checks.
02 / Input
Start with a clear, bounded input.
apps is required. maxReviews is a total cap, while maxReviewsPerAppCountry applies per app/storefront context. Scanned-review and request limits bound filtering work independently of the delivered count.
{
"apps": [
"https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
"https://play.google.com/store/apps/details?id=com.whatsapp"
],
"countries": [
"us"
],
"languages": [
"en"
],
"maxReviewsPerAppCountry": 10,
"maxReviews": 10,
"includeAppMetadata": true,
"includeRawData": true
}Replace example targets and credential placeholders before running. These are documentation examples, not a promise of currently available source results.
| Field | Type / required | Default | Purpose |
|---|---|---|---|
| apps | arrayRequired | Not specified | Required, nonempty array. Apple numeric app IDs (310633997), Android package names (com.whatsapp) or HTTPS apps.apple.com/play.google.com URLs. Both stores can be mixed. App discovery by search/name is not supported. |
| countries | array | Not specified | Two-letter codes. Overrides URL countries when supplied; otherwise URL country or US is used. |
| languages | array | Not specified | Each language is a separate request context. Defaults to the Play URL language or English. It does not translate text or identify its actual language. |
| sort | string | "newest" | Sort within each source context. The combined dataset is not globally date sorted. Options: newest, mostHelpful |
| maxReviews | integer | 10000 | Unique exported reviews across all apps; 0 means no result ceiling. Minimum: 0 · Maximum: 100000000 |
| maxReviewsPerAppCountry | integer | 1000 | Unique emitted rows attributed to each context. Duplicates do not consume the cap. 0 means no result ceiling. Minimum: 0 · Maximum: 100000000 |
| includeAppMetadata | boolean | true | Store app profiles, rating histograms and available source metadata in the run key-value store. Metadata is not a charged review row. |
| includeRawData | boolean | true | Preserves original review payloads and app metadata sections, including unmapped fields. Increases export size. |
All other input controls (15)
| Field | Type / required | Default | Purpose |
|---|---|---|---|
| ratings | array | [1,2,3,4,5] | Keep any listed star rating. Other filters combine with AND. |
| dateFrom | string | Not specified | YYYY-MM-DD or ISO timestamp with timezone. Compared with sourceDate, which may be an edit date. |
| dateTo | string | Not specified | Inclusive YYYY-MM-DD UTC day or ISO timestamp with timezone. |
| keywords | array | Not specified | Case-insensitive title/body match; any listed keyword matches. Searches retrieved candidates within the work limits. |
| appVersions | array | Not specified | Exact versions attached to source reviews. Apple catalog versions may be unavailable outside the finite RSS enrichment window. |
| replyFilter | string | "all" | RSS cannot determine reply status. Unsupported collection is reported as a source error, rather than an empty export. Options: all, withReply, withoutReply |
| appleSource | string | "auto" | Auto uses deeper catalog pagination and discloses any limited RSS fallback. Catalog mode fails visibly if catalog becomes unavailable. Options: auto, catalog, rss |
| enrichAppleReviews | boolean | true | Fetch up to ten RSS pages to add available source versions and vote counts to catalog reviews. Includes additional requests. |
| maxReviewsScannedPerAppCountry | integer | 100000 | Counts examined candidates, including duplicates and filter rejects. Must be at least the per-context review cap; 0 removes this ceiling. Minimum: 0 · Maximum: 100000000 |
| maxRequestsPerAppCountry | integer | 10000 | Counts metadata, enrichment, page requests and retries. 0 removes this ceiling. Endpoint exhaustion still does not prove complete historical coverage. Minimum: 0 · Maximum: 100000000 |
| maxConcurrency | integer | 3 | Independent app/country/language contexts. Continuation pages within each context run sequentially. Minimum: 1 · Maximum: 10 |
| requestIntervalMillis | integer | 350 | Shared per-host delay. Apple metadata lookups have an additional 3-second spacing. Minimum: 0 · Maximum: 60000 |
| requestTimeoutSecs | integer | 30 | Timeout applied to each HTTP attempt. Minimum: 1 · Maximum: 120 |
| maxRetries | integer | 3 | Bounded backoff for throttling and transient failures. Permanent errors and parser changes fail visibly. Minimum: 0 · Maximum: 8 |
| proxyConfiguration | object | {"useApifyProxy":false} | Optional proxy configuration, applied to all source and metadata requests. Direct requests are the default. |
03 / Output
Know what each returned row represents.
- Rows retain store/app identity, review text, rating, source date and date semantics, available version, helpful-vote context, and developer replies.
- Current app version is not automatically the version reviewed. Store-specific missing values remain missing; inspect the collection report and raw payload when reconciling fields.
{
"schemaVersion": 1,
"store": "google_play",
"appId": "com.example.notes",
"appName": "Example Notes",
"appUrl": "https://play.google.com/store/apps/details?id=com.example.notes",
"developerName": "Example Developer",
"appRating": 4.2,
"appRatingCount": 12500,
"reviewId": "demo-review-001",
"reviewKey": "google_play:com.example.notes:demo-review-001",
"rating": 2,
"title": null,
"text": "Sync stopped working after the latest update.",
"sourceDate": "2026-10-12T09:00:00.000Z",
"sourceDateType": "unspecified",
"scrapedAt": "2026-10-14T09:00:00.000Z",
"country": "us",
"language": "en",
"appVersion": "3.2.1",
"reviewerName": "Example Reviewer",
"reviewerUrl": null,
"reviewerImage": null,
"helpfulCount": 7,
"voteCount": null,
"voteMetric": "thumbs_up",
"developerReplyStatus": "present",
"replyId": null,
"replyText": "Please contact support so we can investigate.",
"replyDate": "2026-10-13T10:00:00.000Z",
"replyDateType": "unspecified",
"isEdited": null,
"reviewUrl": "https://play.google.com/store/apps/details?id=com.example.notes&reviewId=demo-review-001",
"reviewTags": [],
"source": "google_play_rpc",
"sources": [
"google_play_rpc"
],
"fieldSources": {
"reviewId": "google_play_rpc",
"rating": "google_play_rpc",
"text": "google_play_rpc",
"sourceDate": "google_play_rpc",
"reviewerName": "google_play_rpc",
"appVersion": "google_play_rpc",
"helpfulCount": "google_play_rpc",
"replyText": "google_play_rpc",
"replyDate": "google_play_rpc"
}
}Example values illustrate the published contract. Available fields and populated values depend on the source, mode, and result status.
Fields in the documented output view
store
Store
appName
App
appId
App ID
country
Requested country
language
Requested language
rating
Stars
title
Title
text
Review
sourceDate
Source date
sourceDateType
Date meaning
appVersion
Review version
developerReplyStatus
Reply status
replyText
Developer reply
replyDate
Reply date
helpfulCount
Vote metric
voteCount
Vote count
voteMetric
Vote meaning
reviewerName
Reviewer
reviewId
Source review ID
source
Source
reviewUrl
Review link
Output views select columns. They do not necessarily filter record types or exhaust the full JSON payload. Use structured JSON when you need nested arrays or objects.
Dataset links and run artifacts (6)
- Full review dataset (JSON)
- URL returning exported review objects: app/store identity, star rating, original text, source date, available review version, reviewer fields, votes, developer reply, provenance and optional sourceData. Use offset/limit to paginate large exports. No global date sort across apps. A null value means unavailable; country/language are request context.
- First 20 reviews for AI inspection
- URL returning at most 20 rows with core review and reply fields, excluding large original payloads. A preview of the existing dataset; it does not change collection or create new review charges. Read the full dataset with pagination for complete analysis.
- Core review fields (CSV)
- URL exporting the reviews table view as CSV. This view selects core fields; full JSON also preserves provenance, reviewer details, tags and original source payloads.
- Collection and quality report
- URL returning SUMMARY: total unique reviews, failed contexts and per-app/country/language candidates scanned, requests, duplicates, source, field coverage, warnings, errors, date bounds and stop reasons. Always inspect before claiming complete coverage. historicalCompleteness is not_guaranteed.
- App metadata index
- URL returning APPS as {apps:[{store,appId,country,language,key}]}. Each key identifies one APP_ JSON profile in this same key-value store. Fetch /records/{key} for full metadata. Empty when metadata is disabled or unavailable. Profiles are separate from charged review rows.
- List app profile record keys
- URL listing APP_ record keys in the appProfiles collection. Fetch /records/{key} from the same key-value store for each profile. Use the APPS index for store, app and requested locale context.
04 / Pricing
Understand the billable unit.
These are the active public event prices checked on 2026-10-29, in USD. They describe each event, not a universal flat price for a run. Confirm your current Apify plan and run budget before starting.
| Billable event | Rate (USD) | When it applies |
|---|---|---|
Actor Start apify-actor-start | $0.00005 / event | Charged when the Actor starts running. Number of events charged depends on Actor memory (one event per GB, minimum one event). Start units depend on allocated memory: one event per GB, with at least one event. |
result apify-default-dataset-item | $0.001 / event | Single result in the default dataset. $1.00 per 1,000 of this event. Other events and separate services are additional. |
- Use the configured result-event rate and separate startup event below.
- Tighter filters can scan more source pages than the number of delivered reviews suggests. Keep request and scan bounds explicit.
A result limit and a spending cap are different controls. Account charges, applicable taxes, and separately billed providers or proxies must be considered where relevant. A cap setting is not a minimum invoice charge.
05 / API & automation
Use the same input from your workflow.
Test a small run in Apify Console, inspect its records and charges, then save a task or call the actor from your own application. Keep your Apify token in an environment variable. Source-specific credentials, if required, are separate from the Apify API token.
# Save the input example as input.json and set APIFY_TOKEN.
# This request starts an asynchronous, potentially billable run.
curl --request POST \
'https://api.apify.com/v2/acts/whoareyouanas~app-store-google-play-review-scraper/runs' \
--header "Authorization: Bearer $APIFY_TOKEN" \
--header 'Content-Type: application/json' \
--data @input.jsonThe response identifies the run. Wait for it to finish, inspect its status, and use its default dataset and key-value store to retrieve results. A successful run can still contain partial or failed records; check the output contract above before continuing downstream.
Coverage & interpretation
Check the result before relying on it.
- Storefront and language context can affect which reviews are exposed; cross-store rows are not identical source contracts.
- The actor collects feedback, not verified user demographics, sentiment scores, or a complete app-review history guarantee.
Questions
Before you build an integration.
What do I need to provide?
apps is required. maxReviews is a total cap, while maxReviewsPerAppCountry applies per app/storefront context. Scanned-review and request limits bound filtering work independently of the delivered count.
What should I check in the output?
- Rows retain store/app identity, review text, rating, source date and date semantics, available version, helpful-vote context, and developer replies.
- Current app version is not automatically the version reviewed. Store-specific missing values remain missing; inspect the collection report and raw payload when reconciling fields.
How do I budget the run?
- Use the configured result-event rate and separate startup event below.
- Tighter filters can scan more source pages than the number of delivered reviews suggests. Keep request and scan bounds explicit.
Keep exploring