Modern, typed Google Play Store scraper client for Python. Fetch app details, search results, top lists, reviews, and search suggestions with a clean API and Pydantic models.
Based on and inspired by the original work at https://github.com/facundoolano/google-play-scraper, reworked with type hints, Pydantic models, and a simpler client API.
- Simple high-level client:
GooglePlayClient - Typed data models for responses via Pydantic:
AppDetails,AppOverview,Review - Search apps, fetch app details, list collections, reviews with pagination, and query suggestions
- Locale and country support (e.g.,
hl=en,gl=us) - Optional throttling, proxy support, and SSL verification control
- Python 3.11+
Install from PyPI:
pip install play-store-scraper-ng
Requires Python 3.11 or newer.
from google_play_scraper import GooglePlayClient
client = GooglePlayClient(country="us", lang="en")
# Fetch app details by ID
details = client.app("com.whatsapp")
print(details.title, details.score, details.installs)
# Search apps
results = client.search("todo list", num=10)
for app in results:
print(app.title, app.score)The client also supports async usage with httpx. Async methods are prefixed with 'a' (e.g., app -> aapp). All synchronous methods have an asynchronous equivalent.
import asyncio
from google_play_scraper import GooglePlayClient, Sort, Collection, Category
async def main():
client = GooglePlayClient()
# Async app details
details = await client.aapp("com.whatsapp")
print(f"App: {details.title}, Score: {details.score}")
# Async search
results = await client.asearch("photo editor", num=5)
for app in results:
print(f"Search result: {app.title}")
# Async list
top_free_games = await client.alist(
collection=Collection.TOP_FREE,
category=Category.GAME,
num=10
)
for app in top_free_games:
print(f"Top game: {app.title}")
# Async reviews
reviews, _ = await client.areviews("com.burbn.instagram", sort=Sort.NEWEST, num=5)
for r in reviews:
print(f"Review by {r.user_name}: {r.text[:50]}...")
# Async suggestions
suggestions = await client.asuggest("video")
print(f"Suggestions for 'video': {suggestions}")
if __name__ == "__main__":
asyncio.run(main())from google_play_scraper import GooglePlayClient
client = GooglePlayClient(
country="us", # default country code for requests
lang="en", # default language for responses
proxies={"https": "http://host:port"}, # optional proxies for requests.Session
throttle_requests_per_second=2, # optional rate limit
verify_ssl=True # set to False to skip SSL verification (not recommended)
)Parameters may be overridden per-call where supported (see below).
from google_play_scraper import GooglePlayClient
client = GooglePlayClient()
app = client.app("com.spotify.music", lang="en", country="us")
print(app.title)
print(app.score, app.score_text)
print(app.price, app.currency)
print(app.developer, app.developer_email)
print(app.installs, app.min_installs, app.max_installs)
print(app.updated)
print(app.screenshots[:3])Returns an AppDetails model (extends AppOverview).
from google_play_scraper import GooglePlayClient
client = GooglePlayClient()
apps = client.search("timer", num=20, price="all", lang="en", country="us")
for a in apps:
# a is AppOverview
print(a.app_id, a.title, a.score)price can be one of: "all" (default), "free", "paid".
from google_play_scraper import GooglePlayClient, Collection, Category, Age
client = GooglePlayClient()
top_free_tools = client.list(
collection=Collection.TOP_FREE,
category=Category.TOOLS,
num=50,
lang="en",
country="us",
)
for app in top_free_tools:
print(app.title, app.score)See google_play_scraper.constants for available Category, Collection, and Age values.
from google_play_scraper import GooglePlayClient, Sort
client = GooglePlayClient()
reviews, next_token = client.reviews(
app_id="com.whatsapp",
sort=Sort.NEWEST, # or Sort.RATING / Sort.HELPFULNESS
num=100, # number of reviews to fetch (up to a server-side limit)
lang="en",
country="us",
)client.reviews returns a tuple of (reviews: list[Review], next_token: str | None). To request the next page, pass the token to the next call:
from google_play_scraper import GooglePlayClient
client = GooglePlayClient()
reviews, next_token = client.reviews("com.whatsapp", num=100)
if next_token:
more_reviews, next_token = client.reviews("com.whatsapp", num=100, pagination_token=next_token)from google_play_scraper import GooglePlayClient
client = GooglePlayClient()
suggestions = client.suggest("photo ed")
print(suggestions)All return types are validated Pydantic models that are easy to consume and serialize.
AppOverview: minimal data used in lists/search (e.g.,title,app_id,score,icon,developer)AppDetails: extendsAppOverviewwith rich metadata (e.g.,description,installs,histogram,price,genre,screenshots,updated)Review: normalized review entry (score,text,user_name,thumbs_up, dates, developer reply info)
See google_play_scraper/models.py for full fields.
Import enums to control listing and sorting:
from google_play_scraper import Category, Collection, Sort, AgeCommon exceptions:
AppNotFound: App ID does not exist or could not be parsedParsingError: Unexpected response structureQuotaExceeded: Rate-limited or temporarily blocked by GoogleGooglePlayError: Base class for library errors
Handle errors explicitly:
from google_play_scraper import GooglePlayClient
from google_play_scraper import AppNotFound, GooglePlayError
client = GooglePlayClient()
try:
app = client.app("com.nonexistent.app")
except AppNotFound:
print("App not found")
except GooglePlayError as e:
print("General error:", e)- Locale/country: set defaults via
GooglePlayClient(country=..., lang=...)and override per call - Rate limiting:
throttle_requests_per_secondto avoid temporary blocking - Proxies: pass a
requests-style proxies dict (e.g.,{ "http": "http://host:port", "https": "http://host:port" }) - SSL: set
verify_ssl=Falseonly for troubleshooting
- Use conservative
throttle_requests_per_secondand caching when scraping at scale - Respect Google Play Terms of Service and robots.txt. This library is for educational and research purposes; use responsibly
- API responses and page structures can change without notice; pin versions and add monitoring
See the demo/ directory for runnable examples.
Sync demos:
demo/sync/demo_app.py— fetch app detailsdemo/sync/demo_search.py— search appsdemo/sync/demo_list.py— list collections and categoriesdemo/sync/demo_reviews.py— fetch reviews with paginationdemo/sync/demo_suggest.py— query suggestions
Async demos:
demo/async/demo_app.py— fetch app detailsdemo/async/demo_search.py— search appsdemo/async/demo_list.py— list collections and categoriesdemo/async/demo_reviews.py— fetch reviews with paginationdemo/async/demo_suggest.py— query suggestions
Run with:
python -m demo.sync.demo_app
python -m demo.async.demo_app
- PyPI: https://pypi.org/project/play-store-scraper-ng/
- Source: https://github.com/RankoR/google-play-scraper
- Issues: https://github.com/RankoR/google-play-scraper/issues
PRs and issues are welcome! Please run tests locally before submitting changes.
MIT License. See LICENSE.