How to Scrape Google Play Store Data (incl. Python)
- To scrape Google Play Store data in Python, install the open-source
google-play-scraperpackage. Itsapp()call returns full metadata andreviews()returns 200 reviews per page plus acontinuation_token. I ran version 1.2.7 and both worked first try. - Google Play caps reviews at 200 per request. I paged with the
continuation_tokenand two calls came back with zero overlapping review IDs, for 400 unique reviews. - The official Google Play Developer API only returns reviews for apps you own, from the last week, at 200 GET requests per hour. For competitor or market data you scrape the public listing.
- These public routes have no proxy layer, so sustained paging draws
HTTP 503and a captcha. For volume across many apps and countries, a managed API like ChocoData handles the rotation and parsing for you.
I scrape Google Play Store data for competitive dashboards, and the fastest route in Python is one open-source package plus a couple of official endpoints. This guide covers the Google Play (Android) side only: app metadata, ratings, reviews, and search, each pulled from the public listing. Every snippet below is code I ran in July 2026, with the real return values, the rate limits I hit, and the point where the do-it-yourself route stops scaling. For the Apple side, I keep a separate walkthrough on how to scrape Apple App Store data.
What Google Play Store data can you scrape?
The Google Play Store data you can scrape from the public listing falls into three groups: app metadata (title, developer, rating, install count, price, category), review threads (star rating, text, author, developer reply, and the app version reviewed), and search or top-chart results. None of it needs a Google account, because it all renders on pages any visitor can open.
The catalog is large enough to justify the tooling. Business of Apps put Google Play at roughly 1.58 million apps as of September 2025, so the listings you want to track sit in a very active market. The cleanest way to pull all three groups in Python is a single package, so that is where I start. The metadata call is the simplest, which makes it a good first test before review pagination gets involved.
How do you scrape Google Play Store data in Python?
The fastest way to scrape Google Play Store data in Python is the open-source google-play-scraper package, which calls Play’s internal endpoints and hands you parsed dicts with no external dependencies. I ran version 1.2.7 on Python 3.13 and it returned data on the first call with zero configuration.
Install it:
pip install google-play-scraper
Then pull an app’s metadata by its package name (the id= value in a Play Store URL, for example com.instagram.android) with the app() function:
from google_play_scraper import app
meta = app("com.instagram.android", lang="en", country="us")
print(meta["title"], meta["score"], meta["installs"], meta["ratings"])
# In my run: Instagram 4.0059237 5,000,000,000+ 168139300
That is a single call, no token needed. The installs field is the human-readable bucket Google shows (5,000,000,000+), score is the live aggregate rating (4.0059237 in my pull), and ratings is the raw rating count, which came back as 168,139,300. The same dict also carries description, genre, developer, released, updated, version, price, and the screenshot URLs, which is the full listing surface most ASO and market jobs need. If you would rather use a wrapper that mirrors the App Store API shape, I compare the options in the app-store-scraper library guide.
How do you scrape Google Play Store reviews in Python?
To scrape Google Play Store reviews in Python, call the reviews() function with the same package name. It returns a list of review dicts and a continuation_token for paging. Here is the call I ran against Instagram:
from google_play_scraper import Sort, reviews
result, continuation_token = reviews(
"com.instagram.android",
lang="en", # defaults to "en"
country="us", # defaults to "us"
sort=Sort.NEWEST, # NEWEST or MOST_RELEVANT
count=200, # 200 is the per-page max Google serves
filter_score_with=None, # set 1-5 to fetch only one star rating
)
for r in result[:3]:
print(r["score"], r["at"].date(), "-", r["content"][:70])
When I ran this, result came back as a list of exactly 200 review dicts and continuation_token was a populated object. Each review carried these fields: userName, score, at (a Python datetime), content, thumbsUpCount, reviewId, reviewCreatedVersion, appVersion, repliedAt, replyContent, and userImage. The newest review in my pull was timestamped the day before I ran it, so the feed is current, and the replyContent field carries the developer reply when one exists.
Paging past the first 200 reviews
Google serves at most 200 reviews per request, so to go deeper you feed the continuation_token from one call into the next. The package docs state that “because the maximum number of reviews per page supported by Google Play is 200, it is designed to pagination and recrawl by 200 until the number of results reaches count.” The paging call looks like this:
from google_play_scraper import Sort, reviews
page1, token = reviews("com.instagram.android", count=200, sort=Sort.NEWEST)
page2, token = reviews(
"com.instagram.android", count=200, sort=Sort.NEWEST,
continuation_token=token,
)
ids1 = {r["reviewId"] for r in page1}
ids2 = {r["reviewId"] for r in page2}
print(len(page1), len(page2), "reviews,", len(ids1 & ids2), "overlap")
I verified the token actually advances. Page 1 and page 2 each returned 200 reviews with zero overlapping reviewId values, for 400 unique reviews across the two calls. One caveat on smaller apps: once you reach the end of the review set, the call keeps handing back a token and re-serves the same batch, so a naive loop repeats forever. I dedupe on reviewId and stop when a page adds no new IDs. There is also a reviews_all() helper that drains every review, but it has no count ceiling, so on a popular app it walks the entire history, one request per 200 reviews, which on a large app means tens of thousands of calls. I keep to explicit count pages in production.
Filtering reviews by star rating
To pull only one star rating, pass filter_score_with an integer from 1 to 5. This is how I isolate one-star reviews for a complaint analysis without downloading the whole set:
from google_play_scraper import reviews
one_star, _ = reviews("com.instagram.android", count=200, filter_score_with=1)
print(len(one_star), "one-star reviews")
The same 200-per-page cap and continuation-token paging apply to the filtered call, so a rating-specific pull scales exactly like the full one. Sorting is controlled separately by sort, where Sort.NEWEST gives you recency and Sort.MOST_RELEVANT mirrors the default order Google shows on the listing.
How do you scrape Google Play search results?
To scrape Google Play search results, use the search() function from the same package with a query term. It returns a list of app dicts, each carrying the same metadata fields as app(), which is what you want for app store optimization (ASO) research and market mapping:
from google_play_scraper import search
hits = search("photo editor", lang="en", country="us", n_hits=20)
for h in hits[:3]:
print(h["appId"], "-", h["title"], "-", h["score"])
Each result dict includes appId, title, score, installs, developer, price, and the icon URL, so a single search call resolves a keyword into a ranked list of package names you can then feed back into app() or reviews(). The package also exposes permissions() for an app’s requested Android permissions, which rounds out the public-listing surface. What none of these public calls give you is the authenticated data behind your own developer account, which is a different tool entirely.
Does the official Google Play Developer API return this data?
The official Google Play Developer API does not return public listing data, and this trips people up constantly. Its Reply to Reviews resource is scoped to apps you own and to a narrow recent window. Google’s Reply to Reviews documentation states it plainly: “You can retrieve only the reviews that users have created or modified within the last week,” and the API “allows you to access feedback only for production versions of your app.” It is also rate-limited at 200 GET requests per hour per app.
That makes the official API the right tool for exactly one job: replying to recent reviews on your own production listing. For competitor research, market scans, historical review sets, or any app you do not publish, scraping the public listing with google-play-scraper is the route that reads other apps. The catch is that the public route has no rate-limit protection of its own, which is where blocks come in.
Why does Google Play block your scraper?
Google Play blocks a scraper when it sees too many requests from one IP too fast, and it answers with an HTTP 503 and a captcha rather than the data you asked for. The maintainer of the widely used google-play-scraper project documents the failure mode: too many requests in a short period and “requests start getting status 503 responses with a captcha,” after which “the requesting IP can be banned from making further requests for a while (usually around an hour).” I reproduced it. A tight loop of listing requests from a single cloud IP began returning 503 responses within a few dozen calls.
Two walls show up first when you run the DIY route at any real volume:
- No proxy layer. The Python package sends every request from your one server IP, so once Google throttles that address you get empty pages or 503s until the ban lifts. You are back to buying and rotating residential proxies yourself.
- Dynamic JavaScript. If you skip the package and try raw
requestsplusBeautifulSoup, the listing HTML comes back as a shell, because the rating, installs, and reviews render from script blobs. That forces a headless browser like Selenium or Playwright, which is slower and heavier to maintain.
You can soften the first wall by spacing requests out, and the Node version of the library exposes a throttle option for exactly that. Throttling reduces the block rate but also caps your throughput, so past a certain volume across many apps and countries, the arithmetic favors moving the fetch layer off your machine. That is the switch most teams I have worked with eventually make.
How do you scrape Google Play Store data at scale?
To scrape Google Play Store data at scale without managing proxies, you point a managed scraper API at the app and get clean JSON back. It removes the IP rotation, the country looping, and the parser maintenance by accepting a package name and returning parsed fields. I route our pipelines through ChocoData because the request shape is the same across app metadata, reviews, and search, so one client covers the whole Play surface.
The metadata call takes the Android package name as id:
# App metadata by package name
curl "https://api.chocodata.com/api/v1/appstore/app?id=com.instagram.android&api_key=$CHOCO_API_KEY"
# A page of review threads, parsed and paged server-side
curl "https://api.chocodata.com/api/v1/appstore/reviews?id=com.instagram.android&country=us&page=1&api_key=$CHOCO_API_KEY"
# Play Store search results
curl "https://api.chocodata.com/api/v1/appstore/search?term=photo%20editor&country=us&api_key=$CHOCO_API_KEY"
The Python version is the same GET with your key as a query parameter, loaded straight into pandas for analysis:
import requests
import pandas as pd
resp = requests.get(
"https://api.chocodata.com/api/v1/appstore/reviews",
params={"id": "com.instagram.android", "country": "us", "page": 1,
"api_key": "YOUR_CHOCO_API_KEY"},
timeout=30,
)
reviews = resp.json()["data"]["reviews"]
df = pd.DataFrame(reviews)
df.to_csv("play_reviews.csv", index=False)
print(df.head())
The proxy rotation, the captcha handling, and the JSON parsing run server-side, so you are not babysitting 503s or writing selectors. Each Google Play country store has its own review set, so the same call looped over country=us, country=gb, and country=de widens coverage without any extra IP work on your side. The free tier covers 1,000 requests with no card, Pro works out to about $0.60 per 1,000 records, and you are billed only for successful requests, so retries behind a good call are not charged separately. For a one-off pull of a few hundred reviews, the Python scripts above are free and fine. For continuous collection across both stores and many countries, a managed API is the cheaper path once you count the proxy time. If you want the tool-by-tool numbers first, I benchmark the options in the best App Store scrapers of 2026.
Is it legal to scrape Google Play Store data?
Scraping public Google Play Store listings is generally treated as lawful in the US, though not without limits. In hiQ Labs v. LinkedIn the Ninth Circuit read the Computer Fraud and Abuse Act narrowly for publicly available pages, and that is the ruling most public-data scrapers lean on.
It still comes down to a contract question. Google’s Terms of Service prohibit automated access to its services, so your exposure lives in those terms rather than in hacking statutes. Stay on public listing fields, avoid collecting personal data from review authors, and get your own counsel before commercial use. I build data pipelines, I am not a lawyer, so treat this as context rather than legal advice.
Sources
- GitHub - JoMingyu/google-play-scraper (Python package:
app(),reviews(),search(),permissions(), and 200-per-page pagination) - https://github.com/JoMingyu/google-play-scraper - PyPI - google-play-scraper (the “maximum number of reviews per page supported by Google Play is 200” note and version 1.2.7) - https://pypi.org/project/google-play-scraper/
- Google Play - Reply to Reviews API (last-week window, production versions only, 200 GET requests per hour) - https://developers.google.com/android-publisher/reply-to-reviews
- GitHub - facundoolano/google-play-scraper (503 + captcha throttling and the ~1-hour IP ban) - https://github.com/facundoolano/google-play-scraper
- CourtListener - hiQ Labs v. LinkedIn docket (public-data scraping and the CFAA) - https://www.courtlistener.com/docket/4517811/hiq-labs-inc-v-linkedin-corporation/
- Google - Terms of Service (automated-access restriction) - https://policies.google.com/terms
FAQ
What is the best library to scrape Google Play Store data in Python?
The google-play-scraper package (JoMingyu, version 1.2.7) is the one I reach for first. It has no external dependencies, reads Google Play's internal endpoints, and exposes app(), reviews(), search(), and permissions(). It handles the 200-per-page pagination for you. The gplay-scraper package is a heavier alternative with more derived ASO fields, but for metadata, reviews, and search the lighter package covers most jobs.
Can you use requests and BeautifulSoup to scrape the Google Play Store?
Only partially. A Google Play listing renders much of its data through dynamic JavaScript, so a plain requests plus BeautifulSoup fetch returns a shell without the full rating, install count, or review threads, which live in shifting script blobs. That is why google-play-scraper calls Google's internal JSON endpoints instead of parsing the HTML, and why a raw HTTP scraper needs a headless browser like Selenium or Playwright to see the same fields.
How many reviews can you scrape from one Google Play app?
Google Play serves at most 200 reviews per request. To go deeper you feed the continuation_token from one reviews() call into the next and keep paging. The reviews_all() helper drains the entire review history, but it has no ceiling, so on a popular app it fires one request per 200 reviews and can run into tens of thousands of requests, which is where throttling starts.
Do you need a Google account or API key to scrape Google Play?
No account or API key is needed for the public listing. The google-play-scraper package reads pages any visitor can open, so metadata, reviews, and search come back with no login. The official Google Play Developer API is the opposite: it needs OAuth and your own developer credentials, and it only exposes apps you publish, not third-party listings.
Does google-play-scraper return install counts and exact ratings?
Yes. The app() call returns installs as the human-readable bucket Google shows (for example 5,000,000,000+), score as the live aggregate rating to several decimals, and ratings as the raw rating count. In my July 2026 run against Instagram it returned a score of 4.0059237 and 168,139,300 ratings, which is the precision you need to track small rating movements over time.