Skip to main content

App Reviews

Fetch reviews, search apps, and look up metadata from the Apple App Store and Google Play Store.

PyPI Python Downloads License

CI E2E Docs

Documentation · PyPI · Contributing


Why App Reviews?

Apple and Google use completely different APIs, formats, and auth methods. App Reviews handles all of this behind a simple Python API -- no API keys required.

from app_reviews import AppStoreSearch, GooglePlayReviews, Country

# Search for apps
results = AppStoreSearch().search("whatsapp", country=Country.US, limit=5)
print(results[0].name, results[0].icon_url)

# Fetch reviews
reviews = GooglePlayReviews().fetch("com.whatsapp", countries=[Country.US])
for review in reviews:
    print(f"{review.rating}* {review.body[:80]}")

Highlights

Both stores Apple App Store + Google Play in one package
Search & lookup Find apps by keyword, look up metadata by ID
No API keys Works out of the box using public endpoints
155 countries Fetch across regions in a single call
Official APIs Optionally use App Store Connect or Google Play Developer API
Export JSON, JSONL, CSV
Minimal deps Just cryptography for JWT + stdlib urllib

Install

pip install app-reviews

Or with uv:

uv add app-reviews

Quick Start

Apple App Store

from app_reviews import AppStoreReviews, Country

client = AppStoreReviews()
result = client.fetch("324684580", countries=[Country.US, Country.GB])

for review in result:
    print(f"[{review.country}] {review.rating}* {review.title}")

Google Play Store

from app_reviews import GooglePlayReviews, Country

client = GooglePlayReviews()
result = client.fetch("com.instagram.android", countries=[Country.US])

for review in result:
    print(f"[{review.country}] {review.rating}* {review.body[:80]}")

Review

fetch() returns a FetchResult containing Review objects:

Field Type Description
id str Raw identifier assigned by the source (see below)
store Store "appstore" or "googleplay"
app_id str App Store ID or package name
country str Two-letter country code
rating int Star rating (1 -- 5)
title str Review title (may be empty for Google Play)
body str Review text
author_name str Reviewer display name
app_version str | None App version at time of review
created_at datetime When the review was posted
updated_at datetime | None When the review was last edited
is_edited bool Whether the review was edited
source Source Provider (e.g. "appstore_scraper", "googleplay_official")
language str | None Review language code
fetched_at datetime | None When the review was fetched

Review IDs

id is the raw identifier assigned by the source, passed through unchanged. Treat it as unique within a (store, source) pair rather than globally, use source to tell provenance apart, and key any deduplication on (store, source, id).

Ids are not necessarily comparable across sources. On the App Store they definitely differ -- RSS ids are numeric while Connect ids are opaque, with no mapping between them -- so the same review fetched via appstore_scraper and appstore_official carries two different ids. Google Play appears to use a single identifier space for both providers.

For App Store Connect specifically, customerReviewResponses requires a Connect customerReviews.id. RSS ids are numeric and Connect ids are opaque, with no mapping between them, so an appstore_scraper id cannot be used to reply.


Search & Lookup

Find apps by keyword and look up app metadata -- no authentication required.

Search

from app_reviews import AppStoreSearch, GooglePlaySearch, Country, AppMetadata

# App Store -- returns list[AppMetadata]
results: list[AppMetadata] = AppStoreSearch().search("fitness tracker", country=Country.US, limit=10)
for app in results:
    print(f"{app.name} by {app.developer} ({app.rating}*)")

# Google Play -- returns list[AppMetadata]
results: list[AppMetadata] = GooglePlaySearch().search("fitness tracker", country=Country.US, limit=10)
for app in results:
    print(f"{app.name} by {app.developer}")

Lookup

# Look up by bundle ID (App Store) or package name (Google Play)
# Returns AppMetadata | None
app = AppStoreSearch().lookup("com.burbn.instagram")
if app:
    print(f"{app.name} - {app.icon_url}")

app = GooglePlaySearch().lookup("com.whatsapp")
if app:
    print(f"{app.name} - {app.rating}*")

AppMetadata

Both search() and lookup() return AppMetadata objects:

Field Type Description
app_id str Bundle ID (App Store) or package name (Google Play)
name str App display name
developer str Developer or publisher name
category str Primary category (e.g. "Social Networking")
price str Formatted price (e.g. "Free", "$4.99")
version str Current version string
rating float Average star rating (0.0 -- 5.0)
rating_count int Total number of ratings
url str Store page URL
icon_url str | None App icon image URL

Authentication (Optional)

For higher limits and more data, use the official APIs with your developer credentials.

Apple App Store Connect

Requires an Apple Developer Program membership ($99/year).

from app_reviews import AppStoreReviews, AppStoreAuth, Country

auth = AppStoreAuth(
    key_id="ABC123DEF4",
    issuer_id="12345678-1234-1234-1234-123456789012",
    key_path="/path/to/AuthKey.p8",
)

client = AppStoreReviews(auth=auth)
result = client.fetch("324684580", countries=[Country.US, Country.GB])
Google Play Developer API

Requires a Google Play Developer account ($25 one-time).

from app_reviews import GooglePlayReviews, GooglePlayAuth, Country

auth = GooglePlayAuth(service_account_path="/path/to/service-account.json")

client = GooglePlayReviews(auth=auth)
result = client.fetch("com.instagram.android", countries=[Country.US])

Advanced Usage

Retry and proxy
from app_reviews import AppStoreReviews, RetryConfig

retry = RetryConfig(
    max_retries=5,       # default: 3
    backoff_factor=1.0,  # default: 0.5
    timeout=60.0,        # default: 30.0
    retry_on=[429, 503], # default: [500, 502, 503, 504, 429]
)

client = AppStoreReviews(retry=retry, proxy="http://proxy.example.com:8080")
result = client.fetch("324684580", countries=["us"])
Export results
from app_reviews import GooglePlayReviews
from app_reviews.exporters.json import export_json
from app_reviews.exporters.csv import export_csv
from app_reviews.exporters.jsonl import export_jsonl

client = GooglePlayReviews()
result = client.fetch("com.instagram.android")

export_json(result.reviews)   # JSON array string
export_csv(result.reviews)    # CSV string with headers
export_jsonl(result.reviews)  # one JSON object per line

Limitations

  • Free scrapers have limits:

    • App Store RSS: ~500 most recent reviews.
    • Google Play scraper: rate-limited and may not return all reviews.
  • No historical data:

    • Only the most recent reviews from public endpoints
  • Official APIs require developer accounts:

    • Apple ($99/year), Google ($25 one-time)

Documentation

Read the full docs includes guides on the Python API, authentication, export formats, and architecture.


Contributing

git clone https://github.com/firattamurcw/app-reviews.git
cd app-reviews
uv sync --group dev
make test

See CONTRIBUTING.md · Security Policy


Acknowledgements

The Google Play scraping logic (parsing AF_initDataCallback datasets, field index paths) is based on the work done in google-play-scraper by JoMingyu. We re-implemented it on top of our own HTTP layer to support retries and proxies, but the data-structure knowledge originates from that project.


License

MIT

Metadata

Release files for app-reviews 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for app-reviews 0.5.0
File Size Uploaded
app_reviews-0.5.0.tar.gz 141.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for app-reviews 0.5.0
File Interpreter ABI Platform
app_reviews-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 186.0 kB

Release files / app_reviews-0.5.0.tar.gz

Download URL app_reviews-0.5.0.tar.gz
Size 141.6 kB
Tags Source
SHA-256 checksum
How to use checksums
f75d77bc9c5fcdf6704fa01813cec63c0555388b83c31a118c7188146421a11f
BLAKE2b-256 checksum
How to use checksums
1e9fbe7d928bfa66201e44222d60be27d59a40b8f7214cefd61c2b2408d6811d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.

Transparency log

Release files / app_reviews-0.5.0-py3-none-any.whl

Download URL app_reviews-0.5.0-py3-none-any.whl
Size 44.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
28946935d52b485dbccb6b91d6b2363ee289465452eda9e1b2fd75b7b8cba17a
BLAKE2b-256 checksum
How to use checksums
417161ef447bc4c2e8122afa1edf91875ba9d5fb64ef468c745ce5e1b14bfe05
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.

Transparency log

Release history Release notifications | RSS feed

1.2.0

2 release files

1.1.0

2 release files

1.0.0

2 release files

0.6.0

2 release files

This release

0.5.0 This release

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page