# Google Maps Photos Scraper - Videos, Uploaders & Dates (`topapi/google-maps-photos-scraper`) Actor

Scrape every photo and video of Google Maps places from links, Place IDs or a search: full-size image URL, width/height, upload date, uploader name and profile, owner or visitor, caption, GPS, MP4 links. Filter by videos, owner, 360°, date. No login. $0.12 per 1,000 photos.

- **URL**: https://apify.com/topapi/google-maps-photos-scraper.md
- **Developed by:** [Top Api](https://apify.com/topapi) (community)
- **Categories:** Travel
- **Security:** Limited permissions
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.12 / 1,000 photo or videos

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does Google Maps Photos Scraper do?

**Google Maps Photos Scraper** extracts every photo, video and 360° capture of a Google Maps place, one row each: the image at the size you choose, its original width and height, when it was uploaded, who uploaded it (name and Google Maps profile), whether the business or a visitor posted it, the caption, where it was taken and, for videos, a playable MP4. Paste place links or IDs, or find places with a search. Built for menu and listing catalogs, local-SEO agencies, travel and real-estate sites, and teams building image datasets.

Google Maps Photo Scraper - Google Place Photos API - Google Business Profile photo downloader

- **Every photo the public gallery lists:** 2,873 rows for Katz's Delicatessen in one run, read to the gallery's end
- **The uploader on every row:** name, profile link, contributor id and avatar, included in the price
- **Videos with MP4, HLS and DASH links** and their length; Street View and 360° captures with their heading
- **Filters before you pay:** Videos, By owner, Street View & 360°, Latest, media type, owner or visitor, upload date window, caption only
- **No login, cookies or Google API key:** paste links, Place IDs, CIDs, feature ids or a search term
- **Pay only for delivered photos:** no start fee; filtered, duplicate and unreadable photos are free
- **Monitor mode:** a scheduled run delivers only photos added since the last one
- **Export anywhere:** JSON, CSV, Excel, XML, RSS; schedules, webhooks, Make, Zapier, n8n, Google Sheets, Slack, and AI agents over MCP

### What data can you get from Google Maps photos?

<table>
<tr>
<td>🖼️ Image URL at your size (`imageUrl`)</td>
<td>🔍 200 px thumbnail (`thumbnailUrl`)</td>
<td>📐 Original width and height</td>
</tr>
<tr>
<td>🎬 Video MP4, HLS, DASH + length</td>
<td>📅 Upload time (`uploadedAt`, hour) + day taken</td>
<td>🏢 Owner or visitor (`uploadedBy`)</td>
</tr>
<tr>
<td>👤 Uploader name (`contributorName`)</td>
<td>🔗 Uploader profile + id</td>
<td>💬 Caption + Google's translation</td>
</tr>
<tr>
<td>📱 Source app (Android, iOS, web, business)</td>
<td>⭐ Posted with a review (`fromReview`)</td>
<td>📍 Where it was taken (lat, lng)</td>
</tr>
<tr>
<td>🧭 Heading of 360° / Street View</td>
<td>🏷️ Google's topic code</td>
<td>🆔 Photo ID</td>
</tr>
<tr>
<td>🗺️ Place name, address, category</td>
<td>🔢 Place ID, CID, feature id, KG id</td>
<td>📊 Google's photo count, rating, reviews</td>
</tr>
</table>

### How to scrape Google Maps photos with Google Maps Photos Scraper

1. [Create a free Apify account](https://console.apify.com/sign-up) (it comes with free monthly credit).
2. Open **Google Maps Photos Scraper** and paste Google Maps place links, or Place IDs, or a search term with a location.
3. Pick the photo categories and how many photos you want per place.
4. Click **Start**. Rows arrive place by place within seconds.
5. Download the dataset as JSON, CSV or Excel, or read it through the API.

### ⬇️ Input

| Parameter | Type | Description |
|---|---|---|
| `startUrls` | array | Google Maps place links, `maps.app.goo.gl` share links, `?cid=` and `place_id:` links, or a CSV/TXT file of links. |
| `placeIds` | array | Place IDs (`ChIJ…`), CIDs (`3545819340560108778`) or feature ids (`0x…:0x…`), one per line. |
| `searchStringsArray` | array | Search terms as typed in Google Maps (`coffee shop`) or business names. |
| `locationQuery` | string | City, area or country for the search terms, e.g. `Seattle, WA`. |
| `maxCrawledPlacesPerSearch` | integer | Places per search term. Default 10; use 1 to look up a business by name. |
| `photoCategories` | array | `all` (default), `latest` (past 30 days, newest first), `videos`, `by_owner`, `street_and_360`. Several combine. |
| `mediaTypes` | array | `photo`, `video`, `photo360`, `streetView`. Empty = all. |
| `uploadedBy` | string | `any` (default), `owner` or `visitor`. |
| `language` | string | Language of names, categories and caption translations. Default `en`. |
| `photosNewerThan` / `photosOlderThan` | string | Upload date window: `2026-01-31`, `30 days`, `6 months`. |
| `withCaptionOnly` | boolean | Only photos with a caption. |
| `includeContributor` | boolean | Uploader name, profile, id and avatar. Default on, included in the price. |
| `monitorMode` / `monitorStoreName` | boolean / string | Deliver only photos no earlier run with the same store name has seen. |
| `maxPhotosPerPlace` | integer | Rows per place. Default 100; `0` = every photo Google lists. |
| `maxResults` | integer | Rows in total. `0` = no limit. |
| `imageSize` | string | `original` (default), `large` (1600 px), `medium` (800 px), `thumbnail` (200 px). |
| `compact` | boolean | Core fields only, for AI and MCP pipelines. |
| `maxConcurrency` | integer | Places read at once. Default 3. |
| `maxPhotosScannedPerPlace` | integer | With filters or Latest on: photos read per place to find matches. Default 5,000. |
| `proxyConfiguration` | object | Leave as is. |

#### Input JSON

```json
{
  "startUrls": [{ "url": "https://www.google.com/maps/place/Katz%27s+Delicatessen/@40.722233,-73.987429,17z/data=!4m6!3m5!1s0x89c2598f7ff4aa09:0x313547e757cb8cea!8m2!3d40.722233!4d-73.987429" }],
  "placeIds": ["ChIJN1t_tDeuEmsRUsoyG83frY4"],
  "searchStringsArray": ["dentist"],
  "locationQuery": "Boise, ID",
  "maxCrawledPlacesPerSearch": 5,
  "photoCategories": ["all"],
  "maxPhotosPerPlace": 100,
  "imageSize": "large"
}
```

#### Paste the link of the place, not of the map

A place link carries the place's id (`!1s0x…:0x…`) or a `cid` / `place_id`. A link that only has coordinates (`/@40.72,-73.98,17z`) points at the map, not a place: click the place on Google Maps first, or use **Search terms** with its name and `maxCrawledPlacesPerSearch: 1`.

#### Use the categories to pay only for what you need

**Videos**, **By owner** and **Street View & 360°** keep only those photos, **Latest** keeps photos uploaded in the past 30 days and delivers them newest first. Photos the filters drop are read but never charged. With a filter on, the actor reads up to `maxPhotosScannedPerPlace` photos of each place to find `maxPhotosPerPlace` matches.

#### Get every photo of a place

Set `maxPhotosPerPlace` to `0`. The actor pages the place's public gallery to its end, 100 photos per request.

### ⬆️ Output

One row per photo, video or 360° capture. A real row from a test run (long links shortened):

```json
{
  "placeName": "Katz's Delicatessen",
  "mediaType": "video",
  "category": "all",
  "photoId": "CIHM0ogKEICAgIDKz8nA1AE",
  "imageUrl": "https://lh3.googleusercontent.com/gps-cs-s/ANWiy9Rm…=s0",
  "thumbnailUrl": "https://lh3.googleusercontent.com/gps-cs-s/ANWiy9Rm…=s200",
  "videoUrl": "https://lh3.googleusercontent.com/gpms-cs-s/AM4Q-U8W…=m37",
  "videoDurationSec": 60,
  "width": 1920,
  "height": 1080,
  "uploadedAt": "2021-05-20T18:00:00.000Z",
  "dateTaken": "2021-05-20",
  "uploadedBy": "visitor",
  "contributorName": "Steve Costello",
  "contributorUrl": "https://maps.google.com/maps/contrib/105103597162936345941",
  "source": "ios",
  "sourceDetail": "photos:gmm_ios",
  "latitude": 40.72223300082572,
  "longitude": -73.98742897561966,
  "placeId": "ChIJCar0f49ZwokR6ozLV-dHNTE",
  "cid": "3545819340560108778",
  "fid": "0x89c2598f7ff4aa09:0x313547e757cb8cea",
  "address": "205 E Houston St, New York, NY 10002",
  "placeCategory": "Deli",
  "placeImagesCount": 95866
}
```

#### Fields and how often they are filled

Measured on Apify on the 2,873 rows of Katz's Delicatessen (every photo its gallery lists):

| Field | Filled | Meaning |
|---|---:|---|
| `photoId`, `imageUrl`, `thumbnailUrl`, `width`, `height` | 100% | Google's photo id, image links, original size |
| `uploadedAt`, `uploadDate`, `uploadTimestamp` | 100% | Upload time (Google gives the hour) |
| `dateTaken` | 99.4% (646-row run) | Day the photo was taken; 65% of those rows were uploaded on a later day |
| `uploadedBy`, `uploadedByOwner` | 100% | `owner`, `visitor` or `google` |
| `contributorName`, `contributorId`, `contributorUrl`, `contributorPhotoUrl` | 99.9% | The uploader |
| `source`, `sourceDetail`, `fromReview` | 100% | App the photo came from, posted with a review |
| `latitude`, `longitude` | 100% | Where it was taken |
| `caption` | 3% | What the uploader wrote (most write nothing) |
| `captionTranslated` | 1% | Google's translation, when the caption is in another language |
| `videoUrl`, `videoDurationSec`, `videoHlsUrl`, `videoDashUrl` | every video | 7 videos in this gallery |
| `heading` | every 360° / Street View capture | First view's compass heading |
| `internalCategoryCode` | 93% | Google's own topic code(s), raw |
| `placeName`, `placeId`, `cid`, `fid`, `placeKgmid`, `placeUrl`, `address`, `placeCategory`, `placeRating`, `placeReviewsCount`, `placeImagesCount` | 100% | The place |
| `searchString`, `placeRank` | rows found by a search | How the place was found |

The run's key-value store holds `RUN_SUMMARY` with one entry per place: Google's photo count, photos read, delivered, filtered, already delivered and whether the gallery was read to its end.

### Use cases

- 🍽️ **Menu and food catalogs**: every dish and menu photo of the restaurants in a city, with dates to keep the freshest.
- 📈 **Local SEO and reputation**: how many photos a business posts versus its visitors, and how recent they are, across competitors.
- 🏨 **Travel, hotel and real-estate listings**: interior, exterior and 360° imagery of venues to enrich pages.
- 🧠 **Image datasets**: labelled place photos with size, date, GPS and source app for vision models.
- 🎥 **Video collection**: every visitor video of a place with a direct MP4 link.
- 🔁 **Brand monitoring**: a weekly monitor run delivers only the new photos customers post of your locations.

### How much does it cost to scrape Google Maps photos?

**$0.12 per 1,000 photos** (`photo` event), no start fee, no per-place or per-search fee. Uploader details, video links and the place summary are included. Filtered, duplicate and unreadable photos are free.

| Photos | Price |
|---:|---:|
| 100 | $0.012 |
| 1,000 | $0.12 |
| 10,000 | $1.20 |
| 100,000 | $12.00 |

Measured on Apify on 2026-10-28:

| Run | Places | Rows | Time | Price |
|---|---:|---:|---:|---:|
| Prefilled run (Katz's Delicatessen + Sydney Opera House, 25 each) | 2 | 50 | 6 s | $0.006 |
| Empty input (the same two places, 100 each) | 2 | 200 | 11 s | $0.024 |
| `pizza` in `Chicago, IL`, 3 places, 80 each | 3 | 240 | 6 s | $0.029 |
| Every photo of Katz's Delicatessen (`maxPhotosPerPlace: 0`) | 1 | 2,873 | 120 s | $0.34 |
| 5 places, 500 each, rebooted by Apify halfway | 5 | 2,297 | 72 s | $0.28 |
| Monitor run, nothing new since the last one | 3 | 0 | 2 s | $0 |

A run stops cleanly at the maximum charge you set: a $0.003 cap delivered and charged exactly 25 photos. A run Apify restarts on another server does not deliver or charge a photo twice.

### Integrations, API, scheduling & MCP

- ⏰ **Schedules**: track your places weekly with `monitorMode` on; each run delivers only new photos.
- 🔔 **Webhooks**: get a call when a run finishes and fetch the dataset.
- 🔌 **Make, Zapier, n8n, Google Sheets, Slack**: through Apify's integrations.
- 🧑‍💻 **API**: start runs and read rows with the [Python](https://docs.apify.com/api/client/python) or [JavaScript](https://docs.apify.com/api/client/js) client, or plain HTTP.
- 🤖 **MCP**: AI agents call it through the Apify MCP server.

Photos of one place from your own code:

```bash
curl -X POST "https://api.apify.com/v2/acts/TopApi~google-maps-photos-scraper/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"placeIds":["ChIJCar0f49ZwokR6ozLV-dHNTE"],"maxPhotosPerPlace":50}'
```

### More scrapers from TopApi

- ⭐ [Google Maps Reviews Scraper](https://apify.com/TopApi/google-maps-reviews-scraper) - every review of a place with owner replies and dates.
- 🏨 [Google Hotels Scraper](https://apify.com/TopApi/google-hotels-scraper) - hotel prices, ratings and offers.
- 🖼️ [Google Images Scraper](https://apify.com/TopApi/google-images-scraper) - Google image search results.
- 🍎 [Apple Maps Scraper](https://apify.com/TopApi/apple-maps-scraper) - places, phones, hours, ratings and photos from Apple Maps.
- 🗺️ [Yandex Maps Scraper](https://apify.com/TopApi/yandex-maps-scraper) - places, phones, websites, reviews.
- 📷 [Facebook Photos Scraper](https://apify.com/TopApi/facebook-photos-scraper) - photos of Facebook pages and groups.

### Limits & empty runs

- **Google's photo count is larger than its gallery.** Katz's Delicatessen shows 95,866 photos; its public gallery lists 2,873, and that is what any signed-out visitor (and this actor) can page through. `RUN_SUMMARY` shows both numbers per place.
- **Menu, Food & drink and Vibe tabs** are not offered: Google serves those topic tabs only to signed-in visitors. Every row carries Google's own topic code (`internalCategoryCode`) instead.
- **Street View captures** are links to Google's Street View images, at most 1,024 x 768.
- **The gallery is not in date order.** Latest, the date window and monitor mode read a place's gallery up to `maxPhotosScannedPerPlace` photos to find the matches.
- **A run that returns nothing** says why in its status: no photos, every photo filtered out, nothing new since the last monitor run, or an input that is not a Google Maps place. Nothing is charged.
- **A run Google refuses completely** ends FAILED with the reason and charges nothing. When Google shows its unusual-traffic page the actor moves from the datacenter proxy to the container's own IP and then to a residential IP by itself.

### ❓ FAQ

#### How much does Google Maps Photos Scraper cost?

$0.12 per 1,000 delivered photos, with no start fee. A place's first 100 photos cost $0.012. Uploader details and video links are included.

#### How many photos can Google Maps Photos Scraper get per place?

Every photo the place's public gallery lists, page by page to its end: 2,873 for Katz's Delicatessen, 46 for a neighbourhood dental practice. Set `maxPhotosPerPlace` to `0` for all of them.

#### Does Google Maps Photos Scraper download the image files?

It returns direct links: images at the size you choose plus a 200 px thumbnail, and MP4, HLS and DASH links for videos. Download them with any tool.

#### Can Google Maps Photos Scraper get only the business's own photos or only videos?

Yes. Pick **By owner** or **Videos** in Photo categories, or use `uploadedBy` and `mediaTypes`. Photos dropped by a filter are never charged.

#### Can Google Maps Photos Scraper find places by search?

Yes. Put a term in **Search terms** (`coffee shop`) and a **Location** (`Seattle, WA`); each place the search finds returns its photos. A business name with `maxCrawledPlacesPerSearch: 1` looks up that one business.

#### Can Google Maps Photos Scraper run on a schedule and return only new photos?

Turn on `monitorMode` and schedule the actor. The first run is the baseline; later runs deliver only photos the earlier runs have not seen, and a place whose photo count did not change is not read again.

#### Do I need a Google account or API key for Google Maps Photos Scraper?

No. It reads the public Google Maps gallery, logged out.

#### Can I use Google Maps Photos Scraper through the Apify API or MCP?

Yes. Start runs over the REST API or the Python and JavaScript clients, or let an AI agent call it through the Apify MCP server.

#### Why did my Google Maps Photos Scraper run return no rows?

The status line says why: the place has no public photos, the filters removed every photo, nothing is new since the last monitor run, or the input is not a Google Maps place. None of these is charged.

#### Your feedback

Found a bug or need a field? Open an issue on the actor's Issues tab and we will look at it.

# Actor input Schema

## `startUrls` (type: `array`):

Google Maps place links from your browser, maps.app.goo.gl share links, ?cid= links or place_id: links, e.g. https://maps.app.goo.gl/… . A CSV/TXT file of links works too.

## `placeIds` (type: `array`):

One per line, any of the three: ChIJCar0f49ZwokR6ozLV-dHNTE, 3545819340560108778 or 0x89c2598f7ff4aa09:0x313547e757cb8cea.

## `searchStringsArray` (type: `array`):

What you would type in Google Maps, e.g. coffee shop, or a business name. Each place the search finds returns its photos.

## `locationQuery` (type: `string`):

City, area, ZIP or country the search terms are looked up in, e.g. Seattle, WA. Empty = Google's own choice.

## `maxCrawledPlacesPerSearch` (type: `integer`):

How many places each search term returns at most (Google Maps' own order). Use 1 to look up one business by name.

## `photoCategories` (type: `array`):

All = every photo Google lists. Latest = uploaded in the past 30 days, newest first. Videos, By owner and Street View & 360° work like the tabs on Google Maps. Pick several to combine.

## `mediaTypes` (type: `array`):

Keep only these kinds of media. Empty = all four.

## `uploadedBy` (type: `string`):

Only the business's own photos, only visitors' photos, or both.

## `language` (type: `string`):

Language of place names, categories and Google's caption translations.

## `photosNewerThan` (type: `string`):

Keep photos uploaded on or after this date: 2026-01-31, or relative like 30 days, 6 months, 1 year. Empty = no limit.

## `photosOlderThan` (type: `string`):

Keep photos uploaded on or before this date (same formats). Empty = no limit.

## `withCaptionOnly` (type: `boolean`):

Skip photos whose uploader wrote no caption.

## `includeContributor` (type: `boolean`):

Add the uploader's name, Google Maps profile link, id and avatar to every row (one extra call per 20 photos; videos always get their links). Included in the price.

## `monitorMode` (type: `boolean`):

Deliver only photos no earlier run with the same store name has seen. The first run is the baseline; a place whose Google photo count did not change is not read again.

## `monitorStoreName` (type: `string`):

Named key-value store that remembers the photos seen. Use one name per list of places you track.

## `maxPhotosPerPlace` (type: `integer`):

Rows each place returns at most (photos, videos and 360° captures together). 0 = every one Google lists to a signed-out visitor (2,873 for a very popular place).

## `maxResults` (type: `integer`):

Stop after this many rows across all places. 0 = no limit.

## `imageSize` (type: `string`):

Size of imageUrl. Every row also carries a 200 px thumbnailUrl.

## `compact` (type: `boolean`):

Core fields only (photo, size, date, uploader, caption, video, place ids) - trimmed for AI / MCP pipelines.

## `maxConcurrency` (type: `integer`):

How many places are read in parallel.

## `maxPhotosScannedPerPlace` (type: `integer`):

When filters or Latest are on, how many of a place's photos are read at most to find matches.

## `proxyConfiguration` (type: `object`):

Leave as is: the Apify datacenter proxy reads Google Maps; if Google shows its unusual-traffic page the run moves to the container's own IP, then to a residential IP.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.google.com/maps/place/Katz%27s+Delicatessen/@40.722233,-73.987429,17z/data=!4m6!3m5!1s0x89c2598f7ff4aa09:0x313547e757cb8cea!8m2!3d40.722233!4d-73.987429"
    },
    {
      "url": "https://www.google.com/maps/place/Sydney+Opera+House/@-33.8567844,151.2152967,17z/data=!4m6!3m5!1s0x6b12ae665e892fdd:0x3133f8d75a1ac251!8m2!3d-33.8567844!4d151.2152967"
    }
  ],
  "maxCrawledPlacesPerSearch": 10,
  "photoCategories": [
    "all"
  ],
  "uploadedBy": "any",
  "language": "en",
  "withCaptionOnly": false,
  "includeContributor": true,
  "monitorMode": false,
  "monitorStoreName": "google-maps-photos-monitor",
  "maxPhotosPerPlace": 25,
  "maxResults": 0,
  "imageSize": "original",
  "compact": false,
  "maxConcurrency": 3,
  "maxPhotosScannedPerPlace": 5000,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

One item per photo, video or 360° capture: image URL at your size + thumbnail, width, height, upload time, uploader, owner or visitor, source, caption, location, video links and the place.

## `summary` (type: `string`):

Per place: Google's photo count, photos read, delivered, filtered and already delivered, whether the gallery was read to its end; searches; unreadable inputs; requests per route.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        {
            "url": "https://www.google.com/maps/place/Katz%27s+Delicatessen/@40.722233,-73.987429,17z/data=!4m6!3m5!1s0x89c2598f7ff4aa09:0x313547e757cb8cea!8m2!3d40.722233!4d-73.987429"
        },
        {
            "url": "https://www.google.com/maps/place/Sydney+Opera+House/@-33.8567844,151.2152967,17z/data=!4m6!3m5!1s0x6b12ae665e892fdd:0x3133f8d75a1ac251!8m2!3d-33.8567844!4d151.2152967"
        }
    ],
    "maxPhotosPerPlace": 25
};

// Run the Actor and wait for it to finish
const run = await client.actor("topapi/google-maps-photos-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "startUrls": [
        { "url": "https://www.google.com/maps/place/Katz%27s+Delicatessen/@40.722233,-73.987429,17z/data=!4m6!3m5!1s0x89c2598f7ff4aa09:0x313547e757cb8cea!8m2!3d40.722233!4d-73.987429" },
        { "url": "https://www.google.com/maps/place/Sydney+Opera+House/@-33.8567844,151.2152967,17z/data=!4m6!3m5!1s0x6b12ae665e892fdd:0x3133f8d75a1ac251!8m2!3d-33.8567844!4d151.2152967" },
    ],
    "maxPhotosPerPlace": 25,
}

# Run the Actor and wait for it to finish
run = client.actor("topapi/google-maps-photos-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    {
      "url": "https://www.google.com/maps/place/Katz%27s+Delicatessen/@40.722233,-73.987429,17z/data=!4m6!3m5!1s0x89c2598f7ff4aa09:0x313547e757cb8cea!8m2!3d40.722233!4d-73.987429"
    },
    {
      "url": "https://www.google.com/maps/place/Sydney+Opera+House/@-33.8567844,151.2152967,17z/data=!4m6!3m5!1s0x6b12ae665e892fdd:0x3133f8d75a1ac251!8m2!3d-33.8567844!4d151.2152967"
    }
  ],
  "maxPhotosPerPlace": 25
}' |
apify call topapi/google-maps-photos-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,topapi/google-maps-photos-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/k8U8BvudUh6sqU0hb/builds/yglWwEEFj93IOEG0d/openapi.json
