How to scrape Google Reviews with Python

One endpoint, every review as clean JSON, no browser automation.

Free to try, no card Rating, date, author, and text Clean JSON, no HTML parsing
THREE STEPS

How do you get started?

From zero to live review data in about two minutes:

  1. 1

    Create a free account. Try it free, no card needed.

  2. 2

    Copy your API key from the dashboard.

  3. 3

    Run the curl or the script below. Clean JSON comes back, ready to save as CSV.

PULLED LIVE FROM THE API, AUGUST 2, 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 charge 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:

ratingdateauthorauthor_reviewssnippet
43 months agoMarcela Ma218We 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!
54 months agojay bagade131Ritual coffee is always good at any locations. But this neighborhood is great. This cafe has a decent amount of tables and space. Parking is difficult to find. They also have merchandise for sale.

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

What data do you get?

Every review comes complete, so you run sentiment analysis or track feedback with no second call. likes counts reader reactions, and a response object carries the business reply when there is one. The same review as CSV, ready for Sheets or a database:

ratingdateisoDatelikesauthorauthor_reviewsauthor_photossnippet
43 months ago2026-04-09T23:27:43.070Z1Marcela Ma218727We 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": 1, "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", "imageUrl": "https://lh3.googleusercontent.com/grass-cs/ACvplmPOBBl3B4jxKxdRF6l-rxh21ym70vLjgzE1JS-azRFNCAq6K4dbPXck-s9_MkZoBfdZ6-2AVv-86Bhdztc-zNDnjkx5jRqiJSXMg42xhlokgwysL59GhQANFmO2jEqcQvDpvBBQbRxaRW1N=k-no", "caption": "Cream latte with a buttery croissant" }, { "type": "image", "imageUrl": "https://lh3.googleusercontent.com/grass-cs/ACvplmPQvg0d6hb-0N0KXeAu9bNajugDr4zoeZkS7Cu4b0sgOgon4PQBTUqG7Jx1L52X5MoImLyIX-_BKEtyevloOCf7-ty3k-PI4DoJ0oCXElsXFDp-S_x_bC6-GHiOgdXcQDna8nHrfcsN5uXC=k-no", "caption": "Espresso pour over menu with prices" }, { "type": "image", "imageUrl": "https://lh3.googleusercontent.com/grass-cs/ACvplmPBvcjEEBnBpgzyvzdvYwVApaHZibe6DxI9naSBOAoe6xSQWIFtk0GJ_YDd_UzFqLRwSmoIuTgAbLB-wCN4SVtegvK10-wqmnGhwr_RcrKOqyI9eEn5yUXHIw5zn6pWjr4RJRr29YSV94g7=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 request charge, however many reviews come back, so paging through the full history costs one charge 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 requests$6 of free usage each month
Cost modelServer, proxy, and developer timeOne charge per search, however many reviews; empty results free
PRICING

How much does scraping Google Reviews cost?

You pay the applicable price per successful search. Eight reviews back or 80 is still one request charge, and a search that returns none costs nothing. Funds are prepaid and never expire.

DepositGoogle Search / 1,000 requestsMaps / 1,000 businessesLinkedIn reads / 1,000 requestsPeople, Jobs, Refresh / 1,000 units
$10+$1.00$1.96$6.00$1.96
$149+$0.76$1.49$4.50$1.49
$549+$0.56$1.10$3.30$1.10
$1,999+$0.41$0.80$2.45$0.80
$6,500+$0.33$0.65$1.95$0.65
$27,500+$0.28$0.55$1.65$0.55
$50,000+$0.26$0.50$1.50$0.50
$100,000+$0.20$0.40$1.50$0.40

Every eligible account gets $6 of free usage monthly. Each deposit keeps its prices until spent; paid funds never expire. People and Jobs bill per successful search, Refresh per accessible profile. Full profiles in People use the read rate per full profile. See all billing details.

Larger deposits unlock lower endpoint prices. Each deposit keeps its prices until spent. See the full deposit table on the pricing page. Prices in USD, ex-tax.

WHO IT'S FOR

Who scrapes Google Reviews?

Run your first reviews search free
Try it free. No card, no contract.
Try for free
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

No. With the CrustAPI endpoint you send one HTTP request with the requests library and get clean JSON back. There is no browser to drive and no HTML to parse, so the code above is the whole scraper.

The star rating, a relative date and an ISO timestamp, the review text, a likes count, the author name with their total review and photo counts, any attached photos, and a link to the review. When the business replied, a response object carries the reply date and text. Enough to run sentiment analysis or track feedback without a second call.

Each response includes a nextPageToken. Pass it back on the next request to get the following page, and keep looping until the token is missing. The Page through every review section above has the exact loop.

Logged-out, public-only collection has repeatedly defeated computer-fraud and contract claims. Google's Terms restrict automated access that violates instructions like robots.txt. What you get is the same public reviews anyone sees on the listing.

The response is plain JSON, so Python's built-in csv module writes it to a file in a few lines. The Save to CSV section above has the exact code, no extra libraries.

Yes. Try it free, no credit card, and paid funds never expire. That is enough to pull several full pages of reviews while you build.

WORKS WITH YOUR STACK

Try it on a place you know

the free plan covers a real search. Run one query and look at the JSON that comes back.

Try for free
No credit card required