Serper Google Places Scraper avatar

Serper Google Places Scraper

Pricing

$10.00 / 1,000 serper places page requests

Go to Apify Store
Serper Google Places Scraper

Serper Google Places Scraper

Run one or many Google Places searches through the Serper.dev API with automatic pagination and CID-based dedupe. Outputs a clean, flat, import-ready dataset - built for Clay, Google Sheets, and CRM lead-gen workflows. Pay only per page request.

Pricing

$10.00 / 1,000 serper places page requests

Rating

5.0

(1)

Developer

Umami Data

Umami Data

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

7 days ago

Last modified

Share

Run one or many Google Places searches through the Serper.dev Places API and get a clean, deduplicated, import-ready dataset — without writing any pagination code. Tuned for lead-gen workflows (Clay, Google Sheets, CRM imports).

You bring your own Serper API key; the actor handles pagination, deduplication, and flattening for you.

Features

  • Familiar input — the standard apiKey / q / gl / location fields, so it slots straight into existing Serper Places workflows.
  • Multi-query runs — paste many search queries (one per line) in a single run.
  • Automatic pagination — the actor walks every result page until Serper returns no more places. No manual page counting.
  • Global deduplication — places are deduplicated by Google CID across all queries (first-seen wins), so the same business never appears twice.
  • Spend capmaxResults caps the number of unique places per query so you stay in control of your Serper credits. An internal 50-page safety brake also guards against runaway pagination — but a normal query stops on its own long before that (Google returns at most ~120 results per query), so you'll almost never reach it.
  • Clean, flat output — every row is the same fixed set of snake_case columns, null-filled when Serper omits a field. Ready to import straight into a spreadsheet or CRM.
  • Secret-safe — your Serper key is stored encrypted, never logged, and never written to a dataset row.

Data / Output

Every dataset row has exactly these columns, in this order. Fields that Serper does not return for a given place are filled with null.

ColumnDescription
titleBusiness / place name
addressFormatted street address
latitudeLatitude of the place
longitudeLongitude of the place
ratingAverage Google rating (e.g. 4.6)
rating_countNumber of ratings
price_levelGoogle price level (e.g. $$), or null
categoryPrimary place category (e.g. Coffee shop)
phone_numberPhone number, when the business has one listed; otherwise null
websiteWebsite, when the business has one listed; otherwise null
cidGoogle Customer ID — the stable place identifier used for deduplication
maps_urlGoogle Maps link, derived as https://maps.google.com/?cid=<cid>
queryThe search query that produced this row
locationThe location used for the search
glThe country code used for the search
hlThe language code used (if supplied)
pageThe Serper result page this row came from
positionThe place's position within its page

Sample output row

{
"title": "Blue Bottle Coffee",
"address": "1 Ferry Building, San Francisco, CA 94111",
"latitude": 37.7956,
"longitude": -122.3933,
"rating": 4.5,
"rating_count": 1280,
"price_level": "$$",
"category": "Coffee shop",
"phone_number": "+1 510-653-3394",
"website": "https://bluebottlecoffee.com",
"cid": "1234567890123456789",
"maps_url": "https://maps.google.com/?cid=1234567890123456789",
"query": "coffee shops",
"location": "San Francisco, United States",
"gl": "us",
"hl": "en",
"page": 1,
"position": 1
}

(The cid above is synthetic — a placeholder for documentation only.)

Usage / Tutorial

  1. Get a Serper API key. Sign up at serper.dev and copy your API key from the dashboard. Serper offers a free tier so you can try the actor before paying for credits.
  2. Paste your key into the Serper API key field. It is a secret field — stored encrypted, never logged, never written to output.
  3. Enter a search. Set a single query in q (e.g. coffee shops), or paste many queries (one per line) into Search queries.
  4. Set the location. Provide a 2-letter country code in gl (e.g. us) and a named location (e.g. New York, United States). Optionally set hl for the language and maxResults to cap results per query.
  5. Run the actor. It paginates through every page automatically and pushes clean, deduplicated rows to the dataset. Export to JSON, CSV, or Excel, or pull it into Clay / Sheets / your CRM.

Run it from code, n8n, or the API

You don't have to use the Console — the actor runs the same way programmatically. There are two separate credentials, don't mix them up:

  • Apify API token — authenticates you to Apify so you can start a run (from your Apify account → Settings → API & Integrations).
  • Serper API key — passed as the apiKey input field, exactly like in the Console. It is a secret field (encrypted, never logged), but you still include it in the input payload — that's expected and safe.

n8n

Add your Apify API token as Apify credentials once, then use the Apify node's "Run Actor and get dataset items" operation, select this actor, and provide the input JSON (keep your Serper key in an n8n credential/variable and reference it via an expression rather than hardcoding):

{ "apiKey": "YOUR_SERPER_API_KEY", "queries": ["coffee shops in soho"], "gl": "gb", "location": "London, United Kingdom", "maxResults": 50 }

The dataset rows flow straight into the next node. (No dedicated node? An HTTP Request node hitting the REST endpoint below works identically.)

REST API (one call, returns the rows)

curl -X POST "https://api.apify.com/v2/acts/USERNAME~serper-google-places-scraper/run-sync-get-dataset-items?token=APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "apiKey": "YOUR_SERPER_API_KEY", "queries": ["coffee shops in soho"], "gl": "gb", "location": "London, United Kingdom", "maxResults": 50 }'

JavaScript / Python (Apify client)

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('USERNAME/serper-google-places-scraper').call({
apiKey: process.env.SERPER_KEY,
queries: ['coffee shops in soho'],
gl: 'gb',
location: 'London, United Kingdom',
maxResults: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
from apify_client import ApifyClient
client = ApifyClient(APIFY_TOKEN)
run = client.actor("USERNAME/serper-google-places-scraper").call(run_input={
"apiKey": SERPER_KEY,
"queries": ["coffee shops in soho"],
"gl": "gb",
"location": "London, United Kingdom",
"maxResults": 50,
})
items = client.dataset(run["defaultDatasetId"]).list_items().items

Bound your spend programmatically: set a per-run charge ceiling (maxTotalChargeUsd in the run options / API). The actor stops cleanly the moment the limit is reached, so an automated loop can never run away. Replace USERNAME with your Apify username (the actor lives at apify.com/USERNAME/serper-google-places-scraper).

Pricing

This actor uses pay-per-event charging, plus your own Serper credits.

  • Actor fee: $0.01 per Serper Places page request (~10 places per page). That works out to $10 per 1,000 page requests. One charged event = one Serper page fetched, so a single multi-page query costs multiple events (e.g. a query that spans 3 pages = 3 charged events). Charging is per page request, not per result — your cost scales with pages fetched, not with how many places land on each page.
  • Bring your own Serper credits: you supply your own Serper API key and pay Serper directly for the API calls the actor makes. The actor never resells Serper credits.
  • Serper free tier: Serper provides a free tier of credits, so you can evaluate the actor at no Serper cost before topping up.

Input / Output Examples

Input

A minimal, runnable input. Replace the placeholder with your real key.

{
"apiKey": "YOUR_SERPER_API_KEY",
"q": "coffee shops",
"gl": "us",
"location": "New York, United States",
"maxResults": 100
}

To run several searches at once, supply queries (one per line) instead of, or in addition to, q:

{
"apiKey": "YOUR_SERPER_API_KEY",
"queries": ["coffee shops", "bakeries", "bookstores"],
"gl": "us",
"location": "New York, United States",
"hl": "en",
"maxResults": 50
}

Output

Each run produces dataset rows shaped exactly like the sample output row above, with the columns documented in Data / Output.

FAQ

Why is pricing per page request and not per result? Serper bills per page request, and a page can return a variable number of places (up to ~10). Charging per page keeps your cost predictable and tied to the actual API calls made, instead of mischarging based on how many places happen to appear on a page.

What happens when I hit the Serper charge limit? The actor respects the run's max-charge limit. It stops issuing new page requests before exceeding the limit, so you never get charged beyond what you set — partial results collected up to that point are still saved.

How many results can a single query return? maxResults caps the number of unique places per query (counted after deduplication — duplicates never consume the cap). Omit it for unlimited results. An internal 50-page safety brake also applies as a runaway-pagination guard; whichever limit is reached first ends the query. In practice a single query exhausts on its own well before 50 pages — Google returns at most ~120 results per query, so the natural last-page stop almost always fires first. The brake exists only to bound spend if the upstream API ever fails to terminate.

Do duplicate places across multiple queries get returned twice? No. Places are deduplicated globally by Google CID across all queries in a run (first-seen wins), so the same business never appears in more than one row.