{
  "openapi": "3.0.1",
  "info": {
    "title": "Google Maps Reviews Scraper $0.25+💰 Replies · Ratings · Search",
    "description": "Only [$0.25+💰 per 1K] Extract Google Maps reviews from $0.25/1K — by text search (\"dentists in Austin TX\"), place URL, Place ID, CID or FID. Owner replies, likes, review language + original text, trip details, star/keyword/date filters, GDPR mode. Export JSON/CSV, run via API, schedule or integrate",
    "version": "0.0",
    "x-build-id": "SRdSIXAQ5c0CChtOq"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/memo23~google-maps-reviews-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-memo23-google-maps-reviews-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/memo23~google-maps-reviews-scraper/runs": {
      "post": {
        "operationId": "runs-sync-memo23-google-maps-reviews-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/memo23~google-maps-reviews-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-memo23-google-maps-reviews-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": {
          "startUrls": {
            "title": "Start URLs",
            "type": "array",
            "description": "URLs to start with. Supports Google Maps place URLs (https://www.google.com/maps/place/...), review detail URLs (https://www.google.com/maps/reviews/...), shortened mobile links (https://maps.app.goo.gl/...), Maps search URLs with query_place_id, and Google Search result URLs that include the reviews panel fragment (https://www.google.com/search?q=...#lrd=0x...:0x...,1,,,,).",
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "placeIds": {
            "title": "Google Place IDs",
            "type": "array",
            "description": "Array of Google Place IDs to scrape reviews for. Each Place ID should be a string like 'ChIJrTLr-GyuEmsRBfyf1GD_LAY'.",
            "items": {
              "type": "string"
            }
          },
          "FIDs": {
            "title": "Google Feature IDs",
            "type": "array",
            "description": "Array of Google Feature IDs to scrape reviews for. Each Feature ID should be a string like '0x89c25966dcad44b7:0x5cb022a289de6b19'.",
            "items": {
              "type": "string"
            }
          },
          "CIDs": {
            "title": "Google CIDs",
            "type": "array",
            "description": "Array of Google CIDs to scrape reviews for. Each CID should be a string like '15792901685599310349'.",
            "items": {
              "type": "string"
            }
          },
          "contributorUrls": {
            "title": "Reviewer profiles (contributor URLs or IDs)",
            "type": "array",
            "description": "Google Maps reviewer profile URLs (`https://www.google.com/maps/contrib/1234…/reviews`) or bare contributor IDs. Returns that reviewer's most recent reviews across every place they reviewed, with the place's name, address, coordinates, rating and total on each row, the reviewer's exact Local Guide level and points, and each review's original publication date. Google shows visitors only the ten most recent reviews of a profile (its own contributor page stops there too), so expect up to ten rows per profile. Profile URLs among the start URLs are handled the same way.",
            "items": {
              "type": "string"
            }
          },
          "searchQueries": {
            "title": "🆕 Search queries",
            "type": "array",
            "description": "Scrape reviews for every place matching a text search — e.g. `dentists in Austin TX`, `hotels in Kastoria`, `vegan restaurants Berlin`. Include the city/area in the query. Each query is capped by \"Max places per search query\" below. Combine freely with Start URLs / place IDs.",
            "items": {
              "type": "string"
            }
          },
          "maxPlacesPerQuery": {
            "title": "Max places per search query",
            "minimum": 1,
            "maximum": 60,
            "type": "integer",
            "description": "Cap on how many matching places each search query expands to (1-60). The global \"Number of reviews\" cap still applies across all places.",
            "default": 20
          },
          "searchLocation": {
            "title": "Search location",
            "type": "string",
            "description": "Optional location appended to every search query — `dentists` + `Austin, TX` runs as `dentists in Austin, TX`. Skipped for queries that already contain it."
          },
          "searchCoordinates": {
            "title": "Search coordinates (lat,lng)",
            "type": "string",
            "description": "Optional map center for Search queries, e.g. `40.7128,-74.0060` to run `coffee shops` around New York. Queries that do not name a place need it. For small towns and villages it also keeps results local: Google's search results shift with the map position even when the query names the town."
          },
          "sort": {
            "title": "Sort Reviews By",
            "enum": [
              "mostRelevant",
              "newest",
              "highestRating",
              "lowestRating"
            ],
            "type": "string",
            "description": "Define how reviews should be sorted.",
            "default": "newest"
          },
          "language": {
            "title": "Language",
            "type": "string",
            "description": "Language code for the reviews (e.g., 'en', 'de', 'es', 'fr').",
            "default": "en"
          },
          "region": {
            "title": "Region",
            "type": "string",
            "description": "Two-letter country code passed to Google as the `gl` parameter — biases result ranking and regional variants (e.g. `US`, `GB`, `DE`, `GR`). Default `US`.",
            "default": "US"
          },
          "dateNewerThan": {
            "title": "Only scrape reviews newer than",
            "pattern": "^(\\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$|^(\\d+)\\s*(minute|hour|day|week|month|year)s?$",
            "type": "string",
            "description": "Either absolute date (e.g. 2024-05-03) or relative date from now into the past (e.g. 8 days, 3 months). JSON input also supports adding time in both absolute (ISO standard, e.g. 2024-05-03T20:00:00) and relative (e.g. 3 hours) formats. Absolute time is always interpreted in the UTC timezone, not your local timezone - please convert accordingly. Supported relative date & time units: minutes, hours, days, weeks, months, years.\n\n⚠️ Heads up: If this parameter is specified, you must choose the 'Newest' sort by value. The reason for this is that with this parameter entered, the actor stops scraping reviews as soon as it finds the first review that's older than the specified date. If the sorting is not set to 'Newest', it might encounter a review older than the specified date before it reaches the desired review count and not scrape the desired amount of reviews."
          },
          "dateOlderThan": {
            "title": "Only scrape reviews older than [date]",
            "type": "string",
            "description": "Upper date bound — only reviews posted ON or BEFORE this date. Combine with \"Only scrape reviews newer than\" for an exact date window. Formats: `YYYY-MM-DD` or relative like `3 months`."
          },
          "filterKeyword": {
            "title": "Filter reviews by keyword",
            "type": "string",
            "description": "Only keep reviews whose text (including original-language text and the owner's response) contains this keyword, case-insensitive. E.g. `breakfast`, `parking`, `rude`."
          },
          "filterStars": {
            "title": "Filter by star rating",
            "type": "array",
            "description": "Only keep reviews with these star ratings. E.g. pick `1` and `2` to mine complaints, or `5` for testimonials. Leave empty for all ratings.",
            "items": {
              "type": "string",
              "enum": [
                "1",
                "2",
                "3",
                "4",
                "5"
              ],
              "enumTitles": [
                "1 star",
                "2 stars",
                "3 stars",
                "4 stars",
                "5 stars"
              ]
            }
          },
          "reviewsOrigin": {
            "title": "Reviews origin",
            "enum": [
              "all",
              "google"
            ],
            "type": "string",
            "description": "Google aggregates some reviews from third-party platforms. `google` keeps only native Google reviews; `all` (default) keeps everything. Each row carries a `review_origin` field either way.",
            "default": "all"
          },
          "personalData": {
            "title": "Include reviewer personal data",
            "type": "boolean",
            "description": "When OFF, reviewer-identifying fields (name, profile URL, photo, reviewer id) are redacted from the output — useful for GDPR-sensitive pipelines. Review text and ratings are kept.",
            "default": true
          },
          "includePlaceDetails": {
            "title": "Include place details on each row",
            "type": "boolean",
            "description": "ON by default: stamps every row with the place's overall rating, categories, coordinates, full address and canonical name (`place_rating`, `place_categories`, `place_latitude`/`place_longitude`, `place_address`), and fills `placeName` for place-ID/CID/FID inputs. Two extra requests per place. `place_reviews_count` is filled only when Google includes the total in its place record — it does not for every business.",
            "default": true
          },
          "countAllReviews": {
            "title": "Count all reviews (exact total)",
            "type": "boolean",
            "description": "Google omits the total review count from its place record for many businesses, leaving `place_reviews_count` empty. Turn this on to walk the whole review list once per place purely to count it (one request per 20 reviews, capped at 10,000 reviews). Only used for places where Google does not provide the total; expensive for very large places.",
            "default": false
          },
          "includeAuthorDetails": {
            "title": "Include author details (Local Guide level, totals)",
            "type": "boolean",
            "description": "One extra request per reviewer (cached for the run) fills `author_local_guide_level` (the exact level, not the floor), `author_points`, `author_reviews_total`, `author_ratings_total`, `author_photos_total`, and `time_published_original` for reviews that are among the reviewer's ten most recent. Skipped when `personalData` is off.",
            "default": false
          },
          "resolveEditedDates": {
            "title": "Recover original dates of edited reviews",
            "type": "boolean",
            "description": "Google's place review list keeps only the edit date of an edited review. This looks each edited review up on its author's profile, which still carries the original timestamp, and fills `time_published_original` plus `published_at_floor` with `published_at_precision: \"exact\"` when found (the review has to be among that author's ten most recent). One request per edited review's author, cached for the run; cheaper than \"Include author details\" when only the dates matter.",
            "default": false
          },
          "translateTo": {
            "title": "Translate reviews to [language]",
            "type": "string",
            "description": "Language code like `en`, `de`, `es`. Reviews written in another language get `review_text_translated` + `review_language_translated` filled via Google Translate. Leave empty for no translation."
          },
          "maxItems": {
            "title": "Number of reviews",
            "type": "integer",
            "description": "Maximum number of reviews to scrape per run",
            "default": 100
          },
          "maxReviewsPerPlace": {
            "title": "Max reviews per place",
            "minimum": 1,
            "type": "integer",
            "description": "Cap per place, on top of the global \"Number of reviews\". With search queries, `50` here and `1000` globally gives up to 50 reviews from each place instead of the fastest places consuming the whole budget. Leave empty for no per-place cap."
          },
          "maxConcurrency": {
            "title": "Max Concurrency",
            "type": "integer",
            "description": "Maximum number of pages that can be processed at the same time.",
            "default": 100
          },
          "minConcurrency": {
            "title": "Min Concurrency",
            "type": "integer",
            "description": "Minimum number of pages that will be processed at the same time.",
            "default": 1
          },
          "maxRequestRetries": {
            "title": "Max Request Retries",
            "type": "integer",
            "description": "Number of times the crawler will retry a failed request before giving up. A request Google keeps rate-limiting (HTTP 429) through every proxy is dropped after at most 6 attempts, even if this number is higher.",
            "default": 10
          },
          "proxy": {
            "title": "Proxy configuration (not used)",
            "type": "object",
            "description": "Not used. The scraper manages its own route to Google: it connects directly first and falls back to its own residential proxies when Google refuses a request, so you don't need to set or pay for a proxy. The field stays here so existing inputs and tasks keep working.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ]
            }
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}