{
  "openapi": "3.0.1",
  "info": {
    "title": "Google Maps Scraper Plus — Places, Leads & Change Monitoring",
    "description": "Fast HTTP Google Maps scraper: unlimited area coverage with an adaptive grid, multi-city runs, emails & socials with MX check, transparent lead score, change monitoring, honest fill-rate report and interactive map.",
    "version": "1.0",
    "x-build-id": "gNrJPWJRTPl4oWHzi"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/cheapapi~google-maps-scraper-plus/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-cheapapi-google-maps-scraper-plus",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/cheapapi~google-maps-scraper-plus/runs": {
      "post": {
        "operationId": "runs-sync-cheapapi-google-maps-scraper-plus",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/cheapapi~google-maps-scraper-plus/run-sync": {
      "post": {
        "operationId": "run-sync-cheapapi-google-maps-scraper-plus",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "searchQueries": {
            "title": "🔍 Search terms",
            "type": "array",
            "description": "What you would type into Google Maps, e.g. <code>dentist</code>, <code>coffee shop</code>, <code>Starbucks</code>. Every term is searched in every location below.",
            "items": {
              "type": "string"
            }
          },
          "locations": {
            "title": "📍 Locations",
            "type": "array",
            "description": "Any number of cities, districts, regions, postcodes or countries, e.g. <code>Austin, Texas, USA</code>, <code>10115 Berlin</code>, <code>Portugal</code>. Each one is geocoded to its real boundary and covered with an adaptive grid, so you are not limited to Google's ~120 results per map view. Leave empty to search without a location (Google picks the area).",
            "items": {
              "type": "string"
            }
          },
          "customGeolocation": {
            "title": "🗺️ Custom search area (GeoJSON)",
            "type": "object",
            "description": "Draw your own area on <a href='https://geojson.io' target='_blank'>geojson.io</a> and paste it here. Accepts Polygon, MultiPolygon, a Point with <code>\"radiusKm\"</code>, or a whole Feature/FeatureCollection."
          },
          "countryCode": {
            "title": "Country code",
            "pattern": "^([A-Za-z]{2})?$",
            "type": "string",
            "description": "Optional two-letter ISO country code (e.g. <code>US</code>, <code>DE</code>). Disambiguates location names and sets Google's region. With no locations, the whole country is searched."
          },
          "startUrls": {
            "title": "🔗 Google Maps URLs",
            "type": "array",
            "description": "Paste any Google Maps link: place pages, search result pages, <code>?cid=</code> links or <code>maps.app.goo.gl</code> share links. You can also link a text file with one URL per line.",
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "placeIds": {
            "title": "🆔 Place IDs / CIDs",
            "type": "array",
            "description": "Look up places directly. Accepts Google Place IDs (<code>ChIJ…</code>), <code>place_id:ChIJ…</code>, CIDs (<code>16434010972841156326</code>) and feature ids (<code>0x89c2…:0xe411…</code>).",
            "items": {
              "type": "string"
            }
          },
          "maxPlacesPerQuery": {
            "title": "Max places per search term & location",
            "minimum": 0,
            "maximum": 100000,
            "type": "integer",
            "description": "Stops each search term × location combination after this many places. <code>0</code> = no limit (get everything in the area). If left empty: 200, or no limit in monitoring mode (so removals can be detected). The Console form is prefilled with 50 for a cheap first try."
          },
          "maxPlacesTotal": {
            "title": "Max places in total",
            "minimum": 0,
            "maximum": 1000000,
            "type": "integer",
            "description": "Hard cap for the whole run across all terms and locations. <code>0</code> = no cap. You can also cap spending with the platform's 'Maximum cost per run'.",
            "default": 0
          },
          "coverage": {
            "title": "Area coverage",
            "enum": [
              "auto",
              "thorough",
              "fast"
            ],
            "type": "string",
            "description": "<b>Auto</b> (recommended): splits the area into tiles and automatically subdivides every tile where Google truncated the list. <b>Thorough</b>: starts with small tiles for dense cities — slower, finds the most places. <b>Fast</b>: one map view per location (max ~120–200 places), cheapest.",
            "default": "auto"
          },
          "includeNearbyKm": {
            "title": "Include places just outside the area (km)",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "By default only places strictly inside the location boundary are returned. Set e.g. <code>2</code> to also keep places up to ~2 km outside.",
            "default": 0
          },
          "pointRadiusKm": {
            "title": "Radius for point locations (km)",
            "minimum": 1,
            "maximum": 200,
            "type": "integer",
            "description": "When a location resolves to a single point (e.g. a street address) instead of an area, search this radius around it.",
            "default": 3
          },
          "minRating": {
            "title": "Minimum rating",
            "minimum": 0,
            "maximum": 5,
            "type": "number",
            "description": "Only places with at least this star rating (e.g. <code>4.2</code>). Filtered places are never charged."
          },
          "minReviews": {
            "title": "Minimum number of reviews",
            "minimum": 0,
            "maximum": 1000000,
            "type": "integer",
            "description": "Only places with at least this many Google reviews."
          },
          "maxReviewsCount": {
            "title": "Maximum number of reviews",
            "minimum": 0,
            "maximum": 1000000,
            "type": "integer",
            "description": "Useful to find new or under-marketed businesses (e.g. <code>10</code>)."
          },
          "categoryFilter": {
            "title": "Only these categories",
            "type": "array",
            "description": "Keep places whose Google category contains any of these words (whole words, in the run's language), e.g. <code>bar</code> keeps \"Cocktail bar\" and \"Wine bars\" but not \"Barbecue restaurant\". Filtered places are never charged.",
            "items": {
              "type": "string"
            }
          },
          "excludeCategories": {
            "title": "Exclude categories",
            "type": "array",
            "description": "Drop places whose category contains any of these words, e.g. <code>hotel</code>.",
            "items": {
              "type": "string"
            }
          },
          "websiteFilter": {
            "title": "Website",
            "enum": [
              "all",
              "withWebsite",
              "withoutWebsite"
            ],
            "type": "string",
            "description": "Filter by whether the listing has a website. \"Without website\" is a classic web-design lead list.",
            "default": "all"
          },
          "phoneFilter": {
            "title": "Phone",
            "enum": [
              "all",
              "withPhone",
              "withoutPhone"
            ],
            "type": "string",
            "description": "Filter by whether the listing has a phone number.",
            "default": "all"
          },
          "claimFilter": {
            "title": "Listing ownership",
            "enum": [
              "all",
              "claimed",
              "unclaimed"
            ],
            "type": "string",
            "description": "Unclaimed listings (owner never verified the Google Business Profile) are strong leads for local SEO agencies.",
            "default": "all"
          },
          "skipClosedPlaces": {
            "title": "Skip closed places",
            "type": "boolean",
            "description": "Drop permanently and temporarily closed places.",
            "default": false
          },
          "nameMatch": {
            "title": "Name must match search term",
            "enum": [
              "any",
              "containsQuery",
              "exact"
            ],
            "type": "string",
            "description": "Useful for brand searches: <b>Contains</b> keeps only places whose name contains every word of the search term.",
            "default": "any"
          },
          "scrapePlaceDetails": {
            "title": "Load full place details",
            "type": "boolean",
            "description": "Adds rating distribution, top reviews, review keywords, owner description, places located inside (malls, airports) and more. Included in the base price — no add-on fee. Turn off only for maximum speed.",
            "default": true
          },
          "maxReviews": {
            "title": "Reviews per place",
            "minimum": 0,
            "maximum": 5000,
            "type": "integer",
            "description": "Reviews per place, up to 5,000 — the complete, most recent review history (text, stars, date, owner reply, photos, per-topic ratings). The first 5 reviews of every place are included in the place price; more reviews are charged per review, with a small minimum per place (see Pricing in the README). Set 0 for no reviews.",
            "default": 5
          },
          "reviewsSort": {
            "title": "Review order",
            "enum": [
              "newest",
              "mostRelevant",
              "highestRating",
              "lowestRating"
            ],
            "type": "string",
            "description": "Which reviews come first when a place has more reviews than you request.",
            "default": "newest"
          },
          "reviewsStartDate": {
            "title": "Only reviews since",
            "type": "string",
            "description": "Optional. Keep only reviews published on or after this date (YYYY-MM-DD). Works best with 'Newest first'. Reviews removed by this date are not charged, but the review pages loaded still cost their minimum (review-minimum top-ups), so set 'Reviews per place' close to what you expect to keep."
          },
          "reviewsPersonalData": {
            "title": "Include reviewer names & profile links",
            "type": "boolean",
            "description": "Off by default for GDPR safety. Turn on only if you have a legitimate interest to process reviewers' personal data.",
            "default": false
          },
          "maxImages": {
            "title": "Image URLs per place",
            "minimum": 0,
            "maximum": 10,
            "type": "integer",
            "description": "Full-size photo URLs per place. Google exposes about 3–5 photos per place to logged-out visitors, so values above that return what is available.",
            "default": 5
          },
          "placeExtras": {
            "title": "Extended profile (popular times & more)",
            "type": "boolean",
            "description": "Adds popular times (busyness by day and hour), price level, 'people also search' places, review topics and the full list of available/unavailable attributes. Charged per place looked up ($0.0022): place-extras when data is returned, place-extras-checked when Google has no extended profile for the place. Adds a few minutes to the run (longer for very large runs).",
            "default": false
          },
          "scrapeContacts": {
            "title": "Find emails, phones & social profiles on the website",
            "type": "boolean",
            "description": "Visits each business website (homepage + contact/about/imprint pages; only the listed page on ordering/booking platforms) and extracts emails, phones and 13 social networks. Emails are checked for a working mail server (MX) and filtered by a business-mailbox privacy rule; platform and template addresses are removed. Also reports website health (parked, dead, social-only, platform page…) and tech signals (CMS, analytics, pixel, online booking). Charged only when the website adds something the listing didn't have (an email, or a valid phone / social profile not already on the listing), at most once per business domain.",
            "default": false
          },
          "maxContactPagesPerSite": {
            "title": "Max pages per website",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "Pages visited per website in total, including the homepage (contact/about/imprint pages are preferred).",
            "default": 4
          },
          "verifyEmailDomains": {
            "title": "Verify email domains (MX)",
            "type": "boolean",
            "description": "Drops emails whose domain cannot receive mail. Free, DNS-based (no SMTP probing).",
            "default": true
          },
          "includePersonalEmails": {
            "title": "Include possibly personal emails",
            "type": "boolean",
            "description": "Off by default for GDPR safety. By default an email is returned only if it is clearly a business mailbox: one of its name parts is or starts with a role word (info@, bookings2@, front.desk@, events@…), a word from the business name or website domain, or the business published it in its structured data. Other addresses (e.g. john@, gerry@) are hidden and counted in <code>personalEmailsHidden</code>. Turn on only if you have a legitimate interest to process personal data.",
            "default": false
          },
          "leadScoring": {
            "title": "Lead score & sales signals",
            "type": "boolean",
            "description": "Adds a transparent 0–100 <code>leadScore</code> with a point-by-point breakdown and <code>leadSignals</code> such as <code>no_website</code>, <code>unclaimed_listing</code>, <code>website_no_https</code>, <code>no_online_booking</code>. Free.",
            "default": true
          },
          "monitoringMode": {
            "title": "Track changes between runs",
            "type": "boolean",
            "description": "Remembers places across runs (schedule this Actor!) and labels each result NEW / UPDATED / UNCHANGED with a field-level diff (phone, website, status, hours…). REMOVED is reported only after Google confirms it (closed permanently, merged, moved out of the area or no longer known) for a place missing from 3 consecutive complete runs.",
            "default": false
          },
          "monitoringName": {
            "title": "Watch name",
            "type": "string",
            "description": "Runs with the same name share memory. Defaults to a fingerprint of your search terms and locations."
          },
          "monitorFields": {
            "title": "Fields that count as a change",
            "type": "array",
            "description": "A place is UPDATED when one of these fields changes. Rating and review count move on almost every run, so by default they are only reported in <code>metricsDelta</code>.",
            "items": {
              "type": "string",
              "enum": [
                "title",
                "categoryName",
                "address",
                "phoneUnformatted",
                "website",
                "businessStatus",
                "openingHoursText",
                "claimThisBusiness",
                "totalScore",
                "reviewsCount",
                "priceInfo"
              ],
              "enumTitles": [
                "Name",
                "Category",
                "Address",
                "Phone",
                "Website",
                "Business status (open/closed)",
                "Opening hours",
                "Ownership (claimed/unclaimed)",
                "Rating",
                "Review count",
                "Price (hotels, fuel)"
              ]
            },
            "default": [
              "title",
              "categoryName",
              "address",
              "phoneUnformatted",
              "website",
              "businessStatus",
              "openingHoursText",
              "claimThisBusiness"
            ]
          },
          "outputOnlyChanges": {
            "title": "Output only new & changed places",
            "type": "boolean",
            "description": "Skip UNCHANGED places — they are not output and not charged, so recurring runs cost only for what is new or changed. Switches monitoring on automatically.",
            "default": false
          },
          "marketReport": {
            "title": "Market & competitor report",
            "type": "boolean",
            "description": "Free. Builds <code>market-report.html</code> (and <code>MARKET_REPORT</code> JSON) from this run's places: category breakdown, opportunity lists (established businesses without a website, unclaimed listings, rising stars, busy but poorly rated, no online booking), leaders and the review topics of the area. No extra requests, no AI — every number comes from the dataset. Skipped when only changes are output.",
            "default": true
          },
          "myBusiness": {
            "title": "Your business (optional)",
            "type": "string",
            "description": "A Place ID, Google Maps URL or CID of your own (or your client's) business. It is looked up too, and the report compares it with its nearest competitors of the same category: rating, reviews, photos, business posts, website, online booking — with strengths and weaknesses."
          },
          "language": {
            "title": "Language",
            "type": "string",
            "description": "Language of place names, categories and reviews (Google <code>hl</code> code, e.g. <code>en</code>, <code>de</code>, <code>tr</code>, <code>pt-BR</code>).",
            "default": "en"
          },
          "outputMap": {
            "title": "Save interactive results map",
            "type": "boolean",
            "description": "Stores <code>results-map.html</code> (clustered map of all places) in the run's key-value store.",
            "default": true
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "Default Apify datacenter proxy works best for Google Maps' internal endpoints and is the cheapest. Residential proxy is not needed.",
            "default": {
              "useApifyProxy": true
            }
          },
          "useProxyForWebsites": {
            "title": "Use proxy for business websites",
            "type": "boolean",
            "description": "Contact enrichment visits business websites directly by default. Enable if some sites block the platform's IPs.",
            "default": false
          },
          "maxConcurrency": {
            "title": "Max concurrency",
            "minimum": 1,
            "maximum": 50,
            "type": "integer",
            "description": "Parallel requests. The default is safe; higher values finish faster on large runs.",
            "default": 10
          },
          "limitedViewRetries": {
            "title": "Retries for Google's 'limited view'",
            "minimum": 0,
            "maximum": 10,
            "type": "integer",
            "description": "Google randomly serves a reduced place page (~50% of requests) without review data and with only today's opening hours. Such places are re-requested up to this many times; records that stayed reduced are labelled in dataQuality.",
            "default": 4
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}