{
  "openapi": "3.0.1",
  "info": {
    "title": "Google Maps Reviews Scraper & Place Contact Details",
    "description": "Google Maps Reviews Scraper & Place Contact Details extracts business reviews, ratings, reviewer data, addresses, phone numbers, websites, opening hours, categories, and other public place information. Ideal for local market research, reputation analysis, lead generation, and competitor insights.",
    "version": "0.1",
    "x-build-id": "1cWozdYzp3PM8QdXr"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/scrapier~google-maps-reviews-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-scrapier-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/scrapier~google-maps-reviews-scraper/runs": {
      "post": {
        "operationId": "runs-sync-scrapier-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/scrapier~google-maps-reviews-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-scrapier-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": "📌🗺️ Place URLs To Enrich",
            "type": "array",
            "description": "🏢➡️☎️ Google Maps place URLs. Every review scraped from a URL here also carries that place's phone, website, opening hours, plus code, timezone and editorial summary. Plain strings and {\"url\": \"...\"} objects both work.",
            "items": {
              "type": "string"
            }
          },
          "placeIds": {
            "title": "🆔🏢 Place IDs To Enrich",
            "type": "array",
            "description": "🔑 Optional. Raw Google Place IDs (`ChIJ...`). Each one is resolved to its canonical Maps URL and enriched exactly like a pasted URL.",
            "items": {
              "type": "string"
            }
          },
          "includePlaceContact": {
            "title": "☎️✅ Attach Place Contact Details",
            "type": "boolean",
            "description": "☎️🌐 Attach the place's published contact block to every review row: `placePhone`, `placePhoneInternational`, `placeWebsite`, `placePlusCode`, `placeTimezone`, `placeEditorialSummary` and the weekly opening hours. Measured 2026-08-10: this data rides along on the `/maps/preview/place` response the scraper already downloads, so it costs **zero extra requests** and no extra time. Turn off only if you want review rows alone.",
            "default": true
          },
          "includeOpeningHours": {
            "title": "🕒📅 Include Weekly Opening Hours",
            "type": "boolean",
            "description": "🕒 Adds `placeOpeningHours` (7 rows of day + hours + calendar date), `placeOpeningHoursText` (one readable line) and `placeOpeningHoursToday` (today's row, resolved in the place's OWN timezone). Turn off for a narrower table.",
            "default": true
          },
          "maxPlacesToEnrich": {
            "title": "🚧🔢 Contact Enrichment Cap (places)",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "🛑 Hard safety cap on how many DISTINCT input places receive a contact block. It is a guard-rail, **not** a cost saver — the contact data is free (see above). Places beyond the cap still return their reviews, with `contactFetched: false` and null contact columns, and the skip is logged.",
            "default": 100
          },
          "onlyPlacesWithWebsite": {
            "title": "🌐🎯 Keep Only Places That Publish A Website",
            "type": "boolean",
            "description": "🌐 Drops every review row of a place whose Google listing has no website link. Dropped rows are never charged. The check runs after the place's reviews are collected, so a place with no website simply saves 0 rows and says so in the log.",
            "default": false
          },
          "onlyUnansweredReviews": {
            "title": "🙊📭 Keep Only Reviews With No Owner Reply",
            "type": "boolean",
            "description": "📭 Keeps only rows where `hasOwnerReply` is false — the actual work queue for a reputation-management outreach list. Dropped rows are never charged and the drop count is logged.",
            "default": false
          },
          "maxReviews": {
            "title": "🧾🔢 Reviews Per Place",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "📊🎚️ Maximum number of reviews to extract per place. Reviews are read by scrolling the live Maps feed, so large values take proportionally longer (roughly 5 s of scrolling budget per requested review, capped at 55 minutes per place).",
            "default": 10
          },
          "reviewsSort": {
            "title": "↕️🗂️ Feed Order",
            "enum": [
              "newest",
              "mostRelevant",
              "highestRanking",
              "lowestRanking"
            ],
            "type": "string",
            "description": "⭐↕️ Sort exactly like Google Maps: newest, most relevant, highest rating, or lowest rating.",
            "default": "newest"
          },
          "reviewsStartDateAbsolute": {
            "title": "📆🧭 Only Reviews On/After This Date",
            "type": "string",
            "description": "🗓️✅ Exact calendar date (YYYY-MM-DD). Reviews older than this cutoff are skipped. Google publishes only a relative age per review (\"3 months ago\"), so this cutoff is applied to the derived date and is accurate to the published bucket, not to the day.",
            "default": ""
          },
          "reviewsStartDateRelative": {
            "title": "⏳🔁 Or A Relative Window",
            "enum": [
              "",
              "7 days",
              "1 month",
              "3 months",
              "6 months",
              "1 year",
              "2 years"
            ],
            "type": "string",
            "description": "⌛📆 Relative time window, used when the absolute date is empty. Same bucket-level accuracy as the absolute cutoff.",
            "default": ""
          },
          "language": {
            "title": "🌍🔤 Maps Interface Language",
            "enum": [
              "en",
              "es",
              "fr",
              "de",
              "it",
              "pt",
              "nl",
              "bn",
              "hi",
              "ar",
              "tr",
              "id",
              "ja",
              "ko",
              "zh-CN"
            ],
            "type": "string",
            "description": "🗣️🌍 Interface language for the Maps pages that are scraped. Applied as `hl=<code>&gl=us` in the page URL, which is the only mechanism Google honours. Affects localized text such as `publishAt`, `categories`, `price` and the review-context chip labels. `publishedAtDate` is derived from the relative age and is most reliable with English.",
            "default": "en"
          },
          "personalData": {
            "title": "🪪🙈 Keep Reviewer Identity",
            "type": "boolean",
            "description": "🔒🙈 When disabled, `name`, `reviewerId`, `reviewerUrl`, `reviewerPhotoUrl` and `reviewUrl` are emitted as null in every row.",
            "default": true
          },
          "proxy": {
            "title": "🛰️🔌 Custom Proxy (optional)",
            "type": "object",
            "description": "🛡️⚙️ Optional custom proxy. Set `use_proxy: true` together with `host` and `port` to route the browser through your own proxy; `username`/`password` may stay empty for unauthenticated proxies. Leave as-is to use Apify Residential (US), which is the default transport and includes 3 automatic IP rotations."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}