Open-source project
gaspa93/googlemaps-scraper avatar
gaspa93/googlemaps-scraper

googlemaps-scraper pulls the newest Google Maps reviews from a list of place URLs

Google Maps reviews scraping

528 stars163 forksPythonGPL-3.0

At a glance

What is it?
googlemaps-scraper is a Selenium based Python script that takes a file of Google Maps place review URLs, extracts the most recent reviews into a CSV, and has a companion monitor script that stores new reviews in MongoDB so a repeated run only fetches what is new.
Who is it for?
googlemaps-scraper fits a researcher or analyst who already has the place URLs and needs the newest reviews in a spreadsheet, and who is prepared to run a browser rather than call an API. It is the wrong tool for anything that needs the full review history, because it starts from the most recent reviews and works backwards, and it is the wrong tool for a pipeline that needs to run unattended at scale, since it drives Chromedriver and depends on the Google Maps page layout.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 115 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The input is a list of place review URLs

The scraper extracts the most recent reviews starting from the URL of a specific point of interest in Google Maps, and the unit of work is that URL. You put the URLs in a file, the script reads them, and it produces a CSV.

The README is unusually specific about how those URLs have to be made, and that detail is the difference between a run that works and a run that returns nothing. The instructions are to go to Google Maps, look for a specific place, click on the number of reviews in the parenthesis, and save the URL that is generated from that interaction. An example file, urls.txt, is included so you can see what a correct URL looks like, and there is a separate urls_places.txt for the place variant.

That constraint is a direct consequence of the approach. The script is not searching Google Maps for a business by name, it is driving a browser to a review page URL that Google has already prepared, and a URL that is not in that shape does not lead the browser to the reviews.

The basic call takes the input file name, the output file name, and the number of reviews to fetch, with sensible defaults of urls.txt for the input, output.csv in the data folder for the output, and 100 reviews.

Flags for place metadata, sorting, source URLs and a visible browser

Beyond the three main parameters there are four switches, and each one changes what ends up in the CSV.

The place flag is the most useful of them, because it switches the mode of operation from reviews to point of interest metadata. The debug flag runs the browser with the graphical interface instead of headless, which is what you want the first time you run it to see what is happening. The source flag adds the source URL as an extra field in the CSV, which matters if you are combining many places into one file and need to know which review came from where.

The sort_by flag is the one with a real effect on the data. It takes a string among most_relevant, newest, highest_rating or lowest_rating, with newest as the default. The README credits that feature to a specific contributor and describes it as allowing the sorting behaviour of reviews to be changed, which matters because the reviews you want are rarely the most relevant ones. A competitor analysis asking for the worst reviews is a different query from one asking for the newest.

The example given for the main usage is short enough to be worth reproducing exactly:

`python scraper.py --N 50`

which generates a CSV file containing the last 50 reviews of the places present in urls.txt.

Why a browser, and what the dependency list says about it

The scraper is Selenium based, and the README tells you to download the latest version of Chromedriver before anything else, with a link to the Chromedriver download index. The requirements file confirms the shape of the implementation, and it is a small, dated dependency set:

bash
beautifulsoup4==4.12.3
certifi==2024.7.4
charset-normalizer==3.3.2
colorama==0.4.6
crayons==0.4.0
idna==3.15
numpy==1.26.4
pandas==2.2.0
pymongo==4.6.3
pytz==2024.1
requests==2.33.0
selenium==4.17.2
termcolor==2.4.0
webdriver-manager==3.5.2

The mix of libraries tells the story. Selenium drives the browser, webdriver-manager handles getting a driver, BeautifulSoup and requests do the parsing and fetching, pandas assembles the output, and pymongo is the MongoDB client for the monitoring feature. numpy and pytz are there for the data handling, and colorama, crayons and termcolor are the terminal colouring packages, which is a hint that the scripts print progress rather than running silently.

The consequence of the browser approach is worth stating plainly. A browser driver has to match the Chrome version on the machine, the page has to look the way the parsing code expects, and both of those change without notice. The pinned versions in the requirements file are from early 2024, and a driver or a layout change is the failure mode to expect.

The install step is a Python environment built from the requirements file, and the README gives a conda create command with a file argument, which is the mechanism for building an environment from a requirements file rather than installing into an existing one. Python 3.9 or newer is required.

The monitor script turns a one-shot export into an incremental feed

The limitation of the basic script is the number of reviews it will retrieve, and monitor.py is the answer to it. The additional requirement is a MongoDB instance on your machine, with a link to the official installation guide.

The design is simple and worth understanding before running it. The script takes the same input file as before, plus a from-date parameter in the format YYYY-MM-DD, which gives the minimum date the scraper tries to obtain. The idea is to periodically run the script: it stores the reviews it finds in MongoDB, and it keeps going until it reaches either the latest review from the previous run or the date given in the input parameter. In other words, the database remembers where the last run stopped, and the next run only fetches what is new since then.

That changes the failure profile. A one-shot run against a place with thousands of reviews stops at the limit you set, and the older ones are simply not there. A monitored run accumulates history across days, and the from-date parameter gives you a floor for the first run so that a long backfill is a deliberate choice rather than an accident.

The MongoDB dependency is the price. The basic script needs nothing beyond Python and a browser, while the monitor needs a database server, and the two scripts share the input file, so the operational setup is a real piece of infrastructure for a tool whose core is a browser loop.

The repository layout, and the scripts you actually run

The top-level entries describe a small collection of scripts rather than a package. There is scraper.py, which is the main one, monitor.py for the incremental variant, googlemaps.py and scrapper_places.py, and two sample input files, urls.txt and urls_places.txt. There are data, input and output directories, a requirements.txt and a README, plus an .idea directory and a .gitignore.

The split between scraper.py and scrapper_places.py matches the place flag in the CLI, and the presence of urls_places.txt suggests the place variant has its own input format, which makes sense because a place metadata page and a review page are different URLs with different structure.

There is no setup.py, no pyproject.toml and no package structure, so this is a set of scripts you clone and run in place, with the environment built from the requirements file. The directory names input, data and output are a hint about the intended flow: URLs in, CSV out, with data as the default location for the results file.

For a project like this, that simplicity is a feature as much as a limitation. There is no library API to import, and there is nothing to install into a larger application, which means the scripts are also the documentation of how the thing works.

Where this is the wrong tool

The first limitation is the direction of travel. The script retrieves the most recent reviews, starting from the newest and working back, and the number it can get is capped by the parameter you pass. There is no way to walk back through years of history in one run, and for a place with a long review history that means either a very high limit or repeated runs with the MongoDB monitor, and even then the from-date floor applies.

The second is fragility. Selenium plus Chromedriver plus a page that Google can change at any time is three separate points of failure, and the pinned dependency versions from early 2024 mean a fresh install today is not the environment the code was written against. A tool whose output depends on an unversioned web page is a tool you will have to maintain.

The third is the driver. It needs a matching Chromedriver, and the download link in the README points at the general Chromedriver index rather than at a pinned version, so the version alignment is on you.

The fourth is what the tool is for. It collects reviews for places you already have URLs for. It is not a business discovery tool, it does not resolve names to places, and it does not give you any of the other data Google Maps holds. If the question is which businesses exist in a category in a city, this is the wrong instrument.

And the obvious caveat applies to any scraper: collecting data that a platform publishes is a matter of the platform's terms and of the law where you operate, and the project itself is a technical tool with no position on that. Check before you point it at anything.

Licence, releases and the state of the project

The project is licensed under GPL-3.0, with the LICENSE file at the root of the repository. The releases are v1.1.0 from 2023-03-25 and v1.0.0 from 2022-01-08, and the last push to the repository was on 2026-06-29, with the repository not archived.

The gap between the release dates and the last push is the pattern to notice. The tags stopped in 2023 while commits continued into 2026, which for a scraper is a reasonable rhythm: the code gets small fixes, but there is no new release because there is no release pipeline to cut one. The version you run is whatever is on the branch.

The project also leans on two long-form write-ups for the design reasoning, a Medium post describing the logic and approach behind the software development, and another on the idea behind the monitoring feature. For a project of this size those posts are the real documentation, since the README is a reference and not a tutorial.

The author is gaspa93, and the repository topics place it in the google-maps-scraping and reviews space, with python and scraper as the other tags.

Editorial conclusion

googlemaps-scraper fits a researcher or analyst who already has the place URLs and needs the newest reviews in a spreadsheet, and who is prepared to run a browser rather than call an API. It is the wrong tool for anything that needs the full review history, because it starts from the most recent reviews and works backwards, and it is the wrong tool for a pipeline that needs to run unattended at scale, since it drives Chromedriver and depends on the Google Maps page layout. Before you use it, check three things: that the URLs in your input file were produced the way the README describes, by clicking the review count in Google Maps, that you can install Chromedriver for your platform, and that you have a MongoDB instance if you intend to use the monitor script rather than the one-shot export. The code is GPL-3.0, the current release is v1.1.0 from 2023-03-25, and the last push was on 2026-06-29.

Frequently asked questions

How do I install the Google Maps scraper?

Download the latest Chromedriver for your platform, then create a Python environment from the requirements file using pip, conda or virtualenv, for example the conda create command with a file argument in the README. Python 3.9 or newer is required.

How do I run the scraper and what do the main flags do?

The --i flag names the input file of place review URLs, --o names the output file created in the data folder, and --N is the number of reviews to retrieve starting from the most recent, defaulting to 100. The --place flag scrapes point of interest metadata instead of reviews, --debug shows the browser, --source adds the source URL to the CSV and --sort_by changes the review ordering.

What does monitor.py add to the basic scraper?

It makes the run incremental and removes the limit on how many reviews can be retrieved, by storing reviews in MongoDB and stopping at the latest review from the previous run or at the date given by the --from-date parameter. It requires a MongoDB instance on your machine.

How do I get the correct Google Maps URL for a place?

Go to Google Maps, look for the place, click on the number of reviews in the parenthesis, and save the URL that interaction generates. The example file urls.txt in the repository shows what a correct URL looks like.

What licence is the Google Maps scraper released under?

GPL-3.0, with the licence file in the repository. The current release is v1.1.0 from 2023-03-25 and the last push to the repository was on 2026-06-29.

Official sources

  1. gaspa93/googlemaps-scraper on GitHub
  2. Issues
  3. License: GPL-3.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/gaspa93-googlemaps-scraper.svg)](https://hysenlabs.com/projects/gaspa93-googlemaps-scraper)

Was this useful?