Get Google Maps place reviews and information

Site google.comTask get-google-maps-place-reviews-and-infoVersion v6Updated Sep 15, 2026Category maps

Resolve a Google Maps place by name and address, extract complete overview metadata, then return every rendered review with explicit missing fields. This skill was captured from a live agent session on google.com and is published here as a reusable recipe for agents.

NoteSelectors and URL schemes drift as sites change. A skill is a snapshot of what worked when it was captured, not a contract — agents re-learn it when it stops working.

Resolve a Google Maps place from a name/address query, extract its overview metadata before entering the review view, and return all currently rendered reviews. Every review includes nullable author, rating, date, text, and image fields plus an explicit missingFields list.

Use Cases

  • Retrieve complete listing information for a named place at an address.
  • Extract rendered Google Maps reviews, including cards with missing rating, date, or image fields.
  • Capture hours, contact details, rating distribution, coordinates, topics, and popular-times labels.
  • Resolve ambiguous place names without guessing an opaque Maps place ID.

Automation Flow

  1. Navigate to https://www.google.com/maps/search/?api=1&query={url-encoded-name-and-address}.
  2. If redirected to /maps/place/, retain the canonical URL. Otherwise choose the /maps/place/ result whose visible name and address best match the request; never fabricate an opaque ID.
  3. On the canonical place page, remain on the overview and run the overview extractor below. It returns null fields and missingFields when metadata is not rendered.
  4. Click button[aria-label^="Reviews for"] when present. If absent, use button[aria-label^="More reviews"] only as a fallback, then run the review extractor below. Deduplicate by review ID.
  5. For more rendered cards, scroll div.m6QErb.DxyBCb.kA9KIf.dS8AEf and rerun the review extractor; report the visible main-listing review total separately from any continuation count.
(()=>{
const clean=s=>(s||'').replace(/\s+/g,' ').trim();
const body=clean(document.body?.innerText),aria=[...document.querySelectorAll('[aria-label]')].map(e=>clean(e.getAttribute('aria-label'))).filter(Boolean);
const first=re=>aria.find(x=>re.test(x))||null;
const href=location.href,coord=href.match(/@(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?)/);
const title=clean(document.querySelector('h1')?.textContent)||null;
const address=(first(/^Address:/i)||'').replace(/^Address:\s*/i,'')||null;
const phone=(first(/^Phone:/i)||'').replace(/^Phone:\s*/i,'')||null;
const ratingLabel=aria.find(x=>/^[0-5](?:\.[0-9])? stars?/i.test(x));
const rating=ratingLabel?Number((ratingLabel.match(/^[0-5](?:\.[0-9])?/)||[])[0]):null;
const countMatches=[...body.matchAll(/([\d,]+) reviews?/gi)].map(m=>Number(m[1].replace(/,/g,'')));
const website=[...document.querySelectorAll('a[href]')].find(a=>/^Website:/i.test(clean(a.getAttribute('aria-label')))||/website/i.test(clean(a.innerText)));
const category=clean([...document.querySelectorAll('button')].find(b=>/^(Historical landmark|Market|Landmark|Restaurant|Cafe|Hotel|Store|Bar|Bakery)$/i.test(clean(b.innerText)))?.innerText)||null;
const fields={place:title,address,phone,category,description:clean(document.querySelector('[aria-label^="About "]')?.innerText)||null,rating,reviewCount:countMatches[0]||null,ratingDistribution:aria.filter(x=>/^\d stars?,/i.test(x)),hours:aria.filter(x=>/^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday),/i.test(x)),currentStatus:first(/^(Open|Closed|Hours)/i),website:website?{label:clean(website.getAttribute('aria-label')||website.innerText),href:website.href}:null,plusCode:first(/^Plus code:/i),coordinates:coord?{latitude:Number(coord[1]),longitude:Number(coord[2])}:null,topics:aria.filter(x=>/mentioned in \d+ reviews/i.test(x)),popularTimes:[...new Set(aria.filter(x=>/^(Popular times|Usually busy|Currently .*busy|Usually .*busy|Wait time:)/i.test(x)))]};
fields.missingFields=Object.entries(fields).filter(([k,v])=>v===null||(Array.isArray(v)&&!v.length)).map(([k])=>k);
return {url:href,placeInfo:fields,visibleReviewTotals:countMatches};
})()
(()=>{
const clean=s=>(s||'').replace(/\s+/g,' ').trim();
const reviews=[...document.querySelectorAll('div.jftiEf[data-review-id]')].map(card=>{
 const raw=clean(card.innerText);
 const author=clean(card.querySelector('.d4r55,[class*="d4r55"]')?.textContent)||((raw.match(/^(.+?)\s+Local Guide\b/i)||[])[1]||null);
 const ratingLabel=clean(card.querySelector('[role="img"][aria-label*="star" i]')?.getAttribute('aria-label'))||null;
 const rating=ratingLabel?Number((ratingLabel.match(/[0-5](?:\.[0-9])?/)||[])[0])||null:null;
 const date=(raw.match(/\b(?:\d+ (?:day|week|month|year)s? ago|\w+ \d{1,2}, \d{4})\b/i)||[])[0]||clean(card.querySelector('.rsqaWe,[class*="rsqaWe"]')?.textContent)||null;
 const text=clean(card.querySelector('.wiI7pd,[class*="wiI7pd"]')?.textContent)||null;
 const photo=card.querySelector('button[data-photo-index], button[aria-label^="Photo" i]');
 const photoImg=photo?.querySelector('img');
 const background=photo ? getComputedStyle(photo).backgroundImage : '';
 const image=photoImg?.currentSrc||photoImg?.src||background.match(/^url\(["']?(.*?)["']?\)$/)?.[1]||null;
 const result={id:card.getAttribute('data-review-id'),author,rating,date,text,image,missingFields:[]};
 for(const k of ['id','author','rating','date','text','image'])if(result[k]===null)result.missingFields.push(k);
 return result;
});
return {url:location.href,renderedReviewCount:reviews.length,reviews:[...new Map(reviews.map(x=>[x.id||JSON.stringify(x),x])).values()]};
})()

Params

ParamWhat it doesExample value
{url-encoded-name-and-address}Resolves the requested place through Maps searchThe%20Alamo%2C%20300%20Alamo%20Plaza%2C%20San%20Antonio%2C%20TX%2078205
button[aria-label^="Reviews for"]Opens the dedicated rendered review viewReviews for The Alamo
button[aria-label^="More reviews"]Fallback review control when the dedicated Reviews button is absentMore reviews (4,684)
div.m6QErb.DxyBCb.kA9KIf.dS8AEfReview-list scroll container for additional rendered cardsscroll container
Sort reviews menuOptional requested review orderingLowest or Newest

Possible Friction Points

TriggerAction
Search returns multiple place linksMatch visible name and address, then verify coordinates and listing data before choosing one.
The dedicated review view hides address, hours, or contact metadataExtract overview metadata before clicking Reviews.
The overview and continuation controls show different review totalsReturn the overview total and continuation count as separate values; do not reconcile them.
Only a few review cards are renderedScroll div.m6QErb.DxyBCb.kA9KIf.dS8AEf and rerun the review extractor.
Review cards lack author, rating, date, text, or imageReturn the field as null and include its name in missingFields.
More reviews opens a photo stripClose it and use the visible Reviews control.
Review sorting or later batches prompt for sign-inReturn currently rendered cards and mark the requested ordering or pagination unavailable.
A broad div.jftiEf button[aria-label="See more"] selector is usedDo not use it; it can open a photo viewer.
Google changes review class namesPrefer [data-review-id], .jftiEf, .wiI7pd, .d4r55, .rsqaWe, and ARIA labels; inspect the loaded DOM and update selectors if all anchors disappear.
Unsigned access shows consent, CAPTCHA, or no public review surfaceReturn visible listing data, mark reviews unavailable, and do not invent results.

Call it

GET https://production-sfo.browserless.io/skills?token=TOKEN-HERE&domain=google.com&task=get-google-maps-place-reviews-and-info