Google Maps Photos Scraper avatar

Google Maps Photos Scraper

Pricing

from $3.00 / 1,000 results

Go to Apify Store
Google Maps Photos Scraper

Google Maps Photos Scraper

Extract photos from any Google Maps place - carousel scraping with max-resolution URLs, contributor info, and category metadata.

Pricing

from $3.00 / 1,000 results

Rating

0.0

(0)

Developer

Crawler Bros

Crawler Bros

Maintained by Community

Actor stats

0

Bookmarked

53

Total users

3

Monthly active users

a day ago

Last modified

Share

Extract every photo currently exposed by the public Google Maps gallery — including max-resolution image URLs, contributor names, observed upload-date text, captions, and visibly available category tabs (Food & Drink, Indoor, Outdoor, Menu, Videos, etc.). Google can expose a different slice or fewer fields for different places, regions, categories, and anonymous sessions; the actor omits unavailable values rather than inventing them.

What this actor does

Give this actor a Google Maps place URL and it returns up to the requested limit (up to 100,000) for that place. Google may expose fewer photos for a place or category. Records are pushed progressively as the public gallery reveals them. For each photo you get:

  • Max-resolution photo URL (full-size, not thumbnail)
  • Photo category — the requested category is included when a non-all tab is visibly selected; all is not stamped onto rows as if it were a Google-published photo category
  • Contributor name and profile URL (when available)
  • Observed upload date text (for example, "2 months ago"); an ISO date is added only when Google publishes a complete calendar date
  • Original dimensions + aspect ratio + orientation, when present in the public viewer route
  • Caption and tags (when published by the contributor)
  • Video flag and duration — distinguishes photos from short clips when exposed by the viewer/grid, with the clip length as Google displays it (videoDuration, e.g. "0:29")
  • Business context — businessName, placeId, featureId, placeUrl echoed on every record so the dataset stays joinable. A canonical ChIJ… Place ID is emitted as placeId; the legacy 0x…:0x… token is emitted as featureId and is never placed under placeId

Use cases

  • Build a visual asset library for restaurants, hotels, and venues
  • Track menu / interior photo updates over time
  • Source UGC photography for travel and food blogs
  • Power "what does this place look like" previews in custom apps
  • Enrich lead-generation pipelines with visual context

Input

FieldTypeRequiredDefaultDescription
placeUrlStringOne of placeUrl/placeId—Google Maps place URL; country domains, short links, copied punctuation, and tracking parameters are normalized
placeIdStringNo—Canonical Google Place ID beginning with ChIJ; use instead of placeUrl
maxPhotosIntegerNo100Maximum number of photos to extract (1–100,000); the source may expose fewer
photoCategoryEnumNoallFilter by tab: all, by_owner, by_visitors, food_and_drink, outdoor, indoor, menu, videos
enrichDetailsBooleanNotrueRead each photo's metadata (contributor name/URL, observed upload date, original dimensions, aspect ratio, orientation, caption, tags). Disable for thumbnail-level rows (photo/thumbnail URL, business context, category, video flag and duration). Every surface is walked in both modes, so disabling trims per-photo work rather than skipping the walk.
proxyConfigurationObjectNoApify ProxyOptional proxy settings

Examples

{
"placeUrl": "https://www.google.com/maps/place/Empire+State+Building/@40.7484405,-73.9878584,17z/",
"maxPhotos": 50,
"photoCategory": "all",
"enrichDetails": true
}

Example: fast visitor-photo export

{
"placeUrl": "https://www.google.com/maps/place/Sushi+no+Midori/@35.6704396,139.7596577,17z/",
"maxPhotos": 1000,
"photoCategory": "by_visitors",
"enrichDetails": false
}

Example: menu photos only

{
"placeId": "ChIJabtoT7hlwokRLECK0SW3_8I",
"maxPhotos": 100000,
"photoCategory": "menu",
"enrichDetails": true
}

Output per photo

One record per photo:

{
"recordType": "photo",
"photoId": "CIHM0ogKEICAgICRye-HxgE",
"photoIndex": 0,
"photoUrl": "https://lh3.googleusercontent.com/gps-cs-s/media=s0",
"thumbnailUrl": "https://lh3.googleusercontent.com/gps-cs-s/media=w200-h150-k-no",
"category": "by_visitors",
"contributorName": "Jane Smith",
"contributorUrl": "https://maps.google.com/maps/contrib/123...",
"uploadDateOriginal": "2 months ago",
"uploadDate": "2026-04-16T00:00:00+00:00",
"caption": "Sunset view from the observation deck",
"width": 4032,
"height": 3024,
"aspectRatio": 1.33,
"orientation": "landscape",
"isVideo": false,
"tags": ["sunset", "view", "observation deck"],
"businessName": "Empire State Building",
"featureId": "0x89c259a9b3117469:0xd134e199a405a163",
"placeUrl": "https://www.google.com/maps/place/Empire+State+Building/...",
"sourceUrl": "https://www.google.com/maps/place/Empire+State+Building/...",
"scrapedAt": "2026-06-16T12:00:00+00:00"
}

photoIndex is Google's observed tile index in the active gallery/category. It preserves the source ordering hint, but is not guaranteed to be contiguous or stable across places, categories, or separate runs.

The place identity is split by form: a canonical ChIJ… token is emitted as placeId, and a legacy 0x…:0x… token as featureId. Only the observed form is emitted — when Google exposes just the legacy token, placeId is omitted (never set to the legacy value).

Empty fields are omitted automatically — no null values in the dataset.

videoDuration holds the clip length exactly as Google renders it on the media tile — mm:ss (for example "0:29"), or h:mm:ss for a clip of an hour or more — rather than a converted seconds count. This keeps the as-displayed value, matching the actor's other observed-text fields (such as uploadDateOriginal) and the sibling Google Maps Directions actor, which keeps the as-displayed duration text and reserves the numeric shape for a distinctly named durationSeconds field. The value is read only from the tile whose media matches the photo's own viewer route, so a neighbouring tile's duration can never be attached.

FAQ

Does it need a proxy or cookies? No login or authenticated cookies. The actor tries direct public access first, then uses a bounded hardcoded US RESIDENTIAL proxy fallback when the public viewer cannot be verified. Set proxyConfiguration.useApifyProxy to false only for an explicit direct-only diagnostic; cookies are never accepted.

Which categories does Google show? Every place is different. Restaurants typically have Food & Drink + Menu, hotels have Indoor + Outdoor, and landmarks usually have a single "All Photos" tab. A category-specific run emits rows only after the requested tab is visibly selected; if Google does not expose that tab in the anonymous page, the actor fails truthfully instead of returning all-photo rows under the wrong category.

What does enrichDetails actually do? Every photo surface is walked in both modes, because walking is how photos are enumerated. With enrichment on, each photo's metadata is read: contributor name/URL, observed upload date text, original dimensions, aspect ratio, orientation, caption, and tags. With it off, rows stay at the thumbnail level — photo and thumbnail URL, business context, category, video flag and duration — so contributor, date, caption, tag and dimension fields are omitted.

Are video clips supported? Yes — short video clips on Google Maps are included when photoCategory is all or videos, with isVideo: true and the clip length Google displays in videoDuration (for example "0:29").

How many photos can I get per place? This actor accepts up to 100,000 photos per run and emits each verified record progressively. Google may expose fewer photos anonymously or limit a gallery by place, region, or category; the actor stops when the public gallery is exhausted.

Data Source

Public Google Maps web UI. No Google API key required.

You are responsible for using these photo records lawfully and in line with Google's terms.

🗺️ Complete Google Maps Scraper Suite

This actor is part of a comprehensive Google Maps data extraction toolkit by crawlerbros. All actors run cookielessly on the free Apify plan with bounded direct, retry, and residential recovery paths, and return clean, structured data.

ActorWhat it does
🏢 Google Maps Business ScraperExtract business data — name, address, phone, website, rating, reviews, hours, amenities
⭐ Google Maps Reviews ScraperScrape reviews with reviewer Local Guide level, photos, mentioned items, owner replies
🕐 Google Maps Business Hours ScraperFull 7-day hours, timezone, current local time, next open/close, holiday hours
📊 Google Maps Popular Times ScraperBusy hours histogram for all 7 days + current busyness + typical visit time
📧 Google Maps Email ExtractorFind business emails + social media links by crawling websites
🗺️ Google Maps Area ScannerGeographic grid scanning — bypass the 120-place limit with bounding box / circle / polygon
💼 Google Maps Leads ScraperB2B lead generation with email + phone enrichment, US states + global countries
🤖 Google Maps MCP ServerUnified MCP server combining search + reviews for AI assistants
🧭 Google Maps Directions ScraperA→B routing — distance, duration, traffic, route alternatives for driving/walking/transit
📍 Google Maps Geocoding ScraperBidirectional geocoding — address ↔ coordinates, with address components
🔗 Google Maps Similar Places Scraper"People also search for" / related place discovery — competitor & alternative finder
🍽️ Google Maps Menu ScraperRestaurant menu items, prices, descriptions, photos
📌 Google Maps Nearby ScraperFind places near a coordinate point — lightweight POI search by category
📋 Google Maps Place List ScraperExtract Google's curated "Top X in Y" lists — best hotels/restaurants/things to do
🌍 Google Maps Timezone ScraperIANA timezone + current local time from coordinates