Google Maps Photos Scraper

Extract public photo URLs and metadata from Google Maps places and search results.

Data fields

FieldTypeDescription
placeNamestring | nullGoogle Maps place name when visible.
placeUrlstringResolved Google Maps URL used for extraction.
placeIdstring | nullGoogle Maps place or feature identifier when available.
cidstring | nullGoogle Maps numeric CID when present.
querystring | nullSearch query that produced the record, if any.
rankintegerPhoto order within the input target.
photoIdstringDeterministic ID used to deduplicate the same Google-hosted photo across targets and retries.
photoUrlstringGoogle-hosted photo URL at the requested resolution.

Input preview

startUrlsGoogle Maps place or search URLs
placeIdsGoogle Maps place IDs
queriesSearch queries
maxPhotosPerPlaceMax photos per input
imageSizePhoto URL resolution
includeSearchDiscoveryInclude search result thumbnails

API and agents

This actor can be run through Apify API, datasets, webhooks, schedules, and the official Apify MCP server.

How this actor works

See example inputs, outputs, API usage, and practical limits before running this actor on Apify.

Open Apify page

Google Maps Photos Scraper exports public Google Maps place photos from URLs, share links, Place IDs, and search queries to JSON, CSV, Excel, or an API.

What does Google Maps Photos Scraper do?

Google Maps Photos Scraper exports public Google-hosted photo URLs and visible place metadata from Google Maps place pages and search results. It captures both visible gallery images and the photo metadata delivered to the browser, while keeping the visible-page path as a fallback. Runs deduplicate photos, save progress, and report target-level warnings instead of discarding valid results when one place fails.

Who is it for? Common use cases

  • Local SEO agencies auditing business profile photo coverage
  • Hospitality, restaurant, and retail teams monitoring public place media
  • Lead generation teams enriching place lists with visual signals
  • Reputation/media auditors comparing competitor photos by location
  • Analysts building datasets of public Maps photo links for review

What data can it export?

  • Public Google-hosted photo URLs and thumbnail URLs
  • Stable photo IDs for deduplication across places and retries
  • Place name and resolved Google Maps URL
  • Query or URL that produced each record
  • Photo order/rank, visible dimensions, captions, and contributor labels when shown
  • Google Maps identifiers when present in the public URL

Input example and recipes

Single landmark or business

{
  "queries": ["Statue of Liberty National Monument"],
  "maxPhotosPerPlace": 10,
  "includeSearchDiscovery": true,
  "maxConcurrency": 1,
  "proxyConfiguration": { "useApifyProxy": false }
}

Category and location monitoring

{
  "queries": ["pizza near Times Square New York"],
  "maxPhotosPerPlace": 25,
  "includeSearchDiscovery": true,
  "maxConcurrency": 1
}

Existing Google Maps URLs

{
  "startUrls": [
    { "url": "https://www.google.com/maps/search/Eiffel+Tower" }
  ],
  "maxPhotosPerPlace": 10
}

Place ID with original-resolution URLs

{
  "placeIds": ["ChIJLU7jZClu5kcR4PcOOO6p3I0"],
  "imageSize": "original",
  "language": "en",
  "country": "FR",
  "maxPhotosPerPlace": 20
}

Example output

{
  "placeName": "Statue of Liberty",
  "placeUrl": "https://www.google.com/maps/place/...",
  "placeId": "0x89c25090129c363d:0x40c6a5770d25022b",
  "cid": null,
  "query": "Statue of Liberty National Monument",
  "rank": 1,
  "photoId": "79d631fd633b36afc9bf1218",
  "photoUrl": "https://lh3.googleusercontent.com/...=w2048-h2048-k-no",
  "thumbnailUrl": "https://lh3.googleusercontent.com/...=w320-h320-k-no",
  "imageWidth": 408,
  "imageHeight": 544,
  "category": null,
  "caption": "Photo of Statue of Liberty",
  "contributorName": null,
  "extractionSource": "photometa",
  "scrapedAt": "2026-07-10T10:00:00.000Z"
}

Input settings

Field Type Description
startUrls array Google Maps place URLs, search URLs, or maps.app.goo.gl share links.
placeIds array Place IDs (ChIJ...), feature IDs (0x...:0x...), or numeric CIDs.
queries array Place names or category + location searches.
maxPhotosPerPlace integer Maximum photo records to save per input.
imageSize string thumbnail, medium, large (the backward-compatible default), or original.
includeSearchDiscovery boolean Include visible search-result thumbnails before a result resolves to a single place.
language string Google Maps language code, such as en, de, or pt.
country string Two-letter country code used to regionalize results.
allowEmptyResults boolean Allow a successful zero-row run. Disabled by default so blocks and source changes are not hidden.
maxRunSeconds integer Work deadline from 60 to 270 seconds; the Actor reserves 30 seconds for checkpointing.
maxConcurrency integer Browser pages in parallel; keep low for Google Maps reliability.
proxyConfiguration object Optional Apify Proxy settings. Start without proxy or with datacenter; use residential only if your run is blocked.

Tips for best results

  • Use specific place names with city/location, such as Hotel Chelsea New York.
  • For category monitoring, use queries such as coffee shops near Shibuya Tokyo and keep includeSearchDiscovery enabled.
  • Keep maxPhotosPerPlace low for first tests, then scale after confirming output quality.
  • Use placeIds when you need deterministic place resolution across scheduled runs.
  • Leave allowEmptyResults disabled unless an empty gallery is a valid business result.
  • If Google blocks requests in your region, enable Apify Proxy in the input.

Limits and legality

This Actor extracts public photo URLs and visible public metadata. It does not log in, bypass paywalls, download private content, or collect hidden account data. Run it only for workloads you are authorized to process, and follow applicable platform terms, privacy requirements, and local law. Google Maps can change its public interface or limit traffic; all-empty runs therefore fail by default instead of silently appearing successful.

API usage

Node.js

import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('fetch_cat/google-maps-photos-scraper').call({
  queries: ['Statue of Liberty National Monument'],
  maxPhotosPerPlace: 10
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

Python

from apify_client import ApifyClient

client = ApifyClient('YOUR_APIFY_TOKEN')
run = client.actor('fetch_cat/google-maps-photos-scraper').call(run_input={
    'queries': ['Statue of Liberty National Monument'],
    'maxPhotosPerPlace': 10,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)

cURL

curl -X POST 'https://api.apify.com/v2/acts/fetch_cat~google-maps-photos-scraper/runs?token=YOUR_APIFY_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"queries":["Statue of Liberty National Monument"],"maxPhotosPerPlace":10}'

MCP and agent usage

Use this actor from agents through Apify MCP:

https://mcp.apify.com?tools=fetch_cat/google-maps-photos-scraper

Claude CLI example:

claude mcp add apify https://mcp.apify.com?tools=fetch_cat/google-maps-photos-scraper

JSON configuration example:

{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=fetch_cat/google-maps-photos-scraper"
    }
  }
}

Example prompts:

  • "Collect public Google Maps photos for these five hotel URLs."
  • "Find visible photo thumbnails for pizza places near Times Square."
  • "Export Maps photo URLs for this landmark query as JSON."

Support

If you need help, open an issue on the Apify actor page and include:

  • Input JSON you used
  • Expected output
  • Actual output or dataset sample
  • Reproducible public URL (for example, a public Google Maps URL) or query
  • Run ID and error message, if any

Common questions

Questions and answers reused from the canonical actor README.

Does it download image files?

No. It exports public image URLs and thumbnails; you can download files separately if your use case allows it.

Can it scrape private photos?

No. Only public Google Maps media visible without login is in scope.

Why are some fields empty?

Google Maps does not expose every label, contributor, or category in every visible page state. Empty optional fields mean the value was not public/visible during the run.

Why did a zero-photo run fail?

An all-empty result can mean an unavailable place, a consent or traffic block, or a Google Maps interface change. The Actor fails so monitoring workflows notice. Set allowEmptyResults only when zero photos is expected.

Can a stopped run continue safely?

Yes. Multi-target runs store RUN_CHECKPOINT with pending targets and seen photo IDs. A resurrected run resumes without charging the start event again or saving the same photo twice.