{
  "openapi": "3.0.1",
  "info": {
    "title": "Google Maps Scraper - Places, Reviews, GPS & Place ID Finder",
    "description": "Google Maps scraper for places from a search: name, category, address, star rating, review count, GPS coordinates and Google's place IDs, one row per place. Add place links for their newest reviews. A town Google can't find gets a free row, not places from elsewhere. $0.27 per 1,000 rows.",
    "version": "0.1",
    "x-build-id": "TSlrBsinibiJDFL7c"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/dami_studio~google-maps-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-dami_studio-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/dami_studio~google-maps-scraper/runs": {
      "post": {
        "operationId": "runs-sync-dami_studio-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/dami_studio~google-maps-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-dami_studio-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": {
          "searchQueries": {
            "title": "Search queries",
            "type": "array",
            "description": "One or more Google Maps searches. Include the location in the text, e.g. \"coffee in Brooklyn\", \"dentists near Eiffel Tower\", \"hotels Lisbon\". You can also paste a search link copied from Google Maps; it runs at the part of the map the link shows. If Google Maps can't find the place after \"in\" or \"near\", or after \"à\", \"en\", \"près de\" or \"cerca de\" when the place starts with a capital letter, that search gets a free BAD_INPUT row instead of places from somewhere else. The same goes for a town it can't find next to a state it can, which it would otherwise search across the whole state.",
            "items": {
              "type": "string"
            }
          },
          "searchQuery": {
            "title": "Single search query (alternative)",
            "type": "string",
            "description": "A single search, if you prefer one box instead of the list above."
          },
          "reviewUrls": {
            "title": "Google Maps place URLs for reviews",
            "type": "array",
            "description": "Place links to read reviews from, newest first. placeUrls is accepted as an alias.",
            "items": {
              "type": "string"
            }
          },
          "placeUrls": {
            "title": "Place URLs (review alias)",
            "type": "array",
            "description": "Optional alias for reviewUrls.",
            "items": {
              "type": "string"
            }
          },
          "placeLinks": {
            "title": "Place links for place rows",
            "type": "array",
            "description": "Optional add-on. Google Maps place links, ?cid= links, short maps.app.goo.gl links or ChIJ place IDs: one place row each, with the same fields as a search row. For reviews from a link, use the field above. Needs a paid Apify plan.",
            "items": {
              "type": "string"
            }
          },
          "language": {
            "title": "Language",
            "type": "string",
            "description": "Google Maps interface language code (e.g. en, de, fr, es).",
            "default": "en"
          },
          "countryCode": {
            "title": "Country",
            "type": "string",
            "description": "Optional two-letter country, for example US, GB or DE. Leave it empty for the default."
          },
          "city": {
            "title": "City",
            "type": "string",
            "description": "Optional. Runs every search in this city, so \"coffee\" becomes \"coffee in Austin, TX\". Add the state or country when the name is common, like Austin, TX or Lyon, France, and leave the place out of the searches themselves. If Google Maps can't find the city, the run stops with a free BAD_INPUT row instead of returning places from somewhere else."
          },
          "county": {
            "title": "County",
            "type": "string",
            "description": "Optional. Runs every search in this county, like Travis County, TX. Works on its own or together with City, and is checked the same way. A search that goes straight to one business is checked by its address, which never names a county, so fill in City too for those."
          },
          "state": {
            "title": "State or region",
            "type": "string",
            "description": "Optional. Added to City and County, like TX or Bavaria, and checked the same way."
          },
          "postalCode": {
            "title": "Postal code",
            "type": "string",
            "description": "Optional. Runs every search in this postal code, like 78704, alone or with the fields above. Some countries search a postal code more widely than its own area; the place check catches a code Google cannot find."
          },
          "locations": {
            "title": "Locations",
            "type": "array",
            "description": "Optional. Several places in one run, like \"Austin, TX\" and \"Denver, CO\": every search runs in every place, and each pair counts as its own search. Up to 50 places and 200 searches a run. When this is filled, City, County, State and Postal code are not used. A place Google Maps can't find gets a free BAD_INPUT row and is skipped; the other places still run.",
            "items": {
              "type": "string"
            }
          },
          "maxItems": {
            "title": "Max places per query",
            "minimum": 1,
            "maximum": 500,
            "type": "integer",
            "description": "How many places to collect per search (the scraper scrolls the results feed to reach this). Website and phone come back on most places; rating, reviewCount, category and address can be null when Google omits them.",
            "default": 60
          },
          "maxReviewsPerPlace": {
            "title": "Max reviews per place",
            "minimum": 1,
            "maximum": 5000,
            "type": "integer",
            "description": "Maximum reviews to return per place URL or discovered place, up to 5,000.",
            "default": 50
          },
          "minRating": {
            "title": "Minimum star rating",
            "enum": [
              "any",
              "3",
              "3.5",
              "4",
              "4.5"
            ],
            "type": "string",
            "description": "Optional add-on. Only places rated at least this. Places with no rating are left out too. Needs a paid Apify plan.",
            "default": "any"
          },
          "websiteFilter": {
            "title": "Website",
            "enum": [
              "allPlaces",
              "withWebsite",
              "withoutWebsite"
            ],
            "type": "string",
            "description": "Optional add-on. Only places with a website, or only places without one. Needs a paid Apify plan.",
            "default": "allPlaces"
          },
          "categoryFilterWords": {
            "title": "Only these categories",
            "type": "array",
            "description": "Optional add-on. Keeps a place when one of its Google categories contains one of these words, like \"dentist\" or \"pizza\". Google has thousands of categories and some go by other names, so a word can miss a place you wanted; check a first run. Needs a paid Apify plan.",
            "items": {
              "type": "string"
            }
          },
          "nameMatch": {
            "title": "Match on the name",
            "enum": [
              "all",
              "contains",
              "exact"
            ],
            "type": "string",
            "description": "Optional add-on. \"Contains\" keeps places whose name holds the words of your search (without the place part), \"exact\" only places named exactly that. Useful for a brand, where Google pads the list with lookalikes. Needs a paid Apify plan.",
            "default": "all"
          },
          "onlyInsideArea": {
            "title": "Only places inside the named area",
            "type": "boolean",
            "description": "Optional add-on. Leaves out places Google lists for your City, County, State, Postal code or Locations, or for the place in a search's text, that sit outside it, like a dentist in a suburb next door. Businesses with no street address are kept and marked with serviceArea. Needs a paid Apify plan.",
            "default": false
          },
          "skipClosed": {
            "title": "Skip permanently closed places",
            "type": "boolean",
            "description": "Optional add-on. Leaves out places Google marks as permanently closed. Needs a paid Apify plan.",
            "default": false
          },
          "includeReviews": {
            "title": "Include reviews for search results",
            "type": "boolean",
            "description": "After collecting places, also return each place's newest reviews, up to Max reviews per place. Every review is a row of its own.",
            "default": false
          },
          "includeOwnerReplies": {
            "title": "Include owner replies",
            "type": "boolean",
            "description": "Attempt to include the business owner's visible reply for each review.",
            "default": true
          },
          "reviewsSort": {
            "title": "Review order",
            "enum": [
              "newest",
              "mostRelevant",
              "highest",
              "lowest"
            ],
            "type": "string",
            "description": "Which reviews come first, and so which ones you get when the cap is reached.",
            "default": "newest"
          },
          "reviewsSince": {
            "title": "Only reviews newer than",
            "type": "string",
            "description": "Optional. A date like 2026-09-01, or a span like 8 days, 2 weeks or 3 months. Reading stops at the first older review. Works with the newest order only. Needs a paid Apify plan."
          },
          "reviewKeywords": {
            "title": "Only reviews with these words",
            "type": "array",
            "description": "Optional add-on. Keeps reviews whose text, or Google's translation of it, holds one of these words, matched at the start of a word (\"tea\" finds \"teapot\", not \"steak\"). Reviews left out are not written as rows. Needs a paid Apify plan.",
            "items": {
              "type": "string"
            }
          },
          "includeReviewerDetails": {
            "title": "Include reviewer profile details",
            "type": "boolean",
            "description": "Adds each reviewer's profile link, photo, review and photo counts, and Local Guide flag to review rows.",
            "default": false
          },
          "skipReviewerNames": {
            "title": "Leave reviewer names out",
            "type": "boolean",
            "description": "Review rows come without the reviewer's name, for when you only need the ratings and text.",
            "default": false
          },
          "includeOrderLinks": {
            "title": "Order online links",
            "type": "boolean",
            "description": "Optional add-on. For each place found by a search, the ordering services Google lists for it. Switches on once its price is live.",
            "default": false
          },
          "includePlaceDetails": {
            "title": "Place details",
            "type": "boolean",
            "description": "Optional add-on. Adds reviewTopics (the words reviewers repeat, with how often), placesInside (the places inside this one, like the restaurants in a hotel) and ownerDescription (the text the business wrote about itself) to each place row. One more request a place. Needs a paid Apify plan.",
            "default": false
          },
          "includeLegalNotice": {
            "title": "Legal-notice details (Germany, Austria, Switzerland)",
            "type": "boolean",
            "description": "Optional add-on. For places whose website is German, Austrian or Swiss, reads the legal notice (Impressum) that site publishes and adds legalNotice: the company name, the directors or owners it names, the VAT id and the register number. Never an e-mail address or phone number from the page. Up to two requests to each business website. Needs a paid Apify plan.",
            "default": false
          },
          "maxPhotosPerPlace": {
            "title": "Photo links per place",
            "minimum": 0,
            "maximum": 10,
            "type": "integer",
            "description": "Optional. Photo links for each place found, one row each (type \"photo\"), links only, up to this many. Google sends a handful with each place (3 or 4 seen), not its whole gallery. 0 for none. Every photo row counts as a row. Needs a paid Apify plan.",
            "default": 0
          },
          "fields": {
            "title": "Only these fields",
            "type": "array",
            "description": "Optional. Field names to keep in each row, like name, phone and website; ok and type always stay. Leave empty for every field.",
            "items": {
              "type": "string"
            }
          },
          "notionConnector": {
            "title": "Notion connector (optional)",
            "type": "string",
            "description": "Optional. Write each place as a page into your Notion when the run finishes. Authorize a Notion connector once in Settings → API & Integrations → MCP connectors, then pick it here. Leave empty to skip (default), results are always saved to the dataset regardless."
          },
          "notionParentId": {
            "title": "Notion target data source ID",
            "type": "string",
            "description": "Optional. The Notion data source ID of the database to write into (only used if a Notion connector is set). Leave empty to create the pages privately in your workspace instead."
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "Optional. Leave this alone unless you need the run to go out through a particular network. Your own proxy servers are used exactly as given."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}