{
  "openapi": "3.0.1",
  "info": {
    "title": "Google Maps Scraper API — Emails, Reviews, Photos & Leads",
    "description": "Google Maps scraper and Google Places API alternative: extract business names, phones, websites, hours, ratings and reviews — plus emails and 7 social profiles pulled from each place's website. Bypass Google's 120-place limit. Export JSON, CSV, Excel. From $3/1k places, no API key.",
    "version": "1.0",
    "x-build-id": "WbD4l1yaDWfErFo3j"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/pro100chok~google-maps-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-pro100chok-google-maps-scraper",
        "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/pro100chok~google-maps-scraper/runs": {
      "post": {
        "operationId": "runs-sync-pro100chok-google-maps-scraper",
        "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/pro100chok~google-maps-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-pro100chok-google-maps-scraper",
        "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": {
          "searchStringsArray": {
            "title": "🔍 Search terms",
            "type": "array",
            "description": "What to search for — one term per line (e.g. `restaurant`, `gym`, `dentist`). Each term is searched in every location below, so 3 terms x 5 cities = 15 searches. You can leave this empty ONLY if you paste Google Maps search links into 'Google Maps search URLs' below.",
            "items": {
              "type": "string"
            }
          },
          "locationQueries": {
            "title": "📍 Locations",
            "type": "array",
            "description": "One location per line — the search runs in every one of them. Format: free text as you'd type into Google Maps, from broad to narrow:\n• `New York` · `Rajasthan, India` · `Brooklyn, New York`\n• `Jaisalmer, Rajasthan, India` · `11201` (postal code)\n\nEach search term is run against each location, so 6 terms × 38 cities = 228 searches. For a single city just enter one line. Leave empty to use the structured City / State / Country fields below instead.",
            "items": {
              "type": "string"
            }
          },
          "startUrls": {
            "title": "🔗 Google Maps search URLs",
            "type": "array",
            "description": "Paste Google Maps SEARCH links (e.g. `google.com/maps/search/gyms+in+Jaipur`) and their query is added to the run. Links to one specific place are not supported — use the search fields above for those.",
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "language": {
            "title": "🗣️ Results language",
            "enum": [
              "",
              "en",
              "es",
              "fr",
              "de",
              "it",
              "pt",
              "nl",
              "pl",
              "uk",
              "ru",
              "be",
              "kk",
              "cs",
              "sk",
              "hu",
              "ro",
              "bg",
              "el",
              "tr",
              "sv",
              "da",
              "no",
              "fi",
              "et",
              "lv",
              "lt",
              "hr",
              "sr",
              "sl",
              "he",
              "ar",
              "fa",
              "hi",
              "bn",
              "ta",
              "ur",
              "th",
              "vi",
              "id",
              "ms",
              "ja",
              "ko",
              "zh-CN",
              "zh-TW"
            ],
            "type": "string",
            "description": "Leave on **Auto** and the actor picks the language from what you typed — search in Ukrainian and you get Ukrainian categories and reviews, search in English and you get English. Pick a language here only to force a different one.\n\nThe country (Google's `gl` hint) is detected the same way, from your locations — `Бровари, Київська область, Україна` searches as Ukraine, `Austin, TX` as the US — so there is nothing to set for it.",
            "default": ""
          },
          "popularTimes": {
            "title": "📊 Popular times (add-on)",
            "type": "boolean",
            "description": "⚠️ **Temporarily unavailable:** since October 13, 2026 Google no longer serves popular times on Google Maps for the web, so this field comes back empty until Google brings it back.\n\nAttach Google's weekly busyness histogram to each place — how busy it usually is for every hour of every day, plus the live \"busier than usual\" reading when Google has one.\n\n**Costs one extra request per place** (Google keeps this out of the search response), so a run with it on is noticeably slower. No extra charge — it is included in the Place event. Many places have no histogram at all: Google only computes one where a business gets enough traffic.",
            "default": false
          },
          "city": {
            "title": "🏙️ City",
            "type": "string",
            "description": "Optional — city name. Combined with the other fields into one location. Ignored if you filled the Locations list above."
          },
          "state": {
            "title": "🗺️ State / region",
            "type": "string",
            "description": "Optional — US state or other top-level region (e.g. `CA`, `Texas`). Combined with the other fields into one location."
          },
          "country": {
            "title": "🌍 Country",
            "type": "string",
            "description": "Optional — full country name, e.g. `USA`, `Germany`, `India`. Combined with the other fields into one location."
          },
          "county": {
            "title": "🗺️ County / district",
            "type": "string",
            "description": "Optional — county or district. Combined with the other fields into one location."
          },
          "postalCode": {
            "title": "📮 Postal code",
            "type": "string",
            "description": "Optional — narrows the search to one postal code. Combined with the city/state/country fields into a single location."
          },
          "maxItems": {
            "title": "🧮 Max results",
            "minimum": 1,
            "maximum": 100000,
            "type": "integer",
            "description": "Hard cap on how many places the run returns in total, across ALL search terms and locations. The actor stops as soon as it has this many — you are never charged for extras. Leave empty to keep going until Google runs out of results.",
            "default": 1000
          },
          "maxCrawledPlacesPerSearch": {
            "title": "🎯 Max results per search (term x location)",
            "minimum": 1,
            "maximum": 100000,
            "type": "integer",
            "description": "Cap for ONE search term in ONE location. With many locations this is what keeps coverage even: without it the first cities crawled can consume the whole 'Max results' budget and the rest return nothing. Leave empty for no per-search cap. The global 'Max results' still applies on top."
          },
          "deepSearch": {
            "title": "🌐 Deep search (split by postal code / district)",
            "type": "boolean",
            "description": "Google caps a single search at ~160 places. With this on, the actor splits the location into postal codes and districts and keeps searching until it hits your Max results — the only way to get thousands of places. On by default; it costs nothing on small runs, since crawling stops the moment Max results is reached.",
            "default": true
          },
          "categoryFilterWords": {
            "title": "🏷️ Category filter",
            "type": "array",
            "description": "Keep only places whose Google category matches one of these words (e.g. `gym`, `fitness`). Leave empty to keep every category. Filtered-out places cost you nothing — they are dropped before enrichment.",
            "items": {
              "type": "string"
            }
          },
          "searchMatching": {
            "title": "🎯 Name matching",
            "enum": [
              "all",
              "only_includes",
              "only_exact"
            ],
            "type": "string",
            "description": "How strictly a place name must match your search term. Google returns loosely related places by default, which is noise for lead lists.",
            "default": "all"
          },
          "placeMinimumStars": {
            "title": "⭐ Minimum rating",
            "enum": [
              "",
              "two",
              "twoAndHalf",
              "three",
              "threeAndHalf",
              "four",
              "fourAndHalf"
            ],
            "type": "string",
            "description": "Skip places rated below this. Places with no rating yet are always kept.",
            "default": ""
          },
          "minimumReviewsCount": {
            "title": "💬 Minimum number of reviews",
            "minimum": 0,
            "type": "integer",
            "description": "Skip places with fewer reviews than this — a quick way to drop inactive or barely-registered listings."
          },
          "website": {
            "title": "🌐 Website filter",
            "enum": [
              "allPlaces",
              "withWebsite",
              "withoutWebsite"
            ],
            "type": "string",
            "description": "Emails come from a place's website, so 'Only places WITH a website' is the setting for email-focused lead lists. 'Only WITHOUT' finds businesses to sell web design to.",
            "default": "allPlaces"
          },
          "skipClosedPlaces": {
            "title": "🚪 Skip closed places",
            "type": "boolean",
            "description": "Drop businesses Google marks as permanently or temporarily closed. Worth turning on for lead lists — a closed business is a wasted row.",
            "default": false
          },
          "scrapeContactsFromWebsite": {
            "title": "📧 Scrape emails + socials from websites",
            "type": "boolean",
            "description": "For every place that has a website, fetch homepage + contact pages and extract emails plus Facebook / Instagram / X / LinkedIn / YouTube / TikTok / Telegram links.",
            "default": true
          },
          "skipPlacesWithoutEmail": {
            "title": "📭 Skip places with no email",
            "type": "boolean",
            "description": "Keep ONLY places where an email was found. Requires email scraping to be on (above). Careful: this typically removes 50-60% of results, since most small businesses publish only a phone number.",
            "default": false
          },
          "skipDuplicateEmails": {
            "title": "🔁 Skip places with a duplicate email",
            "type": "boolean",
            "description": "Keep only the first place for each email address. Booking platforms and website templates put one shared address (e.g. `support@platform.com`) on dozens of listings — this drops those repeats so you don't pay for the same lead twice. Places with no email are never affected.",
            "default": true
          },
          "includeReviews": {
            "title": "💬 Include reviews (add-on)",
            "type": "boolean",
            "description": "Attach user reviews per place — text, rating, author, date, and attached photos. Paginates through Google's review API, so you get the full review history (up to your cap below). Billed per review extracted — see pricing.",
            "default": false
          },
          "maxReviewsPerPlace": {
            "title": "🔢 Max reviews per place",
            "minimum": 1,
            "maximum": 5000,
            "type": "integer",
            "description": "Hard cap on reviews attached to one place. The actor paginates Google's review API (~10 reviews per page) until it hits this cap or runs out of reviews.",
            "default": 20
          },
          "includeImages": {
            "title": "🖼️ Include image URLs (add-on)",
            "type": "boolean",
            "description": "Attach photo URLs to each place. Sources: 3-5 thumbnails from the search response + user-submitted photos from reviews (works only together with 💬 includeReviews). Higher review limit → more photos. Billed per image.",
            "default": false
          },
          "maxImagesPerPlace": {
            "title": "🔢 Max images per place",
            "minimum": 1,
            "maximum": 200,
            "type": "integer",
            "description": "How many image URLs to collect per place (the URLs only, not the image files). Charged per image.",
            "default": 20
          },
          "maxRetries": {
            "title": "🔁 Max retries per request",
            "minimum": 1,
            "maximum": 15,
            "type": "integer",
            "description": "How many times to retry a search that fails. The default is fine; raise it only on a very unstable connection.",
            "default": 5
          },
          "concurrency": {
            "title": "⚡ Concurrent sessions",
            "minimum": 1,
            "maximum": 50,
            "type": "integer",
            "description": "Google sessions running in parallel, each on its own IP. Higher = faster. 10 is a good default; raise it for very large runs.",
            "default": 10
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}