Google Search Results Scraper with Local Businesses avatar

Google Search Results Scraper with Local Businesses

Pricing

$19.99/month + usage

Go to Apify Store
Google Search Results Scraper with Local Businesses

Google Search Results Scraper with Local Businesses

🔎 Google Search Results Scraper extracts live SERP data—titles, snippets, URLs, rankings, ads & featured snippets—by location, language and device. ⚙️ Built for SEO, keyword research, competitor analysis & content planning. 🚀 Fast, scalable, proxy-ready.

Pricing

$19.99/month + usage

Rating

0.0

(0)

Developer

ScraperForge

ScraperForge

Maintained by Community

Actor stats

0

Bookmarked

16

Total users

3

Monthly active users

a day ago

Last modified

Share

Scrape Google Search results and extract the local/map "Places" business pack — name, rating, category, address, phone, website, hours, booking and directions links — directly from the same search results page. This Google SERP scraper is built for local SEO, local lead generation, and "near me" keyword research: run any keyword ("plumber in austin tx", "coffee shop chicago", "dentist near me") and get both the organic/paid Google search results and a structured list of the local businesses Google surfaces for that query, in one Apify dataset.

No Google Maps API key or Google Places API billing required — this actor parses the local pack straight off the public Google Search results page (google.com/search), the same block you see under the map when you search a "near me" style query in a browser.

What this Google local pack scraper does

  • Runs one or many search queries (plain keywords or full Google Search URLs) through Google Search, page by page, the same way apify/google-search-scraper and other SERP scraper actors do.
  • Detects when a query triggers Google's local/map business pack and extracts every business entry: title, star rating, review count text, category, price range, address, years in business, open/closed status, phone number, website, booking link, and directions link.
  • Optionally expands past the default 3-entry teaser into Google's fuller local business list ("More places", udm=1) for up to 100 businesses per query, with sponsored/ad entries flagged.
  • Filters keyword lists down to only the ones with a local pack, or to only businesses above a minimum star rating — useful for local-SEO auditing and lead-list triage.
  • Still returns everything the base Google Search Results Scraper returns — organic results, paid ads/products, People Also Ask, related queries, AI Overview (with a SerpApi key) — so it's a drop-in replacement for the base actor plus local business data.

Why use the local business pack extraction

Most Google SERP scraper actors on Apify (including the highest-usage one in this category) scrape organic results, ads, and People Also Ask, but skip the local/map pack entirely — even though it's the single most commercially relevant block for "near me" and service-area searches. This actor targets exactly that gap:

  • Local SEO rank tracking — see which businesses Google's local pack shows for a given keyword + location, and where a specific business ranks.
  • Local lead generation — pull business name, phone, website, and address for every business ranking in a niche/location without touching a paid Google Places API.
  • Competitor and market research — check ratings, review volume, price range, and "open now" status across all local competitors for a search term.
  • Local-SEO keyword triage — run a big keyword list and keep only the ones that actually surface a local pack (onlyQueriesWithLocalPack), so you know which keywords are worth local-SEO effort.

Input

The actor accepts the base Google Search Results Scraper's full input (30 fields, grouped into the same accordion sections), plus 4 new local-pack fields grouped under their own section.

📍 Local Business Pack (new in this variant)

FieldTypeDefaultDescription
includeLocalPackbooleantrueExtracts the local/map business pack for local-intent queries into localResults. Automatically removes the base actor's default Web-only restriction so the local pack can appear. When false, behavior is identical to the base actor (no local pack extracted).
maxLocalResultsinteger (0–100)20Caps businesses returned per query. 3 or fewer only reads the inline pack (no extra request); a higher value also fetches Google's paginated "More places" finder page. 0 = unlimited.
onlyQueriesWithLocalPackbooleanfalseDrops a query's row entirely (not pushed, not charged) when no local pack was found — for triaging a keyword list to only local-pack-triggering terms.
minLocalRatingnumber (0–5)0Drops local businesses whose parsed star rating is below this threshold. Businesses with no rating found are always kept. 0 = no filtering.

🔍 Search configuration

FieldTypeDescription
queries (required)string (textarea)One search term or full Google Search URL per line. Supports operators like site:, OR, AI site:twitter.com.
resultsPerPageinteger (1–100)Requested results per page (Google's own filtering may return fewer).
maxPagesPerQueryintegerMax pages per query (~10 results per page).

🌍 Location and language

countryCode, searchLanguage, languageCode, locationUule — country/domain, results language, interface language, and an exact-location UULE code for local search emulation.

🔎 Advanced search filters

forceExactMatch, site, relatedToSite, wordsInTitle, wordsInText, wordsInUrl, quickDateRange, beforeDate/afterDate (absolute or relative datepicker), fileTypes.

⚙️ Add-ons and additional settings

aiMode (Google AI Mode), serpApiKey (for AI Overview via SerpApi), perplexitySearch, chatGptSearch, maximumLeadsEnrichmentRecords, leadsEnrichmentDepartments, focusOnPaidAds, mobileResults, includeUnfilteredResults, saveHtml, saveHtmlToKeyValueStore, includeIcons, proxyConfiguration (proxy defaults to Apify's GOOGLE_SERP group).

Input example

{
"queries": "plumber in austin tx\ncoffee shop chicago\npython",
"includeLocalPack": true,
"maxLocalResults": 20,
"onlyQueriesWithLocalPack": false,
"minLocalRating": 4,
"maxPagesPerQuery": 1,
"countryCode": "us",
"languageCode": "en"
}

Output

Every dataset item is one search query result page, carrying the full base actor output plus the new local-pack fields.

New local-pack fields

FieldTypeDescription
hasLocalPackbooleanWhether a local business pack was found for this query.
localPackHeadingstring | nullThe pack's own heading text (e.g. "Places", "Businesses").
localSearchLocationstring | nullThe location line Google shows above the pack (e.g. "Results for Austin, TX").
localFinderUrlstring | nullLink to Google's fuller "More places" list for this query.
localResultsCountnumberCount of businesses in localResults after minLocalRating filtering.
localResultsarrayThe business records — see below.

Each entry in localResults[]:

Sub-fieldTypeDescription
positionnumberRank within the returned list (re-numbered after filtering/dedup).
isAdbooleanWhether the entry is labeled "Ad"/"Sponsored".
titlestringBusiness name.
ratingnumber | nullParsed star rating (0–5), when present.
reviewsTextstring | nullReview count as printed by Google (e.g. "1.2K") — abbreviated text, not an exact integer.
reviewsAriaLabelstring | nullRaw accessibility label the rating was parsed from.
categorystring | nullBusiness category/type.
priceRangestring | nullPrice tier (e.g. $, $$) when shown.
addressstring | nullStreet address, when it could be separated from other text on the page.
cityStatestring | nullCity/state line, when detected separately from address.
yearsInBusinessstring | null"X years in business" text, when shown.
openStatusstring | null"Open" / "Closed", when detectable.
openDetailstring | nullFull open/closed text (e.g. "Closes 9 PM").
phonestring | nullPhone number, when shown.
websitestring | nullBusiness website link.
scheduleUrlstring | nullBooking/ordering/reservation/menu link, when present.
directionsUrlstring | nullGoogle Maps directions link.
mapsFeatureIdstring | nullGoogle's internal place/CID identifier, when extractable from the page.
attributesarray of stringsLeftover short text snippets from the entry that didn't match a known field (amenities, hours snippets, etc.) — a catch-all so nothing visible is silently dropped.
reviewSnippetstring | nullA quoted customer review fragment, when Google shows one.
sourcestring"pack" (inline 3-entry box) or "finder" (the paginated "More places" list).

Base fields (unchanged, still present)

searchQuery (term, url, device, page, type, domain, countryCode, languageCode, locationUule, resultsPerPage), searchQueryTerm, url, hasNextPage, serpProviderCode, resultsTotal, relatedQueries[], paidResults[], paidProducts[], aiOverview (populated only with a serpApiKey and AI Mode enabled), organicResults[], suggestedResults[], peopleAlsoAsk[], customData (echoes the perplexitySearch/chatGptSearch/leads-enrichment input config), htmlSnapshotUrl (when saveHtmlToKeyValueStore is on), html (when saveHtml is on).

Output example

{
"searchQueryTerm": "coffee shop chicago",
"hasLocalPack": true,
"localPackHeading": "Places",
"localSearchLocation": "Results for Chicago, IL",
"localResultsCount": 2,
"localResults": [
{
"position": 1,
"isAd": false,
"title": "Example Coffee Roasters",
"rating": 4.7,
"reviewsText": "1.1K",
"category": "Coffee shop",
"priceRange": "$$",
"address": null,
"cityState": "Chicago, IL",
"openStatus": "Open",
"openDetail": "Closes 6 PM",
"phone": "(312) 555-0100",
"website": "https://example-coffee.com",
"directionsUrl": "https://www.google.com/maps/dir//...",
"mapsFeatureId": "12345678901234567890",
"attributes": ["Dine-in", "Takeout"],
"reviewSnippet": "Great espresso and a cozy spot to work.",
"source": "pack"
}
],
"resultsTotal": 214000,
"organicResults": ["..."],
"peopleAlsoAsk": []
}

Honest limitations (read before relying on a field)

  • The local pack only appears for local-intent queries. Google shows it for "near me"/service+location searches, not for informational or product searches — hasLocalPack: false on a non-local query is expected behavior, not a bug.
  • Address parsing is heuristic and partial. Google's HTML doesn't label "address" explicitly; it is split from surrounding text using pattern matching, so address/cityState are sometimes null even when the information is visible — in that case it usually still shows up inside the catch-all attributes array instead of being fabricated.
  • Review counts are abbreviated strings (e.g. "35K"), not exact integers — there is no exact review-count filter for this reason, only minLocalRating (star ratings are printed as exact values, e.g. "4.9").
  • Website / booking / directions links are matched by English link text ("Website", "Directions", "Book", …). Under a non-default languageCode, some of these links may not be detected.
  • resultsTotal is parsed from Google's own "About N results" text and can be affected by locale-specific number formatting — treat it as an estimate, not an exact count.
  • peopleAlsoAsk and the local pack share the same requirement (not being restricted to the Web-only results tab); with includeLocalPack off and default settings, peopleAlsoAsk may return empty on many queries.
  • perplexitySearch / chatGptSearch / leads-enrichment fields are pass-through configuration inherited from the base actor's schema — the values you set are echoed back in customData for now; they do not currently trigger an external AI or lead-enrichment call.
  • Google occasionally serves a blocking page for a given query/IP combination, which can result in zero rows for that specific query. This is a transport-level limitation of scraping Google directly (shared with the base actor) rather than a local-pack-specific issue — retrying the query or adjusting the proxy configuration usually resolves it.

Use cases

  • Local SEO rank tracking and local-pack keyword auditing
  • Local business lead generation (name, phone, website, address, rating) without a Google Places API key
  • Competitor benchmarking on ratings, review volume, price range, and open hours
  • "Near me" / service-area keyword research at scale
  • General Google SERP scraping (organic, paid ads, People Also Ask, related queries, AI Overview) alongside the local data

Frequently asked questions

Does this need a Google Places API key or Google Maps API billing? No. localResults is parsed directly from the public Google Search results page, not from the Google Places/Maps API.

Will I still get organic and paid results, or only the local pack? Both. This actor is a full superset of the base Google Search Results Scraper — every base input and output field still works exactly as before; the local-pack fields are additive.

Why is localResults empty for my query? The query most likely has no local intent (Google didn't show a local pack for it), or includeLocalPack is set to false. Try a "near me" or "[service] in [city]" style query with includeLocalPack: true.

Can I get more than 3 local businesses per query? Yes — set maxLocalResults above 3 (default 20) to trigger the paginated "More places" fetch, up to 100 per query.

How do I keep only keywords that have a local pack? Set onlyQueriesWithLocalPack to true; rows without a local pack are dropped from the dataset and not charged.

Compliance

Data is collected only from publicly available Google Search result pages. You are responsible for complying with Google's Terms of Service, robots.txt, and applicable laws (including privacy and data protection regulations) in your jurisdiction and use case.