Google Maps Scraper
Pricing
from $1.95 / 1,000 record scrapeds
Google Maps Scraper
Extract data from thousands of locations: get reviews, pricing, photos, and B2B contact info (names, emails, titles). Automate your workflow by scheduling recurring runs, monitoring performance, and integrating directly via our API.
Pricing
from $1.95 / 1,000 record scrapeds
Rating
4.8
(2)
Developer
F
Maintained by CommunityActor stats
0
Bookmarked
4
Total users
2
Monthly active users
an hour ago
Last modified
Categories
Share
Google Maps Custom Target Schema Scraper
A production-ready Apify Actor designed to scrape Google Maps business profiles. This scraper extracts deep, comprehensive data and formats its JSON output in a clean, structured schema.
💰 Pricing & Monetization
This Actor is billed under a highly transparent Pay per event + usage model:
- Actor Start: $0.05 per 1,000 runs ($0.00005 flat rate per run).
- Record Scraped: $1.95 per 1,000 places ($0.00195 per successfully scraped record).
🚀 Features
- Structured Outputs: Output objects are organized in a clean, consistent, industry-standard schema format.
- Dynamic Content Support: Fully renders modern interactive pages to extract dynamic lists and profiles seamlessly.
- Advanced Anti-Detection Measures:
- Ghost-Cursor: Emulates human-like bezier-curve mouse movements prior to clicks to bypass Google's advanced bot detection.
- Automatically avoids rate limits and IP bans to ensure stable scraping.
- Automatically dismisses cookie consent banners.
- Deep Extraction Strategy:
- Fuzzy Match Fallback: Utilizes Dice's Coefficient string similarity to accurately resolve and click the correct business when Google returns an ambiguous list view.
- Extracts core data (Title, Rating, Coordinates, Address, Plus Codes).
- Decomposes addresses into logical segments (Street, Neighborhood, City, State, Country).
- Captures reviews distribution, booking links, and restaurant reservation providers.
- Grabs "People Also Search For", similar nearby hotels, and hotel ads.
- Extracts photo gallery metadata (including author, URL, and upload dates).
- Gathers extended review metadata (including translation status, reviewer photos, detailed sub-ratings).
- Data Sanitization Pipeline: Built-in middleware aggressively scrubs zero-width spaces, invisible byte-order marks, and soft hyphens to guarantee pristine string formatting.
- Fast & Efficient: Optimized to scrape data quickly while minimizing execution time and cost.
Prerequisites
Installation
# Clone or download the repositorycd apify_scrapper# Install dependenciesnpm install
Running Locally
To run the scraper locally, you must provide valid input data matching the expected schema.
- Create a directory named
apify_storage/key_value_stores/default. - Inside that directory, create a file named
INPUT.jsonwith the following format:
{"searchStrings": ["Best coffee shops in Seattle", "Pizza in NYC"],"maxResultsPerSearch": 20,"language": "en","maxReviews": 5,"maxImages": 5}
- Important: Because this scraper requires Residential Proxies to bypass Google's blocks, you must run the scraper with your Apify API token exported to your environment:
# Export your Apify API Tokenexport APIFY_TOKEN="your_apify_api_token_here"# Start the scrapernpm start
Extracted data will be saved to apify_storage/datasets/default/.
🐍 Programmatic Integration (Python)
You can run this Actor programmatically from your Python applications using the official apify-client library.
1. Install Apify Client
$pip install apify-client
2. Python Code Example
from apify_client import ApifyClient# Initialize the Apify Client with your Apify API Tokenclient = ApifyClient("your_apify_api_token_here")# Define the scraper inputsrun_input = {"searchStrings": ["Pizza Hut, Boston"],"maxResultsPerSearch": 10,"language": "en","maxSearchRadius": 5,"searchRadiusUnit": "km"}# Run the Actor and wait for its completionrun = client.actor("google-maps-custom-target-schema-scraper").call(run_input=run_input)# Fetch and print the scraped results from the default datasetdataset = client.dataset(run["defaultDatasetId"])for item in dataset.iterate_items():print(f"Name: {item.get('title')}")print(f"Phone: {item.get('phone')}")print(f"Address: {item.get('address')}")print(f"Distance: {item.get('distanceFromSearchCenter')} {item.get('distanceUnit')}")print("-" * 40)
Detailed Input Parameters
The Actor accepts the following JSON input parameters. These fields control what is searched and how deeply each profile is scraped.
Ways to Search
You can target places using different search patterns based on your needs. Below are examples of how to configure your inputs:
1. Search by Business Name or Keyword (searchStrings)
Perfect for scraping matching businesses across a city or general keywords.
- Plain Search:
["Pizza in Boston", "Dentists near Central Park"] - Specific Business Name:
["Union Oyster House Boston", "Giacomo's Restaurant Boston"]
Example Input:
{"searchStrings": ["Seafood in Boston", "Union Oyster House Boston"]}
2. Search by Latitude and Longitude (Geographic Viewport)
To search within a specific geographic coordinate area, use a Google Maps search URL with @latitude,longitude,zoomz coordinate parameters inside startUrls. The scraper will search only within that specific map viewport.
- Format:
https://www.google.com/maps/search/<query>/@<lat>,<lng>,<zoom>z - Example (Restaurants near Boston Common):
https://www.google.com/maps/search/restaurants/@42.3554,-71.0640,16z
Example Input:
{"startUrls": ["https://www.google.com/maps/search/restaurants/@42.3554,-71.0640,16z"]}
3. Search by Polygons / Custom Areas (Grid Viewport Split)
Since Google Maps doesn't support drawing arbitrary polygons directly, you can scrape custom-shaped regions by splitting your polygon into a grid of overlapping coordinate viewports, and adding their search URLs to startUrls.
- Example (Scraping two adjacent grid viewports covering a custom shape in the North End):
- Viewport 1 (North End West):
https://www.google.com/maps/search/cafes/@42.3642,-71.0545,17z - Viewport 2 (North End East):
https://www.google.com/maps/search/cafes/@42.3655,-71.0510,17z
- Viewport 1 (North End West):
Example Input:
{"startUrls": ["https://www.google.com/maps/search/cafes/@42.3642,-71.0545,17z","https://www.google.com/maps/search/cafes/@42.3655,-71.0510,17z"]}
| Parameter | Type | Default | Description |
|---|---|---|---|
searchStrings | Array | [] | A list of Google Maps search queries. (Accepts strings or arrays, parsed safely with default fallback.) |
startUrls | Array | [] | Direct Google Maps place URLs to scrape. (Accepts strings or arrays, parsed safely with default fallback.) |
maxResultsPerSearch | Integer | 20 | The maximum number of place profiles to scrape per search query. Defaults to 20 if missing, invalid, or malformed. |
language | String | "en" | The language code appended to the Google Maps URLs (e.g., "en", "ar", "es"). |
maxReviews | Integer | 0 | The maximum number of individual reviews to extract per place. Defaults to 0 if invalid. |
maxImages | Integer | 0 | The maximum number of image URLs to collect per place. Defaults to 0 if invalid. |
maxSearchRadius | Number | null | The maximum distance from the search center coordinates. Skipped if null, empty string, or invalid. |
searchRadiusUnit | String | "km" | Unit of measurement for the maximum search radius: "km" (Kilometers) or "mi" (Miles). |
searchCenterLat | Number | null | Optional manual override for the search center latitude. Parse-safe float. |
searchCenterLng | Number | null | Optional manual override for the search center longitude. Parse-safe float. |
🌍 Internationalization & Arabic Localization Support
The scraper features robust built-in support for localized Middle-Eastern addresses and Arabic text parsing to prevent parsing errors and data loss:
- Arabic Commas (
،- U+060C): Google Maps profiles in Arabic regions use standard commas,and Arabic commas،. The parser splits on both/[,،]/to cleanly segment street, neighborhood, and city. - Arabic Country Mappings: Mappings are configured for Arabic country names (e.g.
"السعودية"or"المملكة العربية السعودية"for Saudi Arabia,"الامارات"/"الإمارات"for United Arab Emirates, etc.) to successfully resolve ISO-2 country codes (likeSA,AE,QA,BH,KW,OM,EG,JO,LB). - Asynchronous Search Resolving: Handles client-side JS redirects on single place searches dynamically before trying to extract feeds, preventing timeouts or empty results on direct business matches.
Exhaustive Output Data Structure
The output dataset is formatted as a structured JSON object. Below is a complete breakdown of every single key you will find in the output JSON objects.
Core Metadata & Search Context
searchString(String): The original query used to find this place.rank(Integer): The position of this place in the search results (1-indexed).searchPageUrl(String): The URL of the search results page.searchPageLoadedUrl(String): The final URL after redirects.isAdvertisement(Boolean):trueif this place was a sponsored ad in the search results.
Place Identity & Basics
title(String): The business name.subTitle(String): The subtitle shown below the business name on Google Maps.description(String): The editorial summary/description written by Google.categoryName(String): The primary category of the business (e.g., "Pizza restaurant").categories(Array): A list of all categories assigned to the business.price(String): The price tier (e.g.,"$"or"$$$").totalScore(Float): The overall star rating out of 5.0.reviewsCount(Integer): The total number of reviews.
Location & Contact
address(String): The full, unparsed address string.street(String): Parsed street address.neighborhood(String): The specific neighborhood or district.city(String): Parsed city name.state(String): The full state or province name (e.g., "New York", not "NY").postalCode(String): Parsed ZIP or postal code.countryCode(String): The two-letter country code (e.g., "US", "GB").location(Object): Contains the exactlatandlngcoordinates.locatedIn(String): If the business is located inside another building/mall.plusCode(String): The Google Plus Code for the location.phone(String): The formatted phone number.phoneUnformatted(String): The raw phone number string with non-numeric characters removed.website(String): The business's primary website URL.distanceFromSearchCenter(Float): Calculated distance between the place and the resolved search center (indistanceUnit), ornullif coordinates couldn't be resolved.distanceUnit(String): The unit used for distance calculations ("km"or"mi"), ornull.
Identifiers
placeId(String): The Google Maps Place ID.cid(String): The unique Customer ID (decimal BigInt format).fid(String): The Google Feature ID.kgmid(String): The Knowledge Graph Machine ID.url(String): The canonical Google Maps URL for this profile.
Business Status & Features
claimThisBusiness(Boolean):trueif the business profile is unverified/unclaimed.permanentlyClosed(Boolean):trueif marked permanently closed.temporarilyClosed(Boolean):trueif marked temporarily closed.operationalStatusText(String): Text indicator of current operational status (e.g.,"Open","Closed").openingHours(Array): An array of objects[{ day, hours }].additionalInfo(Object): Contains nested arrays of strings for various amenities and features.
Media & Engagement
imageUrl(String): The primary hero image URL for the business.imagesCount(Integer): Total number of photos uploaded to the profile.imageCategories(Array): The tab labels for photos (e.g., "All", "Menu", "Food").images(Array): Detailed metadata for scraped images. Each object containsimageUrl,authorName,authorUrl, anduploadedAt.imageUrls(Array): A flat list of the raw image URLs.
Reviews Data
reviewsDistribution(Object): Counts of reviews by star rating:{ oneStar, twoStar, threeStar, fourStar, fiveStar }.reviewsTags(Array): Popular keywords mentioned in reviews, e.g.,[{ title: "pizza", count: 45 }].topRelevantReviews(Array): Snippets of the top 5 'Relevant' reviews extracted directly from the main overview tab.reviews(Array): Detailed individual reviews. Each object contains:name,reviewerId,reviewerUrl,reviewerPhotoUrl,reviewerNumberOfReviews,isLocalGuidepublishAt,publishedAtDatetext,textTranslated,rating,starslikesCount,reviewId,reviewUrl,reviewOrigin,reviewImageUrlsreviewContext,reviewDetailedRating(e.g.,{"Food": 5, "Service": 4})responseFromOwnerDate,responseFromOwnerText
Specialized Entities
restaurantData(Object): Contains booking provider info:{ tableReservationProvider: { name, reserveTableUrl } }.menu(String): Direct link to the menu.reserveTableUrl(String): Direct link to book a table.googleFoodUrl(String): Direct link to order food via Google.hotelStars(String): Descriptive hotel rating (e.g., "4-star hotel").hotelDescription(String): Editorial hotel description.hotelAds(Array): Booking ads{ title, googleUrl, isOfficialSite, price, url }.similarHotelsNearby(Array): Competitors{ name, rating, reviews, description, price }.peopleAlsoSearch(Array): Related businesses{ category, title, reviewsCount, totalScore }.
📊 Sample Output JSON
Below is a complete, realistic sample of a successfully scraped Google Maps place record, showing all the fields populated by the Actor:
{"searchString": "Pizza Hut, Boston","rank": 1,"searchPageUrl": "https://www.google.com/maps/search/Pizza%20Hut%2C%20Boston?hl=en","searchPageLoadedUrl": "https://www.google.com/maps/search/Pizza%20Hut%2C%20Boston?hl=en","isAdvertisement": false,"title": "Pizza Hut","subTitle": null,"description": "Popular delivery, carry-out & dine-in chain known for pizza, wings & pasta, plus sides & desserts.","price": "$","categoryName": "Pizza delivery","address": "7 Sycamore St, Everett, MA 02149, United States","neighborhood": "Everett","street": "7 Sycamore St","city": "Everett","postalCode": "02149","state": "Massachusetts","countryCode": "US","website": "https://locations.pizzahut.com/ma/everett/7-sycamore-st","phone": "+1 781-321-3335","phoneUnformatted": "+17813213335","claimThisBusiness": false,"location": {"lat": 42.4144303,"lng": -71.0467333},"locatedIn": "Glendale Square","plusCode": "CX73+Q8 Everett, Massachusetts, USA","menu": "https://www.pizzahut.com/c/content/menu","servicesLink": null,"totalScore": 3.6,"permanentlyClosed": false,"temporarilyClosed": false,"operationalStatusText": "Open","placeId": "ChIJkeNmq51x44kRyEDnYBTWnsk","categories": ["Pizza delivery","Pizza restaurant"],"fid": "0x89e3719dab66e391:0xc99ed61460e740c8","cid": "14528284830957256904","reviewsCount": 843,"reviewsDistribution": {"oneStar": 190,"twoStar": 36,"threeStar": 19,"fourStar": 115,"fiveStar": 365},"imagesCount": 42,"imageCategories": ["All","Interior","Food & drink"],"scrapedAt": "2026-06-15T18:25:34.710Z","reserveTableUrl": null,"googleFoodUrl": null,"hotelStars": null,"hotelDescription": null,"checkInDate": null,"checkOutDate": null,"similarHotelsNearby": [],"hotelReviewSummary": null,"hotelAds": [],"openingHours": [{"day": "Monday","hours": "10:30 AM - 12:00 AM"},{"day": "Tuesday","hours": "10:30 AM - 12:00 AM"},{"day": "Wednesday","hours": "10:30 AM - 12:00 AM"},{"day": "Thursday","hours": "10:30 AM - 12:00 AM"},{"day": "Friday","hours": "10:30 AM - 1:00 AM"},{"day": "Saturday","hours": "10:30 AM - 1:00 AM"},{"day": "Sunday","hours": "10:30 AM - 12:00 AM"}],"additionalOpeningHours": null,"openingHoursBusinessConfirmationText": null,"popularTimesLiveText": null,"popularTimesLivePercent": null,"popularTimesHistogram": null,"peopleAlsoSearch": [],"placesTags": [],"reviewsTags": [{"title": "classic hand tossed pizza","count": 2},{"title": "friendly cashier","count": 5}],"additionalInfo": {"Service options": [{"Curbside pickup": true},{"No-contact delivery": true},{"Takeout": true}]},"gasPrices": [],"questionsAndAnswers": [],"updatesFromCustomers": [],"ownerUpdates": [],"url": "https://www.google.com/maps/place/Pizza+Hut/data=!4m7!3m6!1s0x89e3719dab66e391:0xc99ed61460e740c8!8m2!3d42.4144303!4d-71.0467333!16s%2Fg%2F1thx0fxl!19sChIJkeNmq51x44kRyEDnYBTWnsk","imageUrl": "https://lh3.googleusercontent.com/gps-cs-s/APNQkAFofbDgfNqaqjs94bbGiyoLNvnYcQOE6DN0SBjGw0z_PrelPB97mg5IhaPur1U9wSlQAtxQBrJP0MGutBUEvrhIB2YtOOs1RCp_XsiyE4Rj2PaIhNXiGLuCB5uBvO-vlcFjAY5SJeWx1a8U=w112-h112-p-k-no","kgmid": "/g/1thx0fxl","floor": null,"isExternalServicePlace": false,"externalServiceProvider": null,"externalId": null,"webResults": [],"parentPlaceUrl": null,"tableReservationLinks": [],"bookingLinks": [],"images": [{"imageUrl": "https://lh3.googleusercontent.com/gps-cs-s/APNQkAFofbDgfNqaqjs94bbGiyoLNvnYcQOE6DN0SBjGw0z_PrelPB97mg5IhaPur1U9wSlQAtxQBrJP0MGutBUEvrhIB2YtOOs1RCp_XsiyE4Rj2PaIhNXiGLuCB5uBvO-vlcFjAY5SJeWx1a8U=w112-h112-p-k-no","authorName": "Pizza Hut","authorUrl": "","uploadedAt": "3 years ago"}],"imageUrls": ["https://lh3.googleusercontent.com/gps-cs-s/APNQkAFofbDgfNqaqjs94bbGiyoLNvnYcQOE6DN0SBjGw0z_PrelPB97mg5IhaPur1U9wSlQAtxQBrJP0MGutBUEvrhIB2YtOOs1RCp_XsiyE4Rj2PaIhNXiGLuCB5uBvO-vlcFjAY5SJeWx1a8U=w112-h112-p-k-no"],"reviews": [{"name": "Jane Doe","text": "Great service and the pizza was hot and fresh!","publishAt": "2 weeks ago","likesCount": 3,"reviewId": "ChZDSUhNMG9uQkNNR09Y...","reviewerId": "2394829384","reviewerUrl": "https://www.google.com/maps/contrib/2394829384","reviewerPhotoUrl": "https://lh3.googleusercontent.com/a-/ALV-...","reviewerNumberOfReviews": 15,"isLocalGuide": false,"reviewOrigin": "Google","stars": 4,"responseFromOwnerDate": null,"responseFromOwnerText": null}],"userPlaceNote": null,"restaurantData": {},"topRelevantReviews": [{"text": "Great service and the pizza was hot and fresh!","rating": 5}],"distanceFromSearchCenter": 5.48,"distanceUnit": "km"}