{
  "openapi": "3.0.1",
  "info": {
    "title": "Google Maps Places & Reviews Scraper",
    "description": "Extract Google Maps business listings and their individual reviews in one run — address, phone, website, categories, price band, opening hours, popular times, rating breakdown, photos and reviews with owner replies, all in the same record. Search many terms and cities at once.",
    "version": "0.1",
    "x-build-id": "B8Za9vyI2Tph4UQZV"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/itclan-bd~google-maps-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-itclan-bd-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/itclan-bd~google-maps-scraper/runs": {
      "post": {
        "operationId": "runs-sync-itclan-bd-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/itclan-bd~google-maps-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-itclan-bd-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": {
          "searchTerms": {
            "title": "Search terms",
            "uniqueItems": true,
            "type": "array",
            "description": "What to look for, one term per line — for example <code>dentist</code>, <code>orthodontist</code>. Every term is searched in every location, and the results are merged and deduplicated, so overlapping terms are safe and are a good way to find more businesses in one area.<br><br>Needs at least one location below.",
            "items": {
              "type": "string"
            }
          },
          "locationQuery": {
            "title": "Locations",
            "uniqueItems": true,
            "type": "array",
            "description": "Where to search, one per line. Either a place name — <code>Berlin, Germany</code>, <code>Austin, Texas</code> — or an exact point as <code>latitude, longitude</code>, for example <code>40.758, -73.9855</code>. Names and points can be mixed freely in the same list.<br><br>Every search term is run against every location, so three terms across two locations is six searches.",
            "items": {
              "type": "string"
            }
          },
          "latitude": {
            "title": "Latitude",
            "minimum": -90,
            "maximum": 90,
            "type": "number",
            "description": "Search around an exact point instead of a place name. Give <b>both</b> latitude and longitude — one on its own is ignored with a warning.<br><br>Decimal degrees, -90 to 90. Use this with <b>Search radius</b> below when you need a defined area rather than \"near this city\"."
          },
          "longitude": {
            "title": "Longitude",
            "minimum": -180,
            "maximum": 180,
            "type": "number",
            "description": "The other half of the point. Decimal degrees, -180 to 180."
          },
          "radiusKm": {
            "title": "Search radius",
            "minimum": 0.1,
            "maximum": 500,
            "type": "number",
            "description": "A <b>hard</b> limit on how far from the point above a business may be. Nothing outside it is returned: every result is measured against the point by real geographic distance and dropped if it is further away, and the Actor does not spend requests searching ground outside the circle either.<br><br>Applies only to a latitude and longitude. A location given by name has no single point to measure from, so a radius set without coordinates is ignored with a warning. Leave it empty to let the search decide how far to widen on its own."
          },
          "startUrls": {
            "title": "Google Maps URLs",
            "type": "array",
            "description": "Google Maps links, pasted or uploaded as a file. This is not a general web crawler — only Google Maps URLs are accepted, and each is read for what it names:<br><br>• a <code>/maps/search/…</code> link runs that search, at the viewport the link carries;<br>• a <code>/maps/place/…</code> link is fetched as <b>that</b> business, so a pinned link never returns a different branch;<br>• a <code>place_id:ChIJ…</code> entry — including the <code>/maps/place/?q=place_id:…</code> form this Actor emits as <code>mapsUrl</code> — is an exact place, the same as putting it in <b>Place IDs</b> below.<br><br>Can be used on its own or combined with the search above; everything is merged and deduplicated. <code>?cid=</code> share links are still rejected with a clear error: a cid carries only half of Google's internal id and cannot be resolved back to a place.",
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "placeIds": {
            "title": "Place IDs",
            "uniqueItems": true,
            "type": "array",
            "description": "Scrape exact businesses you already know, one Google place id per line — <code>ChIJfbedxbZZwokRpbnR5BBdz1c</code>. No search step is run, so nothing else comes back with them.<br><br>These are the ids Google's own Places API returns, and the <code>placeId</code> field of every result this Actor produces, so a previous run's output can be fed straight back in for re-scraping or monitoring. Ids that Google does not recognise are reported and skipped rather than failing the run, and a place named twice — by id and by URL, say — is still scraped once.",
            "items": {
              "type": "string"
            }
          },
          "maxPlacesPerSearch": {
            "title": "Max places per search term",
            "minimum": 1,
            "type": "integer",
            "description": "How many places to collect for each search term. Google answers a single point with roughly 170 results at most, so beyond that the Actor automatically widens the search across neighbouring areas until it reaches your number or runs out of businesses.<br><br>This shapes the search itself, not just how much is kept: a lower number also searches a smaller area.",
            "default": 20
          },
          "maxPlacesTotal": {
            "title": "Max places for the whole run",
            "minimum": 0,
            "type": "integer",
            "description": "A hard ceiling on the run, across every search term and location combined. <code>0</code> means no limit. Useful because the setting above applies to <b>each</b> search: three terms in two cities at 100 each can reach 600 places.<br><br>It counts <b>unique</b> places and is applied before any business details are fetched, so it bounds what the run costs. The cap is shared evenly across your searches, so every term and city is represented rather than the first ones using up the whole budget. Places named directly by a Google Maps URL are always kept first.",
            "default": 0
          },
          "maxReviewsPerPlace": {
            "title": "Max reviews per place",
            "minimum": 0,
            "maximum": 500,
            "type": "integer",
            "description": "Reviews to collect for each place, up to 500. <b>0 makes no review requests at all</b> — leave it at 0 if you only need business details, since that is the largest single reduction in work a run can make.",
            "default": 0
          },
          "reviewsSort": {
            "title": "Sort reviews by",
            "enum": [
              "mostRelevant",
              "newest"
            ],
            "type": "string",
            "description": "<b>Most relevant</b> is Google's own ordering — the same reviews, in the same order, that the place's Google Maps page shows. <b>Newest</b> returns the most recently added or edited reviews first.<br><br><b>A review start date takes precedence over this setting.</b> Set one below and collection switches to newest-first whatever is chosen here, because that is the only order in which the Actor can stop as soon as it reaches reviews older than the date. You are told in the log when that happens.",
            "default": "mostRelevant"
          },
          "reviewsStartDate": {
            "title": "Only reviews changed since",
            "type": "string",
            "description": "Leave empty to collect reviews in the order chosen above. Set a date and each place returns <b>only the reviews added or edited on or after it</b>, newest first — which is what makes a daily or weekly monitoring run cheap: the Actor stops as soon as it reaches older reviews instead of paging through everything.<br><br>The comparison uses a review's <b>last edited</b> time, not its original publication date, because that is the order Google returns reviews in. So a review written in 2019 and edited yesterday <b>is</b> included — which is usually what you want, since an edited review is new information. Every review carries both <code>publishedAtDate</code> and <code>lastEditedAtDate</code> if you need to tell them apart.<br><br>Dates with no time zone are read as UTC. Relative spans are counted back from the moment the run starts, so <code>25 hours</code> on a daily schedule gives you an hour of overlap and never misses a review that arrived mid-run. Needs <b>Max reviews per place</b> above 0, which also caps how many qualifying reviews come back."
          },
          "maxImagesPerPlace": {
            "title": "Max photos per place",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "Photo URLs to keep per place. Photos are about <b>half of a record that has no reviews</b> (median 52% across captured places), so lowering this makes a listings-only export markedly smaller. Once reviews are switched on they dominate instead and photos are a much smaller share. Set <code>0</code> if you do not need photos at all.<br><br>These are photos of the business. Reviewer profile pictures are not included here — each review carries its author's photo separately. Most places carry far fewer than the maximum (a median of 10 across captured places), so a lower count is normal rather than a sign of a problem, and no value here costs any extra requests.",
            "default": 50
          },
          "language": {
            "title": "Results language",
            "enum": [
              "en",
              "es",
              "fr",
              "de",
              "it",
              "pt-BR",
              "nl",
              "pl",
              "tr",
              "ru",
              "ar",
              "hi",
              "bn",
              "id",
              "ja",
              "ko",
              "zh-CN",
              "th",
              "vi",
              "af",
              "az",
              "ms",
              "bs",
              "ca",
              "da",
              "et",
              "es-419",
              "eu",
              "fil",
              "gl",
              "hr",
              "zu",
              "sw",
              "lv",
              "lt",
              "hu",
              "nb",
              "uz",
              "pt-PT",
              "ro",
              "sq",
              "sk",
              "sl",
              "fi",
              "sv",
              "is",
              "cs",
              "el",
              "bg",
              "ky",
              "mk",
              "mn",
              "sr",
              "uk",
              "kk",
              "hy",
              "he",
              "ur",
              "fa",
              "ne",
              "mr",
              "pa",
              "gu",
              "ta",
              "te",
              "kn",
              "ml",
              "si",
              "lo",
              "my",
              "ka",
              "am",
              "km",
              "zh-TW"
            ],
            "type": "string",
            "description": "Google returns names, categories, addresses and opening hours already translated, so this changes the data itself — not just labels.",
            "default": "en"
          }
        }
      },
      "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
                  }
                }
              },
              "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}