Skip to content

Google Maps Extractor

Try for free

Extract public Google Maps places by keyword, category, location, or Maps URL. Get addresses, ratings, reviews count, phones, websites, opening hours, and GPS coordinates for every place.

🗺️ Google Maps Extractor

Turn a keyword, a city, or a Google Maps link into a dataset of public places: name, address, phone, website, rating, and hours when Maps publishes them.

Built for lead lists, local research, and location ops that need the same search again next week, not a one-off export.

✨ Features

  • 🔎 Search by keyword plus a location, or pass place_id:ChIJ... when you already know the place.
  • 🔗 Accept Google Maps search links, place links, cid links, maps.app.goo.gl links, and goo.gl/maps links. A URL that is not one of those fails the run and is not stored. A short link that does not open a public place fails the run the same way.
  • 📍 Center a search on a city, country, postal code, or a GeoJSON point. locationQuery is kept only when that text appears on the place address. A polygon or multipolygon keeps places that fall inside that shape.
  • ⭐ Filter by name match, category, minimum stars, whether a website is listed, and permanently or temporarily closed places.
  • 📄 Optional place preview (scrapePlaceDetailPage) for fields that show up on the place page. A failed preview keeps the values already on the search card.
  • 🌐 Language follows the language code. A two-letter countryCode is sent with the search.
  • 🚫 Empty fields stay off the item. A missing closed flag is not written as false.

🚀 Why teams use this

Request-based fetches, not a browser session per place, so a production run spends its time on Maps responses. You get a normal Scrapely dataset: schedule it, call it from the API, and export. Every stored row is a place Maps or the business's own public page actually returned. A start URL that is not Google Maps fails the run, and no error row is written. A search that returns no places exits with an empty dataset.

💡 Use cases

  • Pull every business for a keyword and city into a CRM or spreadsheet.
  • Size a local market: count places per category, rating, and neighbourhood.
  • Enrich an existing list of places with Maps coordinates, phones, and websites.
  • Track new or closed places for an area over time.

🧪 Example input

{
  "language": "en",
  "locationQuery": "New York, USA",
  "maxCrawledPlacesPerSearch": 20,
  "scrapeSocialMediaProfiles": {
    "facebooks": false,
    "instagrams": false,
    "tiktoks": false,
    "twitters": false,
    "youtubes": false
  },
  "searchStringsArray": [
    "restaurant"
  ]
}

🧾 Sample output

One item from a real run of the example input, shortened. Long text is cut and lists show their first entries.

{
  "title": "Gramercy Tavern",
  "placeId": "ChIJvSQIgqFZwokRFYQbJdzceSs",
  "address": "42 E 20th St, New York, NY 10003, United States",
  "categoryName": "New American restaurant",
  "categories": [
    "New American restaurant"
  ],
  "totalScore": 4.6,
  "reviewsCount": 5067,
  "location": {
    "lat": 40.7384555,
    "lng": -73.98850639999999
  },
  "street": "42 E 20th St",
  "city": "New York",
  "postalCode": "10003",
  "state": "New York",
  "neighborhood": "Manhattan",
  "countryCode": "US",
  "phone": "+1 555 0100",
  "phones": [
    "+1 555 0100"
  ],
  "phoneUnformatted": "+1 555 0100",
  "website": "https://www.gramercytavern.com/",
  "openingHours": [
    {
      "day": "Monday",
      "hours": "11:30 am to 11 pm"
    },
    {
      "day": "Tuesday",
      "hours": "11:30 am to 11 pm"
    }
  ],
  "imageUrl": "https://lh3.googleusercontent.com/…",
  "imagesCount": 10041,
  "fid": "0x89c259a1820824bd:0x2b79dcdc251b8415",
  "cid": "3132777853886366741",
  "businessProfileId": "18235747991152489841",
  "url": "https://www.google.com/maps/search/?api=1&query=Gramercy%20Tavern&query_place_id=ChIJvSQIgqFZwokRFYQbJdzceSs"
}

📥 Input

The fields that change what this actor collects:

FieldWhat it does
searchStringsArrayKeywords, or place_id: values. Ignored when startUrls is set.
locationQueryFree-text location. This wins over city, state, county, postal code, country, and customGeolocation. A place is kept only when this text appears in the city, state, address, neighborhood, or street.
city, county, state, postalCode, countryCodeUsed together as the location when locationQuery is empty. City and state must match the place, the postal code must start with the requested code, and the county name must appear in the address, city, or state.
customGeolocationGeoJSON. A point recenters the search. A multipoint recenters on those coordinates and keeps places near them. If none are public, the run fails and stores nothing. A polygon or multipolygon also drops places outside the shape. Coordinate order is [longitude, latitude].
startUrlsGoogle Maps URLs. These take priority over search terms.
maxCrawledPlacesPerSearchHow many places to keep per search term or URL. Default 20. The cap is 1000.
languageResults language, default en.
searchMatchingall, only_includes, or only_exact against the place name.
placeMinimumStarstwo through fourAndHalf. Places with no reviews are skipped.
websiteallPlaces, withWebsite, or withoutWebsite.
skipClosedPlacesDrop places Maps marks permanently or temporarily closed.
categoryFilterWordsKeep places whose categories overlap these words.
scrapePlaceDetailPageOpen each place preview and fill fields the preview actually contains.
scrapeTableReservationProviderStore the reserve link Maps already puts on the place (OpenTable, Resy, and the same kind of host). Provider email, phone, and address are omitted when Maps does not send them.
scrapeContactsRead the business website and its contact page for emails and social profile URLs. Placeholder addresses such as jane@example.com are dropped. Chain sites in the input description (McDonald's, Starbucks, and the rest of that list) are skipped.
includeWebResultsPublic web results for the place name and city, with title, URL, host, and snippet. When those pages send nothing, the place is still stored and webResults is left off.
scrapeOrderOnlineOpen the food-ordering page linked from the place. Store each provider name and link, plus the fee and ready time that page prints.
scrapeDirectoriesBusinesses listed under "At this place", each with locatedIn set to the parent place.
maximumLeadsEnrichmentRecordsUp to this many leads per place, read from the place website's home, contact, about and team pages: people (name, job title, email, phone, LinkedIn) first, then company emails. Each lead also carries the company name, website, phone, LinkedIn page, city and industry. Places without a website, and chain sites, get no leads.
verifyLeadsEnrichmentEmailsAdds emailVerification to each lead email: syntax, disposable-domain and mail-server (MX) checks, with result, quality, subResult, free and role. The mailbox itself is not contacted, so ok means the domain accepts mail.
scrapeSocialMediaProfilesFor each chosen platform, a profile object per link on the place website (up to 3): URL and username, plus name, description, image and the counts the public page shows (Facebook followers, Instagram followers and posts, TikTok followers, likes and videos). X returns URL and username only, because it hides details from logged-out visitors; some Instagram pages do the same. Also turns on contacts, which collects LinkedIn links in linkedIns.

maxQuestions is reserved: Google Maps no longer shows questions and answers, so it returns nothing and does not affect the run. Leads, verification and social profiles never fail the run when a site has nothing to show.

{
  "searchStringsArray": ["restaurant"],
  "locationQuery": "Konstanz",
  "maxCrawledPlacesPerSearch": 8,
  "language": "en",
  "searchMatching": "all",
  "website": "allPlaces",
  "skipClosedPlaces": false,
  "scrapePlaceDetailPage": false
}

📤 Output

Each place is one dataset item. A key is present only when the Maps payload had a value. Depending on the place, that can include:

title, placeId, address, neighborhood, street, city, state, postalCode, countryCode, location, plusCode, floor, categoryName, categories, price, totalScore, reviewsCount, reviewsDistribution, reviewsTags, phone, phones, phoneUnformatted, website, menu, openingHours, additionalOpeningHours, popularTimesHistogram, popularTimesLiveText, popularTimesLivePercent, imageUrl, imagesCount, imageCategories, fid, cid, kgmid, businessProfileId, url, searchPageUrl, searchString, language, rank, scrapedAt, description, ownerDescription, subTitle, additionalInfo, claimThisBusiness, reserveTableUrl, permanentlyClosed, temporarilyClosed, wasOpenAtScrapeTime.

A hotel place can also include hotelStars, hotelDescription, checkInDate, checkOutDate, hotelAds (provider title, the price string Maps printed, googleUrl, and isOfficialSite when Maps labels that row the official site), and similarHotelsNearby. A gas station can include gasPrices with the fuel name, the price tag, and the number from that tag. popularTimesHistogram uses Su through Sa, each with hour and occupancyPercent.

When the matching add-on is on and the page has the value, an item can also include tableReservationLinks, tableReservationProviders (name and reserveTableUrl), emails, facebooks, instagrams, youtubes, tiktoks, twitters, webResults (title, url, displayedUrl, description), orderOnline, locatedIn, and parentPlaceUrl.

inputStartUrl is set for rows that came from startUrls. inputPlaceId is set for a direct place id. openingHours is a list of {day, hours}. location is {lat, lng}. Rank is the kept-place order, including directory rows.

💰 Pricing

You pay per event, plus platform usage (compute and proxy traffic).

EventWhen it is chargedPrice
Place scrapedEach place saved to the dataset$0.0044
Filter appliedEach saved place when a filter is on (category words, minimum stars, closed places, website)$0.0008
Place details scrapedEach place whose detail page was opened and read (scrapePlaceDetailPage)$0.0016
Contact details scrapedEach place where scrapeContacts found an email or social link$0.0024
Social profile scrapedEach social profile returned with profile data$0.008
Lead scrapedEach lead record returned (maximumLeadsEnrichmentRecords)$0.006
Lead email verifiedEach lead email checked (verifyLeadsEnrichmentEmails)$0.0032

Add-ons are charged only when you turn the option on and only for places where it returned data.

Example: 1,000 places with no add-ons cost $4.40 in event fees plus platform usage. In our test runs platform usage for a plain search was about $0.08 to $0.16 per 1,000 places. The default 20-place search costs $0.088 in event fees.

If you set a maximum cost per run, the run saves as many places as that budget pays for and then stops cleanly.

Related actors

G2
4.7/5
Excellent
Trustpilot

The internet is full of data.
Start owning yours.

Scrape.ly gives you the infrastructure, the tooling, and the team to extract, process, and operationalize web data at any scale. Setup takes minutes. The advantage lasts forever.

No credit card. No setup calls.