# Google Maps Scraper (HTTP / curl\_cffi) (`kitcunemia/google-maps-scraper-http`) Actor

Lightning-fast HTTP Google Maps scraper for lead generation. No browser = 5–10× cheaper. Returns 30+ fields per place: phone, website, address, owner, ratings, amenities. Quad-tree subdivision unlocks unlimited results per area. Chrome TLS impersonation bypasses Google anti-bot.

- **URL**: https://apify.com/kitcunemia/google-maps-scraper-http.md
- **Developed by:** [Kitcune Mia](https://apify.com/kitcunemia) (community)
- **Categories:** Lead generation, Developer tools, Automation
- **Stats:** 3 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

$1.60 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## 🗺️ Google Maps Scraper — HTTP / curl_cffi

> **The fastest, cheapest, most efficient Google Maps scraper on Apify.**
> Pure HTTP. No Chromium. No Playwright. No Selenium. Just raw speed and 30+ fields per place.

---

### ⚡ Why this scraper

|  | This actor | Typical browser-based scrapers |
|---|---|---|
| **Engine** | curl_cffi with TLS impersonation | Headless Chromium |
| **Memory** | ~512 MB is plenty | 2–4 GB minimum |
| **Speed** | **51 unique places in 3.7 seconds** (local, no proxy) | 60–120 seconds for the same set |
| **Cost on Apify** | Pennies per 1,000 places | 5–10× more compute units |
| **Coverage per area** | **Unlimited** via quad-tree subdivision | Capped at Google's ~120 per viewport |
| **Fields per place** | **30–40 fields** (full address parts, amenities tree, owner info, hotel data, etc.) | 15–25 typical |
| **Anti-bot** | Chrome TLS fingerprint, sticky residential sessions, fresh impersonation per request | Headless flag detection risk |
| **Resumability** | Auto-resumes after Apify migrations | Often re-scrapes from scratch |

---

### 🚀 Top 10 reasons to pick this scraper

1. **🔥 Blazing fast** — runs 5–10× faster than browser-based alternatives because there's no browser to boot, render, or close
2. **💰 Cheapest on Apify** — no Chromium = lowest memory footprint = lowest compute-unit cost
3. **🌍 Quad-tree subdivision** — breaks Google's hard ~120-results-per-area limit by recursively splitting saturated viewports into 4 quadrants. Scrape entire cities, not just neighborhoods
4. **📊 Maximum data per place** — 30+ fields per place including structured address parts, full amenities tree, place tags (LGBTQ+ friendly, women-owned, …), owner info, entrance coordinates, current open/closed status, next opening time, and rich hotel data
5. **🥷 TLS impersonation** — curl_cffi mimics real Chrome TLS fingerprints (Chrome 120/123/124/131 rotated per request) to bypass Google's anti-bot
6. **🌐 Sticky residential sessions** — each viewport gets its own Apify session ID so all paginated requests for one logical search hit the same residential IP. Cuts "weird traffic" challenges by ~80%
7. **🌎 Multi-language coverage** — re-search the same areas in additional languages to catch translations & regional categories you'd otherwise miss
8. **🔁 Multi-zoom expansion** — search each seed at zoom-N..zoom+N for +30–70% extra unique places
9. **♻️ Resume-ready** — auto-checkpoints every 30s + on Apify's `PERSIST_STATE` event. Migrations resume without re-pushing duplicates
10. **🛠 Battle-tested error handling** — detects consent-page redirects, captcha, 429s, and rotates intelligently. Fast-fails on deterministic 4xx (no retry storms)

---

### 📦 What you get — full output schema

Every place returns this rich JSON object (real example from a coffee shop in Manhattan):

```json
{
  "title": "Bird & Branch Coffee Roasters",
  "subTitle": "Family-run specialty coffee shop",
  "description": "Signature coffee drinks including burnt marshmallow, turmeric, & nut milks with pastries & toasts.",
  "categoryName": "Coffee shop",
  "categories": ["Coffee shop", "Cafe", "Corporate gift supplier", "Dessert shop"],

  "address": "359 W 45th St, New York, NY 10036, United States",
  "addressParts": {
    "street": "359 W 45th St",
    "city": "New York",
    "state": "New York",
    "postalCode": "10036",
    "neighborhood": "Manhattan",
    "countryCode": "US"
  },
  "neighborhood": "Manhattan",
  "street": "359 W 45th St",
  "city": "New York",
  "postalCode": "10036",
  "state": "New York",
  "countryCode": "US",
  "formattedLocality": "New York, NY, United States",

  "location": {"lat": 40.7602998, "lng": -73.9907758},
  "entranceLocation": {"lat": 40.7602896, "lng": -73.9908287},

  "phone": "+1 917-265-8444",
  "phoneUnformatted": "+19172658444",
  "website": "http://www.birdandbranch.com/",
  "websiteDisplay": "birdandbranch.com",

  "totalScore": 4.6,
  "openingHoursToday": {"day": "Wednesday", "hours": "7 AM–7:30 PM"},
  "currentStatus": "Closed · Opens 7 AM",
  "nextOpensAt": "06:30",

  "placeId": "ChIJTVhsxFNYwokRXgPwYnY0vgI",
  "fid": "0x89c25853c46c584d:0x2be347662f0035e",
  "cid": "197653116721562462",
  "kgmid": "/g/11hbtg2w_k",
  "url": "https://www.google.com/maps/search/?api=1&query=...&query_place_id=ChIJ...",

  "timezone": "America/New_York",
  "ownerName": "Bird & Branch Coffee Roasters",
  "ownerId": "105862650674626077989",

  "placeTags": ["Identifies as women-owned", "Identifies as Asian-owned"],
  "additionalInfo": {
    "Accessibility": [{"Wheelchair-accessible car park": true}],
    "Service options": [{"Dine-in": true}, {"Takeout": true}],
    "Payments": [{"NFC mobile payments": true}, {"Credit cards": true}]
  },

  "imagesCount": 944,
  "imageUrl": "https://lh6.googleusercontent.com/.../photo.jpg"
}
````

#### Hotel-specific extras

When the result is a hotel, you also get:

```json
{
  "hotelStars": "4 stars",
  "hotelPrice": "BYN 695",
  "hotelCheckInDate": "2026-04-30",
  "hotelCheckOutDate": "2026-05-01",
  "hotelAmenities": ["Free Wi-Fi", "Pool", "Pet-friendly"],
  "longDescription": "On renowned 42nd Street, this relaxed 44-story hotel is set amid Times Square's bustling theaters, shops and restaurants…"
}
```

***

### 🎯 Use cases

| Use case | Why this scraper wins |
|---|---|
| **Lead generation** | 84%+ phone & website coverage, unclaimed-business detection (`claimThisBusinessUrl`), owner names |
| **Competitor monitoring** | Quad-tree scans entire metro areas; structured `addressParts` makes geo-grouping trivial |
| **Market analysis** | `additionalInfo` amenities tree + `placeTags` enables segmentation by accessibility, payment options, ownership demographics |
| **Hotel/travel platforms** | Hotel-specific block: stars, price, check-in/out dates, amenities, full description |
| **SEO/local SEO** | Owner names, claim status, kgmid (Knowledge Graph IDs), canonical URLs |
| **POI database building** | placeId + fid + cid + kgmid = stable cross-reference identifiers |

***

### 🏁 Quick start

#### Option 1 — Apify Console (no code)

1. Click **Try for free** on the actor page
2. Fill in the input form:
   - **Search terms**: `["coffee", "cafe", "bakery"]`
   - **Location**: `Brooklyn, New York, USA`
   - Leave defaults for everything else (they're tuned for max coverage)
3. Click **Start**
4. Watch the dataset populate live in the **Dataset** tab
5. Export as JSON, CSV, Excel, or pull via API

#### Option 2 — API call

```bash
curl -X POST https://api.apify.com/v2/acts/YOUR_USERNAME~google-maps-scraper-http/runs \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_APIFY_TOKEN" \
  -d '{
    "searchStringsArray": ["restaurant", "bar", "cafe"],
    "locationQuery": "SoHo, Manhattan, New York",
    "maxCrawledPlacesPerSearch": 500,
    "maxSubdivisionDepth": 4,
    "concurrency": 8
  }'
```

#### Option 3 — Python SDK

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("YOUR_USERNAME/google-maps-scraper-http").call(run_input={
    "searchStringsArray": ["dentist", "pediatrician"],
    "locationQuery": "Austin, Texas",
    "maxCrawledPlacesPerSearch": 1000,
    "additionalLanguages": ["es"],  ## bilingual coverage
})
for place in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(place["title"], place.get("phone"), place.get("website"))
```

***

### 🎛 Input parameters

#### What to scrape

| Field | Type | Default | Description |
|---|---|---|---|
| **`searchStringsArray`** | string\[] | `["restaurant"]` | Search terms. Each runs across all viewports & languages. |
| **`locationQuery`** | string | `"Times Square, …"` | Free-text location, geocoded via OpenStreetMap. |
| **`customGeolocation`** | object | — | Optional GeoJSON Polygon/MultiPolygon/Point that overrides `locationQuery`. |
| **`startUrls`** | string\[] | — | Direct `google.com/maps/place/…` URLs to scrape without going through search. |

#### Coverage controls

| Field | Type | Default | Description |
|---|---|---|---|
| **`maxCrawledPlacesPerSearch`** | int | `500` | Hard cap per search term across all viewports. |
| **`maxPlacesPerViewport`** | int | `80` | Cap per single viewport (Google maxes at ~120). |
| **`enableSubdivision`** | bool | `true` | Quad-tree split when a viewport saturates — **leave on**. |
| **`maxSubdivisionDepth`** | int | `4` | Max recursive splits. depth=4 → up to 256 viewports per seed. |
| **`zoom`** | int | auto | Override the seed viewport's Google Maps zoom level (1–21). |
| **`multiZoomDelta`** | int | `0` | Search each seed at zoom-N..zoom+N. delta=1 → +30-70% extra places at 3× cost. |
| **`language`** | string | `"en"` | Google UI language (`hl=`). |
| **`additionalLanguages`** | string\[] | `[]` | Extra languages to re-search in. Useful for bilingual cities. |

#### Performance & proxy

| Field | Type | Default | Description |
|---|---|---|---|
| **`concurrency`** | int | `8` | Parallel viewport searches. Each on its own sticky proxy session. |
| **`requestTimeoutSecs`** | int | `15` | Per-HTTP-request timeout. |
| **`minRequestIntervalMs`** | int | `0` | Global throttle (ms) between any two requests. Useful without residential proxies. |
| **`proxyConfiguration`** | object | Apify residential | Proxy settings. **Residential is strongly recommended.** |

***

### 📈 Tips for maximum coverage & speed

#### 🎯 Maximum coverage

```json
{
  "searchStringsArray": ["restaurant", "cafe", "bar", "bakery"],
  "locationQuery": "Manhattan, New York",
  "maxCrawledPlacesPerSearch": 5000,
  "maxSubdivisionDepth": 5,
  "multiZoomDelta": 1,
  "additionalLanguages": ["es", "zh"],
  "concurrency": 12
}
```

This will likely return **2,000–5,000 unique restaurants** across Manhattan — far beyond Google's per-area limit.

#### ⚡ Maximum speed (small areas)

```json
{
  "searchStringsArray": ["coffee"],
  "locationQuery": "Times Square",
  "maxCrawledPlacesPerSearch": 50,
  "enableSubdivision": false,
  "concurrency": 4
}
```

Returns ~40-50 places in **under 5 seconds**.

#### 💎 Use multiple search terms instead of categories

Google's `categoryName` filter is brittle — a place tagged only `"Coffee shop"` won't match a `"Cafe"` query. Pass several related terms instead:

```json
"searchStringsArray": ["coffee", "cafe", "espresso bar", "coffee roaster"]
```

The actor automatically deduplicates by `placeId` so overlapping results are free.

#### 🏘 Scrape multiple non-contiguous areas

Use `customGeolocation` with a `MultiPolygon` to scrape, e.g., all five NYC boroughs in one run:

```json
{
  "type": "MultiPolygon",
  "coordinates": [
    [[[-74.05, 40.70], [-73.90, 40.70], [-73.90, 40.85], [-74.05, 40.85], [-74.05, 40.70]]],
    [[[-73.97, 40.55], [-73.85, 40.55], [-73.85, 40.62], [-73.97, 40.62], [-73.97, 40.55]]]
  ]
}
```

***

### 📤 Output

Results stream into the actor's **default dataset** as you scrape — no waiting until the end. Three pre-built dataset views are available:

- **Overview** — title, category, address, contacts, rating
- **Lead generation** — for sales: phone, website, owner, claim status
- **Hotels** — stars, price, check-in/out, amenities

Export formats supported by Apify:

- 📄 JSON / JSON Lines
- 📊 CSV / Excel
- 🌐 HTML / RSS
- 📡 API (paginated)

***

### ❓ FAQ

**Q: How does this compare to the official Google Places API?**
A: Google's API is rate-limited, expensive at scale, capped at 60 results per query, and missing many fields. This actor has no quotas, returns more data per place, and costs a fraction.

**Q: Will I get blocked?**
A: Not if you use Apify residential proxies (the default). The actor uses chrome TLS impersonation (rotated per request), sticky sessions per viewport, and intelligent backoff. We tested 1000+ requests with zero captcha hits.

**Q: How many places can I get per area?**
A: With `enableSubdivision=true` and `maxSubdivisionDepth=4`, you can scrape thousands of places per city. Google's hard limit is ~120 per single viewport — quad-tree subdivision recursively splits saturated areas to break it.

**Q: Does this extract reviews?**
A: **No.** Google's `/maps/preview/review/listentitiesreviews` endpoint requires browser-bound session tokens that JavaScript constructs from in-memory state — impossible to obtain from HTTP-only requests. If you need reviews, use a browser-based scraper (which costs 5–10× more compute). For the same reason, full week opening hours, popular times, and photo lists aren't extractable HTTP-only. Everything else IS.

**Q: Which fields are 100% reliable?**
A: title, categories, full structured address (street/city/state/postal/country), coordinates, placeId, fid, cid, kgmid, totalScore (rating), URL, timezone, ownerName, imagesCount. Phone & website are present on 84%+ of places (only places without listed contacts are missing them).

**Q: Can I resume an interrupted run?**
A: Yes — state is checkpointed every 30 seconds and on Apify's `PERSIST_STATE` event. Migrated runs auto-resume without re-pushing duplicates.

**Q: Multi-language passes — when should I use them?**
A: When scraping non-English areas (e.g. Tokyo, Mexico City, Berlin) — Google returns slightly different category names and translations per `hl` setting. Each language costs 1× the search budget but typically catches 5–15% more unique places.

***

### 🔧 Honest limitations

We believe in being upfront. Here's what this scraper **does not** extract:

| Field | Why not |
|---|---|
| Review text & individual reviews | Endpoint requires browser-bound session tokens |
| Full week opening hours | Only "today" is in the search XHR |
| Popular times histogram | Browser-only XHR |
| Photo URLs (per-photo list) | Browser-only XHR (only `imagesCount` and a thumbnail URL are HTTP-accessible) |
| Q\&A | Browser-only XHR |
| `reviewsCount` for non-hotels | Google has stripped it from the search XHR for restaurants/retail/etc. |

If any of the above are critical for your use case, you'll need a browser-based scraper (which will be **5–10× slower and more expensive**). For the 95% of users who just need leads, addresses, contacts, ratings, and place identifiers — **this scraper is the optimal choice**.

***

### 🛠 Tech stack

- **`curl_cffi`** — TLS-impersonation HTTP client (Chrome fingerprint rotation)
- **`apify` SDK** ≥ 3.3.0 — Actor runtime, dataset, KV store, proxy
- **`crawlee`** ≥ 1.5.0 — Used as a browserforge bug workaround dependency
- **Python 3.12** — Slim Apify base image, no system Chromium installed

No Node.js. No browser. No headless detection risk. Just Python + curl.

***

### 📜 License & feedback

Built by independent developers. Open to feature requests on the actor's **Issues** tab.

If this scraper saves you compute units, leave a ⭐️ review on the Apify Store!

# Actor input Schema

## `searchStringsArray` (type: `array`):

Search queries to scrape, e.g. \['restaurant', 'cafe', 'pub']. Each term searches independently across all seed viewports and languages.

## `locationQuery` (type: `string`):

Free-text location, e.g. 'New York, USA' or 'Manhattan'. Resolved via OpenStreetMap Nominatim. Ignored if customGeolocation is set.

## `customGeolocation` (type: `object`):

GeoJSON Polygon, MultiPolygon, or Point. Overrides locationQuery. Point requires 'radiusKm'. MultiPolygon yields one seed per polygon.

## `startUrls` (type: `array`):

Direct google.com/maps/place/... URLs. Scraped without going through search.

## `maxCrawledPlacesPerSearch` (type: `integer`):

Hard cap per term across all viewports & languages. Quad-tree subdivision stops when this is hit. Default 500 — increase for dense city-scale scraping.

## `maxPlacesPerViewport` (type: `integer`):

Per-viewport cap. Google itself returns ≤120 per viewport scroll; values above 120 have no effect for one viewport.

## `enableSubdivision` (type: `boolean`):

When a viewport saturates (≥18 new of 20 first-page results), split into 4 quadrants and recurse. This is what unlocks scraping >120 results per area. Leave on.

## `maxSubdivisionDepth` (type: `integer`):

Max recursive splits. Each level multiplies viewports by 4 (depth=4 → up to 256 viewports per seed).

## `language` (type: `string`):

Google UI language (hl=). Affects place names, opening-hours strings, tag labels, etc.

## `additionalLanguages` (type: `array`):

Extra language codes to re-search the same areas. Useful for non-English regions where Google returns different translations & categories per language. Each language adds ~Nx searches.

## `zoom` (type: `integer`):

Override auto-derived zoom of the seed viewport. Higher zoom = denser results before subdivision.

## `multiZoomDelta` (type: `integer`):

Search each seed at zoom-N..zoom+N to maximize coverage. delta=1 → 3 zoom levels per seed (3x cost, +30-70% unique places). delta=0 disables.

## `concurrency` (type: `integer`):

How many viewports run in parallel. Each on its own sticky proxy session. Tune up for speed, down if rate-limited.

## `requestTimeoutSecs` (type: `integer`):

Per-HTTP-request timeout in seconds. Increase if your residential proxies are slow.

## `minRequestIntervalMs` (type: `integer`):

Global throttle: minimum gap between any two outbound requests. 0 = disabled.

## `proxyConfiguration` (type: `object`):

Apify proxy settings. Residential proxies are strongly recommended.

## Actor input object example

```json
{
  "searchStringsArray": [
    "restaurant"
  ],
  "locationQuery": "Times Square, Manhattan, New York",
  "maxCrawledPlacesPerSearch": 500,
  "maxPlacesPerViewport": 80,
  "enableSubdivision": true,
  "maxSubdivisionDepth": 4,
  "language": "en",
  "additionalLanguages": [],
  "multiZoomDelta": 0,
  "concurrency": 8,
  "requestTimeoutSecs": 15,
  "minRequestIntervalMs": 0,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchStringsArray": [
        "restaurant"
    ],
    "locationQuery": "Times Square, Manhattan, New York",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("kitcunemia/google-maps-scraper-http").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchStringsArray": ["restaurant"],
    "locationQuery": "Times Square, Manhattan, New York",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("kitcunemia/google-maps-scraper-http").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchStringsArray": [
    "restaurant"
  ],
  "locationQuery": "Times Square, Manhattan, New York",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call kitcunemia/google-maps-scraper-http --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=kitcunemia/google-maps-scraper-http",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Google Maps Scraper (HTTP / curl_cffi)",
        "description": "Lightning-fast HTTP Google Maps scraper for lead generation. No browser = 5–10× cheaper. Returns 30+ fields per place: phone, website, address, owner, ratings, amenities. Quad-tree subdivision unlocks unlimited results per area. Chrome TLS impersonation bypasses Google anti-bot.",
        "version": "0.5",
        "x-build-id": "voAxb6nXiahe1pffy"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/kitcunemia~google-maps-scraper-http/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-kitcunemia-google-maps-scraper-http",
                "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/kitcunemia~google-maps-scraper-http/runs": {
            "post": {
                "operationId": "runs-sync-kitcunemia-google-maps-scraper-http",
                "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/kitcunemia~google-maps-scraper-http/run-sync": {
            "post": {
                "operationId": "run-sync-kitcunemia-google-maps-scraper-http",
                "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",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Search queries to scrape, e.g. ['restaurant', 'cafe', 'pub']. Each term searches independently across all seed viewports and languages.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "locationQuery": {
                        "title": "Location",
                        "type": "string",
                        "description": "Free-text location, e.g. 'New York, USA' or 'Manhattan'. Resolved via OpenStreetMap Nominatim. Ignored if customGeolocation is set."
                    },
                    "customGeolocation": {
                        "title": "Custom geolocation (GeoJSON)",
                        "type": "object",
                        "description": "GeoJSON Polygon, MultiPolygon, or Point. Overrides locationQuery. Point requires 'radiusKm'. MultiPolygon yields one seed per polygon."
                    },
                    "startUrls": {
                        "title": "Direct Google Maps URLs",
                        "type": "array",
                        "description": "Direct google.com/maps/place/... URLs. Scraped without going through search.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "maxCrawledPlacesPerSearch": {
                        "title": "Max places per search term",
                        "minimum": 1,
                        "maximum": 100000,
                        "type": "integer",
                        "description": "Hard cap per term across all viewports & languages. Quad-tree subdivision stops when this is hit. Default 500 — increase for dense city-scale scraping.",
                        "default": 500
                    },
                    "maxPlacesPerViewport": {
                        "title": "Max places per viewport",
                        "minimum": 1,
                        "maximum": 120,
                        "type": "integer",
                        "description": "Per-viewport cap. Google itself returns ≤120 per viewport scroll; values above 120 have no effect for one viewport.",
                        "default": 80
                    },
                    "enableSubdivision": {
                        "title": "Quad-tree subdivision",
                        "type": "boolean",
                        "description": "When a viewport saturates (≥18 new of 20 first-page results), split into 4 quadrants and recurse. This is what unlocks scraping >120 results per area. Leave on.",
                        "default": true
                    },
                    "maxSubdivisionDepth": {
                        "title": "Max subdivision depth",
                        "minimum": 0,
                        "maximum": 7,
                        "type": "integer",
                        "description": "Max recursive splits. Each level multiplies viewports by 4 (depth=4 → up to 256 viewports per seed).",
                        "default": 4
                    },
                    "language": {
                        "title": "Primary language",
                        "type": "string",
                        "description": "Google UI language (hl=). Affects place names, opening-hours strings, tag labels, etc.",
                        "default": "en"
                    },
                    "additionalLanguages": {
                        "title": "Additional languages",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Extra language codes to re-search the same areas. Useful for non-English regions where Google returns different translations & categories per language. Each language adds ~Nx searches.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "zoom": {
                        "title": "Initial zoom",
                        "minimum": 1,
                        "maximum": 21,
                        "type": "integer",
                        "description": "Override auto-derived zoom of the seed viewport. Higher zoom = denser results before subdivision."
                    },
                    "multiZoomDelta": {
                        "title": "Multi-zoom expansion (±N)",
                        "minimum": 0,
                        "maximum": 3,
                        "type": "integer",
                        "description": "Search each seed at zoom-N..zoom+N to maximize coverage. delta=1 → 3 zoom levels per seed (3x cost, +30-70% unique places). delta=0 disables.",
                        "default": 0
                    },
                    "concurrency": {
                        "title": "Concurrent tasks",
                        "minimum": 1,
                        "maximum": 30,
                        "type": "integer",
                        "description": "How many viewports run in parallel. Each on its own sticky proxy session. Tune up for speed, down if rate-limited.",
                        "default": 8
                    },
                    "requestTimeoutSecs": {
                        "title": "Per-request HTTP timeout (s)",
                        "minimum": 5,
                        "maximum": 60,
                        "type": "integer",
                        "description": "Per-HTTP-request timeout in seconds. Increase if your residential proxies are slow.",
                        "default": 15
                    },
                    "minRequestIntervalMs": {
                        "title": "Min interval between requests (ms)",
                        "minimum": 0,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Global throttle: minimum gap between any two outbound requests. 0 = disabled.",
                        "default": 0
                    },
                    "proxyConfiguration": {
                        "title": "Proxy",
                        "type": "object",
                        "description": "Apify proxy settings. Residential proxies are strongly recommended.",
                        "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
                                    }
                                }
                            },
                            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
