How to scrape Google Reviews with Python

This guide shows how to scrape Google Reviews with Python: call one endpoint, get every review as clean JSON with rating, date, author, and text, then save it to a CSV file. No browser automation, no parsing HTML.

3,000 free searches / month, no card Rating, date, author, and text Clean JSON, no HTML parsing
PULLED LIVE FROM THE API, JULY 20, 2026

One request, real response

The hard part of scraping Google Reviews yourself is driving a browser, scrolling the review panel, and parsing markup that keeps changing. Instead you send one HTTP request to a search endpoint and get clean JSON back. First a quick test with curl:

# one credit per search, however many reviews come back; empty results cost nothing curl "https://crustapi.com/v1/search?type=reviews&q=Ritual Coffee Roasters San Francisco" -H "x-api-key: YOUR_KEY"

Then the same call in Python with the requests library. Install it with pip install requests, drop in a key, and run:

# pip install requests, then run this file import requests resp = requests.get( "https://crustapi.com/v1/search", params={"type": "reviews", "q": "Ritual Coffee Roasters San Francisco"}, headers={"x-api-key": "YOUR_KEY"}, ) data = resp.json() for r in data["reviews"]: print(r["rating"], r["date"], r["user"]["name"]) print(r["snippet"])

The response is one JSON object: searchParameters, a reviews list, and a nextPageToken for the following page. Here are the first two reviews that came back, shown as CSV so they drop straight into Sheets or a database:

rating,date,author,author_reviews,snippet 4,"3 months ago","Marcela Ma",218,"We had the butter croissant, which was delicious, but unfortunately, they couldn't warm it up. The hot chocolate, however, was a hit. It's more for adults since it's chocolate-forward and not overly sugary. The place is super cute, and the staff is friendly. It's a bit pricey, but hey, it's the city!" 5,"a year ago","George Adaimi",325,"If you're a true coffee lover, this spot is a must-visit. The coffee is rich, smooth, and clearly crafted with care. The staff are warm and welcoming, making the experience even better. The atmosphere is artistic and relaxed, with colorful wall art and creative energy. It's a perfect place to unwind or catch up with friends over a great cup. Definitely a standout for both quality brews and good vibes."

Change q to any business you want reviews for, like Blue Bottle Coffee Oakland or a place name plus its city.

WHAT EVERY REVIEW INCLUDES

The full record, ready to use

Every review comes complete, so you run sentiment analysis or track feedback with no second call. The same review as CSV, ready for Sheets or a database:

rating,date,isoDate,likes,author,author_reviews,author_photos,snippet 4,"3 months ago","2026-04-09T23:27:43.070Z",0,"Marcela Ma",218,727,"We had the butter croissant, which was delicious, but unfortunately, they couldn't warm it up. The hot chocolate, however, was a hit. It's more for adults since it's chocolate-forward and not overly sugary. The place is super cute, and the staff is friendly. It's a bit pricey, but hey, it's the city!"

Or the same review as JSON, exactly as the API returns it:

// one review in full { "rating": 4, "date": "3 months ago", "isoDate": "2026-04-09T23:27:43.070Z", "snippet": "We had the butter croissant, which was delicious, but unfortunately, they couldn't warm it up. The hot chocolate, however, was a hit. It's more for adults since it's chocolate-forward and not overly sugary. The place is super cute, and the staff is friendly. It's a bit pricey, but hey, it's the city!", "likes": 0, "user": { "name": "Marcela Ma", "thumbnail": "https://lh3.googleusercontent.com/a/ACg8ocInkAH2F_P1TyG7hpvo39Q2KKplbELzR8duUksX8syS12bJgYB7=s64-c-rp-mo-ba12-br100", "link": "https://www.google.com/maps/contrib/109805202270566134406/reviews?hl=en", "reviews": 218, "photos": 727 }, "media": [ { "type": "image", "caption": "Cream latte with a buttery croissant", "imageUrl": "https://lh3.googleusercontent.com/grass-cs/ACvplmNHEmNaMTf8CEKiqJRAbKIrME64Wks0wN64Eky3z8jbCz7T5J0CC5wAATUMbUUgfPVf5TrDx-waBsSU4_CV9hbSjFB3L41k6Aa1AoonSo9W7zGs8p9d0jDPonix8UdV_KFGZnTeTSuBYiGI=k-no" }, { "type": "image", "caption": "Espresso pour over menu with prices", "imageUrl": "https://lh3.googleusercontent.com/grass-cs/ACvplmMKXgNU9Y3haKe_24Ua0_yZjyUZ9-Idg8ZXwsSYtBrzgTvkh5Es2DjacbHSUpkWGrMxPDzBaxagCChAiGsW-HlqcTsP_UrNaC3LvuunwYAgOSSdz_D69OlgGGGFg1c_npzYkeXN9XCgDJK6=k-no" } ], "link": "https://www.google.com/maps/reviews/data=...!1s0x0:0x6b734213bb326353...?hl=en", "id": "Ci9DQUlRQUNvZENodHljRjlvT2pJNE4xbHljR2x0WjFaTE9IbFdURk15Y2xOWVgxRRAB" }
MORE THAN ONE PAGE

Page through every review

One call returns the first page of reviews. To pull the rest, read nextPageToken from the response and pass it back on the next request. Keep looping until the token stops coming, and you have the whole review history:

# collect every review by following nextPageToken import requests def all_reviews(query, key): reviews, token = [], None while True: params = {"type": "reviews", "q": query} if token: params["nextPageToken"] = token data = requests.get( "https://crustapi.com/v1/search", params=params, headers={"x-api-key": key}, ).json() reviews += data["reviews"] token = data.get("nextPageToken") if not token: return reviews rows = all_reviews("Ritual Coffee Roasters San Francisco", "YOUR_KEY") print("pulled", len(rows), "reviews")

Each request is one credit, however many reviews come back, so paging through the full history costs one credit per page and empty pages cost nothing.

HOW IT COMPARES

vs writing your own scraper

You can build a reviews scraper with a headless browser and a parser, and plenty of tutorials show how. The trade is maintenance. Here is the difference in practice.

Writing it yourselfCrustAPI
SetupInstall a headless browser, scroll the review panel, handle blocksOne GET request, no browser
OutputParse the HTML yourself; fields break when the layout changesClean JSON with rating, date, author, and text named, or the same rows as CSV
PagingTrack scroll state and dedupe rows by handFollow one nextPageToken to the end
MaintenanceFix the scraper each time the page changesWe keep it working
Free tierFree, but you pay in time and blocked requests3,000 searches / month, no card
Cost modelServer, proxy, and developer timeOne credit per search, however many reviews; empty results free
PRICING

One credit per search

Prepaid packs, and credits never expire: 25k for $49 · 100k for $149 · 500k for $549 · 2.5M for $1,999 · up to 250M, all self-serve, ex-tax. A search that returns 8 reviews or 80 costs one credit; a search that returns none costs nothing.

Run your first reviews search free
3,000 credits a month. No card, no contract.
Get started →
THE LAST STEP

Save the reviews to a CSV file

Because the response is plain JSON, Python's built-in csv module writes it to a file in a few lines. No extra libraries. This reads every review from the search and writes one row each:

# save every review to a CSV file with the built-in csv module import csv, requests data = requests.get( "https://crustapi.com/v1/search", params={"type": "reviews", "q": "Ritual Coffee Roasters San Francisco"}, headers={"x-api-key": "YOUR_KEY"}, ).json() with open("reviews.csv", "w", newline="") as f: writer = csv.writer(f) writer.writerow(["rating", "date", "author", "author_reviews", "snippet"]) for r in data["reviews"]: writer.writerow([r["rating"], r["date"], r["user"]["name"], r["user"].get("reviews", ""), r["snippet"]])

Open reviews.csv in Sheets or Excel and you have a clean feedback log. Swap the business, run it again, and append to track many locations at once.

Related: Google Reviews API · Google Reviews Scraper · Google Maps Scraper API · Scrape Google Maps with Python · API docs

FAIR PLAY

When a different tool fits better: replying to reviews, managing your own listing, or a contract with a formal SLA are Google Business Profile products, not scraping. This endpoint returns the public reviews anyone sees on a listing, which is what most research and monitoring work needs, but it is not the official Google Business Profile API.

BEFORE YOU ASK

Common questions

WORKS WITH YOUR STACK

Try it on a place you know

3,000 free credits covers a real search. Run one query and look at the JSON that comes back.

Get 3,000 free credits
No credit card required