{"platform":"google-maps","title":"Google Maps reviews","version":2,"summary":"Sort the reviews by Newest. If the listing has 500 reviews or fewer, collect them all (complete=true). Otherwise collect the 500 most recent (complete=false, sort='newest'), never more than 1000. Everything required is visible on each review card: stars, reviewer name, their lifetime review count and Local Guide badge, the relative date, the text. Review ids, exact timestamps and profile links are optional extras that sharpen the result when they are cheap to read.","identity":[{"name":"platform","type":"'google-maps'","required":true,"description":"Which registry entry this submission follows."},{"name":"placeId","type":"string","required":true,"description":"Google's feature id, 0x<hex>:0x<hex>. In a /maps/place/ URL it is the '!1s0x…:0x…' segment (the LAST one when several appear), or the 'ftid=' parameter. If you only have a ?cid= link, send `cid` (decimal) instead."},{"name":"cid","type":"string","required":false,"description":"The decimal cid from a ?cid= link, when placeId is unknown."},{"name":"name","type":"string","required":true,"description":"The listing's name as shown."},{"name":"address","type":"string","required":false,"description":"Formatted address. Strongly recommended: multi-location businesses are told apart by it."},{"name":"lat","type":"number","required":false,"description":"Listing latitude ('!3d' in the URL). Needed for the place to join its city page."},{"name":"lon","type":"number","required":false,"description":"Listing longitude ('!4d' in the URL)."},{"name":"listedReviews","type":"integer","required":true,"description":"The review count Google displays on the listing ('1,234 reviews'). Checked against the feed."},{"name":"listedRating","type":"number","required":true,"description":"The star rating Google displays (4.6). Checked against the mean of the submitted ratings on complete feeds; on a window it is the headline shown against the window's anchor rating."},{"name":"ratingHistogram","type":"array of 5 integers","required":true,"description":"The listing's rating histogram, the five bars next to the star rating: review counts for 1, 2, 3, 4 and 5 stars IN THAT ORDER (Google draws the bars 5 stars first, so reverse what you read). Each bar's accessibility label or tooltip carries the exact count ('5 stars, 1,234 reviews'); it is shown for every listing, signed in or not. Required for a window or capped feed, where it tells the scorer how the reviews you did not collect are distributed; optional on a complete feed. Checked against listedReviews and listedRating."},{"name":"complete","type":"boolean","required":true,"description":"True only if the review list was scrolled/paged to its very end. False for a newest-first window (the 500 most recent reviews) or a capped feed."},{"name":"sort","type":"string","required":false,"description":"The order you collected in: 'newest' or 'relevant'. A window (complete=false) must be 'newest' and the reviews must be sent in that order."},{"name":"capped","type":"boolean","required":false,"description":"True when you deliberately stopped at 5,000+ reviews of a much larger listing. Accepted in place of complete only at that depth; below it send a newest-first window instead."},{"name":"pulledAt","type":"ISO 8601 datetime","required":true,"description":"When the reviews were collected. Relative dates are resolved against this, so make it the actual collection time."},{"name":"mapsUrl","type":"string","required":false,"description":"The listing URL you collected from."},{"name":"reviews","type":"array","required":true,"description":"The reviews, one object each (see the review fields), in the order collected."}],"review":[{"name":"rating","type":"integer 1-5","required":true,"description":"Stars given."},{"name":"author","type":"string","required":true,"description":"Reviewer display name, exactly as shown."},{"name":"authorReviewCount","type":"integer","required":true,"description":"The reviewer's lifetime review count shown next to their name ('12 reviews'; 'Local Guide · 45 reviews · 12 photos'). Drives the established-account anchor; the score degrades badly without it. Send 1 when the line shows no count."},{"name":"date","type":"string","required":true,"description":"The relative date exactly as displayed, in English ('3 months ago', 'a year ago', 'Edited 2 weeks ago'). May be omitted only when `timestamp` is given. Collect with the page in English (hl=en), or translate the relative date to this English form yourself, keeping the 'Edited' prefix: the server does not translate. On an edited review the displayed date is the EDIT date; keep the prefix so we know."},{"name":"isLocalGuide","type":"boolean","required":false,"description":"Whether the reviewer carries the Local Guide badge. Omit or false when absent. Required in practice: the credible-reviewer anchor keys on it."},{"name":"text","type":"string","required":false,"description":"Full review text in its original language (expand 'More' when you can); omit or empty for star-only reviews. Do not send the auto-translated version."},{"name":"reviewId","type":"string","required":false,"description":"Optional but valuable: Google's review id, the token starting with 'Ch' or 'Ci'. On the page it is the data-review-id attribute of the review card and the id in the review's 'Share' link; in the captured review payload it is the first element of each review row (howToCollect). Lets us match reviews exactly across pulls and catch feeds copied from another listing."},{"name":"timestamp","type":"number or numeric string","required":false,"description":"Optional but the single most valuable extra: when the review was POSTED (not last edited), as an epoch timestamp in microseconds (Google's native value), milliseconds, or seconds. The page never shows it (the DOM only carries the relative date), but the page's own network responses do: see howToCollect. Without it, `date` is used at display resolution (a week or a month for older reviews) and the result is labeled 'approximate dates'."},{"name":"editedTimestamp","type":"number or numeric string","required":false,"description":"Optional, with timestamp: when the review was last edited, in the same units (row[0][1][3] of the captured review row; send it whenever it is present and later than the posting time). Google's Newest sort orders by this, so it tells us exactly where a newest-first window starts; the posting time still drives the burst tests."},{"name":"authorUrl","type":"string","required":false,"description":"Optional: the reviewer's profile link, https://www.google.com/maps/contrib/<21-digit id>, the href of the reviewer's name. Lets cross-business reviewer matching key on the account instead of the display name."},{"name":"language","type":"string","required":false,"description":"BCP-47 language code of the text when known."},{"name":"authorPhotoCount","type":"integer","required":false,"description":"The reviewer's lifetime photo count, shown on the same line as their review count ('45 reviews · 12 photos'). Include it whenever it is shown."},{"name":"photoCount","type":"integer","required":false,"description":"Photos attached to this review. Include it whenever the card shows photos."},{"name":"ownerResponse","type":"{date?, text?}","required":false,"description":"The business's reply, when any."},{"name":"source","type":"string","required":false,"description":"Which platform the card says the review came from, when the listing shows several (hotels: Google, Booking.com, Expedia, Hotels.com, Tripadvisor, Agoda). Send Google reviews only; reviews marked with another source are dropped before scoring."}],"rules":["Before collecting, check that the review list lets you sort by Newest and load more than the first handful of reviews. Google often requires a signed-in account for sorting and paging. If you are signed out and cannot sort or scroll further, stop and ask the user to sign in to Google in the browser you are using, then continue. When you ask, tell the user what this involves: you will read Google Maps through their signed-in browser, much like scrolling the listing themselves; heavy use could trip Google's rate limits, and a secondary Google account is a reasonable choice for anyone who checks many places. Do NOT submit the ten or so 'most relevant' reviews a signed-out page shows as if they were a feed: that sample is too small and too flattering to score, and the server rejects windows under the minimum.","Exact timestamps are the biggest single improvement you can make. The strongest manipulation signal is a burst of throwaway accounts on one day, and relative dates ('6 months ago') hide every such day older than a week: on our corpus two thirds of the places convicted on exact dates read cleaner on page dates. If your browser can run page JavaScript or read network responses (Playwright, Puppeteer, Chrome DevTools MCP, Claude in Chrome), capture them as described in howToCollect. If it cannot (an accessibility-tree-only agent), send the relative dates; the report will say the dates are approximate and that this is a limit of the collecting client.","Sort by Newest BEFORE collecting. Google's default 'Most relevant' order favors long reviews from active accounts and buries the short throwaway reviews the scorer looks for, so a sample taken in that order is flattering by construction. A partial feed in any other order is rejected.","A listing with up to 500 reviews: collect every review and send complete=true. A larger listing: collect the 500 most recent and send complete=false with sort='newest' (a window of fewer than 200 is rejected: too short to show the place's normal review rate). Collecting the whole list is always welcome.","Never collect more than 1,000 reviews: the score does not sharpen past the 1,000 most recent, and the user is waiting on the pull (aim to answer within a minute or two). A window larger than 1,000 is trimmed to its newest 1,000; a complete pull of a bigger listing is accepted but was unnecessary.","Alternatively a listing far larger than 5,000 reviews may be sent capped at 5,000+ reviews with capped=true.","Hotels: Google shows reviews from several platforms (Booking.com, Expedia, Hotels.com, Tripadvisor, Agoda) alongside its own. Filter the review list by source = Google before collecting; only Google reviews are scored (the signals key on Google account features) and skipping the rest keeps the pull short. Partner reviews that arrive anyway, marked with `source`, are dropped.","Google's 'limited view' sometimes answers a reviews page with 5 reviews and no next page at a listing showing hundreds. That is not the feed: retry in a fresh session, do not submit it.","Send each review as shown. Keep the original-language text (never the auto-translation), never summarize or deduplicate reviews yourself, and keep the order you collected in.","Every review needs its displayed relative date in English (or an exact timestamp). Load the page with hl=en so dates read '3 months ago', not a localized form.","listedReviews and listedRating must be the numbers Google displays on the listing at collection time. On a complete feed the mean of the submitted ratings is checked against listedRating.","ratingHistogram is the five-bar rating histogram next to the star rating, as counts for 1 to 5 stars in that order. It is required with a window or capped feed: the lifetime distribution is what lets the scorer judge the reviews you did not collect (a place with thousands of reviews and almost no 4-star or lower ratings is flagged from the histogram alone). Its total must match listedReviews and its mean listedRating; a reversed array is detected and rejected.","When you include review ids or profile links, they must be Google's own (the structure is verified). Leave the field out rather than inventing a value.","Identity (name, address, lat, lon) comes from you: the server never contacts Google.","A result built from a window says so (\"based on the N most recent reviews\") and from relative dates says \"approximate dates\". Neither affects whether the place can be endorsed; that depends on who submitted the data (provenance)."],"howToCollect":["A short link (maps.app.goo.gl, goo.gl/maps, g.co) must be opened and followed to its final google.com/maps URL before anything else. Run page JavaScript only on that final google.com page; if your browser tool refuses to run it, retry once there before falling back to reading the cards.","Open the place in Google Maps and read the canonical URL: '/maps/place/<Name>/@…/data=…!1s0x…:0x…!8m2!3d<lat>!4d<lon>…'. The !1s segment is placeId, !3d/!4d are lat/lon. The header shows the name, the star rating and the review count.","Next to the star rating, the reviews summary shows five bars for 5, 4, 3, 2 and 1 stars. Read each bar's exact count from its accessibility label or tooltip ('4 stars, 212 reviews'; hovering or the accessibility tree gives it) and send them as ratingHistogram in 1-to-5 order: [count1, count2, count3, count4, count5].","Open the reviews tab, choose Sort → Newest, then scroll until you have the reviews you need (or the list ends). Scroll with page JavaScript, not the mouse wheel: the review list is a nested scroller, wheel events land on whatever is under the pointer, and setting the list's scrollTop to its scrollHeight in a loop (waiting for new cards each step) loads a page per step. On the mobile web view each scroll loads a page of 8-10 reviews; 500 reviews take about a minute.","On a hotel, the reviews tab also has a source filter (All / Google / Booking.com / …): pick Google before sorting and scrolling, so partner-platform reviews are never loaded.","Each review card shows: the reviewer's name (its link is authorUrl, optional), 'Local Guide' and 'N reviews · M photos' under the name (isLocalGuide, authorReviewCount, authorPhotoCount), the stars (rating), the relative date (date), and the text (click 'More' to expand when you can). The card's data-review-id attribute is reviewId (optional).","Exact timestamps: start capturing BEFORE you open the reviews tab (or reload the page after installing the capture). Reviews the page already holds in memory are never requested again, so a capture installed after sorting misses the newest pages. Each page of 8-10 reviews arrives as a response to '/maps/rpc/listugcposts' or, on newer builds of Maps, to a '/maps/.../batchexecute' call made as the list loads; the review rows inside are laid out the same. Capture with your browser tool's network reader, or wrap window.fetch and XMLHttpRequest.prototype.open/send so every response whose URL contains 'listugcposts' or 'batchexecute' is cloned as text into a window-level array you read back afterwards (other batchexecute calls fire too; keep the ones whose payload holds review rows, see the next rule).","Parsing a captured response: it starts with a \")]}'\" guard line; drop it, then JSON.parse. A batchexecute response is an envelope of chunks, each beginning [\"wrb.fr\", <rpc id>, <payload string>]: JSON.parse the third element of each chunk and keep the one whose result has review rows at [2]; that is the same payload a listugcposts response carries directly. Review rows are at payload[2]; in each row, row[0][0] is reviewId, row[0][1][2] the time the review was POSTED in microseconds since the epoch (send it as timestamp), row[0][1][3] the time it was last edited (send it as editedTimestamp when present: Google's Newest sort orders by this, so a newest-first feed may show a few posting-time inversions where reviews were edited; that is expected, keep the posting time as timestamp), row[0][1][6] the displayed relative date, row[0][1][4][5] the author block ([0] name, [2][0] profile url, [5] lifetime review count, [6] photo count), row[0][2][0][0] the stars and row[0][2][15][0][0] the text; payload[1] is the next-page token. Do not look for the timestamp in the DOM: it is not there."],"example":{"platform":"google-maps","placeId":"0x31752f3a1b2c3d4e:0x5f6a7b8c9d0e1f20","name":"Example Bistro","address":"12 Example St, District 1, Ho Chi Minh City, Vietnam","lat":10.776,"lon":106.7,"listedReviews":2,"listedRating":4.5,"ratingHistogram":[12,9,31,180,1002],"complete":true,"sort":"newest","pulledAt":"2026-10-27T08:00:00Z","reviews":[{"rating":5,"author":"A. Reviewer","authorReviewCount":9,"isLocalGuide":true,"date":"4 months ago","text":"Great pho, friendly staff.","language":"en","reviewId":"ChdDSUhNMG9nS0VJQ0FnSUNsZ1BMeDhRRRAB","authorUrl":"https://www.google.com/maps/contrib/101315872898595950451"},{"rating":4,"author":"B. Reviewer","authorReviewCount":41,"isLocalGuide":false,"date":"2 years ago"}]}}