{
  "openapi": "3.0.1",
  "info": {
    "title": "Google Maps Email Extractor & Lead Scraper",
    "description": "Google Maps email extractor API: business emails, graded deliverability and a 0-100 lead score for $7 per 1,000 leads. Finds contact pages under their native name (impressum, kapcsolat, contatti +44, ten languages); MX, SPF, DMARC, catch-all checks. Local business email finder for B2B leads.",
    "version": "1.4",
    "x-build-id": "hHpFl2ADuq0BbslQK"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/highbrow_fame~google-maps-email-extractor/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-highbrow_fame-google-maps-email-extractor",
        "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/highbrow_fame~google-maps-email-extractor/runs": {
      "post": {
        "operationId": "runs-sync-highbrow_fame-google-maps-email-extractor",
        "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/highbrow_fame~google-maps-email-extractor/run-sync": {
      "post": {
        "operationId": "run-sync-highbrow_fame-google-maps-email-extractor",
        "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": "REQUIRED unless you set startUrls: the run needs at least one of the two, and it will stop immediately if both are empty. List of search queries to use on Google Maps (e.g., 'restaurants in Budapest', 'dentists in London'). Each query will produce a separate search.",
            "items": {
              "type": "string"
            }
          },
          "startUrls": {
            "title": "Google Maps URLs",
            "type": "array",
            "description": "An alternative to searchQueries: supply one and leave the other empty. Direct Google Maps search result URLs. Use this if you already have specific Google Maps URLs to scrape.",
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "maxResults": {
            "title": "Maximum Results Per Query",
            "minimum": 0,
            "maximum": 1000,
            "type": "integer",
            "description": "Maximum number of business listings to extract per search query. Set to 0 for unlimited. Default and form prefill: 25, enough to judge output quality on a real market. Runtime is roughly 70 s of startup plus 5-8 s per lead, so no run returns within a 30-45 s tool-call window: if you call this Actor programmatically or from an AI agent, pass maxResults explicitly, poll the run, then read the dataset. For production runs use 100-1000 and raise maxRunSeconds to match (the run stops at that time budget). Billing: $0.007 per delivered lead on the Free plan, $0.006 Bronze, $0.005 Silver, $0.0045 on Gold, Platinum and Diamond (all enrichment included at every tier), plus a $0.015/GB run-start fee ($0.06 on the 4 GB default, the same on every plan). Example on the Free plan: 100 leads = $0.76, 1,000 leads = $7.06. Bigger runs are cheaper per lead because the start fee amortises. Runs of several hundred leads can also need a longer Apify run timeout (Start new run, Options, Timeout). The scraper estimates the runtime at startup and, with autoExtend on, restarts itself with a longer timeout if your settings would not fit.",
            "default": 25
          },
          "scrapeEmails": {
            "title": "Scrape Emails from Websites",
            "type": "boolean",
            "description": "Visit each business website to extract email addresses. Disabling this speeds up the scraper significantly.",
            "default": true
          },
          "scrapeSocials": {
            "title": "Scrape Social Media Links",
            "type": "boolean",
            "description": "Extract social media profile links (Facebook, Instagram, LinkedIn, Twitter) from business websites.",
            "default": true
          },
          "language": {
            "title": "Language",
            "enum": [
              "en",
              "de",
              "fr",
              "es",
              "it",
              "pt",
              "nl",
              "hu",
              "pl",
              "cs",
              "sk",
              "ro",
              "bg",
              "hr",
              "sl",
              "sr",
              "bs",
              "mk",
              "sq",
              "el",
              "tr",
              "ar",
              "he",
              "ja",
              "ko",
              "zh",
              "th",
              "vi",
              "id",
              "ms",
              "fil",
              "hi",
              "bn",
              "ta",
              "te",
              "ml",
              "kn",
              "mr",
              "gu",
              "pa",
              "ur",
              "fa",
              "ru",
              "uk",
              "sv",
              "no",
              "da",
              "fi"
            ],
            "type": "string",
            "description": "Language code for Google Maps results (e.g., 'en', 'de', 'hu').",
            "default": "en"
          },
          "enrichMetaAds": {
            "title": "Enrich with Meta Ad Library lookup URL",
            "type": "boolean",
            "description": "When enabled, the scraper fetches each business's Facebook page to extract the numeric page ID, then builds a targeted Meta Ad Library URL (active ads only). Adds ~1 request per business with a Facebook URL. Great for identifying actively-advertising leads (high purchase intent).",
            "default": false
          },
          "validateEmails": {
            "title": "Validate emails (MX / SPF / DMARC / SMTP)",
            "type": "boolean",
            "description": "When enabled, the actor grades every primaryEmail before delivery: checks MX records, SPF & DMARC DNS entries, and attempts an SMTP RCPT TO probe to detect catch-all domains (high bounce risk). Fills the `emailValidation` field with deliverability 'high'/'medium'/'low'. Critical for cold-outreach teams protecting sender reputation.",
            "default": true
          },
          "extractWebSignals": {
            "title": "Extract web quality signals (lite Lighthouse)",
            "type": "boolean",
            "description": "When enabled, the actor extracts lightweight web quality signals from every homepage it already fetches: HTTPS-only, mobile-responsive, page size, favicon, Open Graph tags, structured data. Fills `webSignals` + `webQuality` ('modern'/'dated'/'poor'). Free (uses HTML already in memory). Perfect for web-agency outreach targeting.",
            "default": true
          },
          "onlyNew": {
            "title": "Only new leads since last run",
            "type": "boolean",
            "description": "Return only places that earlier runs of this watch list did not deliver: they are skipped before anything is scraped and not charged (the run-start fee still applies to every run). The first run returns everything, all marked as new. Combine with a Schedule for a daily alert. \"Maximum Results Per Query\" counts the places checked, new or not, so set it above the number you expect.",
            "default": false
          },
          "monitorKey": {
            "title": "Watch list name",
            "type": "string",
            "description": "Optional. Names the list of leads already delivered. Empty: the search itself is the list (change the search and the list starts over). The same name keeps the list when you edit the search; different names keep several lists apart."
          },
          "maxRunSeconds": {
            "title": "Time budget (seconds)",
            "minimum": 0,
            "maximum": 86400,
            "type": "integer",
            "description": "How long the run may work before it stops by itself, in seconds. When the budget is used up the run stops starting new places and pages, finishes the ones in progress, saves everything collected and ends as SUCCEEDED with the message \"Stopped at the time budget: N leads saved. Raise maxRunSeconds for more.\" Leave empty or 0 for no time budget (default). Roughly 70 s of startup plus 5-8 s per lead: set 900 for about 100 leads, 3600 or more for 500+. Values 1-29 count as 30. The Apify run timeout still applies on top of this."
          },
          "maxConcurrency": {
            "title": "Max Concurrency",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "Maximum number of pages processed in parallel. Lower values reduce the chance of being blocked.",
            "default": 5
          },
          "proxyConfiguration": {
            "title": "Proxy Configuration",
            "type": "object",
            "description": "Proxy configuration for the scraper. The default (Apify datacenter proxy) was measured on four markets in paired runs against RESIDENTIAL: same rows delivered, same email hit rate, ~78% cheaper. Switch to the RESIDENTIAL group only if your runs hit Google's consent wall or return nothing — that is Google throttling datacenter IPs, and RESIDENTIAL gets past it at $8/GB."
          },
          "maxEmailScrapeConcurrency": {
            "title": "Email Scrape Concurrency",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "Maximum concurrent requests when scraping business websites for emails. Keep low to avoid blocks.",
            "default": 10
          },
          "sinceDatasetId": {
            "title": "Delta Mode — Skip places already in this dataset",
            "type": "string",
            "description": "Optional, and it requires state: you have to remember the datasetId that a previous run returned and pass it back here. Leave it empty on a first run. If you provide a dataset ID from a previous run, the actor will skip any Google Maps place already present there (matched by placeId). Perfect for daily/weekly scheduled runs that only want NEW leads — you save on every duplicate. Example: '0selLasyFyBlq5xRq' from a previous run."
          },
          "autoExtend": {
            "title": "Auto-extend run on timeout shortage (zero-touch UX)",
            "type": "boolean",
            "description": "⭐ Recommended. If your run's timeout is too short for the requested maxResults, the actor automatically starts a fresh run with a sufficient timeout instead of refusing. You never have to adjust the timeout manually. Note for programmatic callers: when this fires, the run you started finishes early and your results live in a SECOND run with a different runId, named in the first run's status message. Follow that pointer rather than reading the first run's empty dataset. Billing is unchanged — PAY_PER_EVENT only charges for leads actually delivered, regardless of which run delivered them. The original run exits cleanly with a pointer to the new run's dataset. Set to false only if you want the preflight to refuse with a detailed error instead.",
            "default": true
          },
          "geoGridTiles": {
            "title": "Geo-grid tiles — bypass Google's 120-result cap",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "🎯 Power feature. Google Maps caps a single search result list at ~120 places. If you need comprehensive coverage of a large city (say all 800+ restaurants in Manhattan), set this to N and the actor splits the search area into an N×N geographic grid, issuing the same query against each tile's map viewport. Tile results are de-duplicated by placeId so you get a single clean dataset. Leave at 1 (default) for small cities or when the 120-cap isn't a concern. Try 3 (→9 tiles) for medium cities, 5 (→25 tiles) for big cities, up to 10 (→100 tiles) for NYC/Tokyo-scale coverage. Only works when your query contains a recognizable location (e.g. 'restaurants in Manhattan', 'dentists near Berlin') — geocoded free via OpenStreetMap/Nominatim. ⚠️ Billing impact: each extra lead still costs one lead at your plan rate ($0.007 Free down to $0.0045 on Gold, Platinum and Diamond), and the run-start fee is charged once regardless of tile count — so 5× tiles doesn't mean 5× cost, it means up to 5× unique leads discovered.",
            "default": 1
          },
          "searchStringsArray": {
            "title": "Search terms (compass alias)",
            "type": "array",
            "description": "Alias for \"Search queries\", accepted so an input written for compass/crawler-google-places runs here unchanged. If both are set, \"searchQueries\" wins.",
            "items": {
              "type": "string"
            }
          },
          "maxCrawledPlacesPerSearch": {
            "title": "Max results per search (compass alias)",
            "minimum": 0,
            "type": "integer",
            "description": "Alias for \"Max results\". If both are set, the alias wins: the platform writes schema defaults into every input, so the native field is always present and the explicitly supplied alias is the stronger signal of intent."
          },
          "scrapeContacts": {
            "title": "Extract emails (compass alias)",
            "type": "boolean",
            "description": "Alias for \"Extract emails from websites\". If both are set, the alias wins (see \"Max results\" alias for why)."
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}