# Apple Maps Scraper - Places, Ratings, Hours, Photos (`thirdwatch/apple-maps-scraper`) Actor

Scrape Apple Maps places: name, category, address, GPS coordinates, phone, website, rating, review count, opening hours, amenities, photos and review snippets. Search by query or coordinates. Pure HTTP, no browser, $1 per 1,000 places.

- **URL**: https://apify.com/thirdwatch/apple-maps-scraper.md
- **Developed by:** [Thirdwatch](https://apify.com/thirdwatch) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Apple Maps Scraper

Extract places from **Apple Maps** with a plain search query: business name, category, full address, GPS coordinates, phone, website, star rating and rating count, opening hours, amenities, photos, review snippets and editorial descriptions. No Apple account, no API key, no browser. Results come straight from the same data feed the Apple Maps web app uses, so they are as fresh as what you see at maps.apple.com.

Apple Maps is the default map on more than two billion iPhones, iPads and Macs, and its place data is a blend of Apple's own listings plus Yelp, TripAdvisor, Foursquare and The Infatuation. That makes it a distinct signal from Google Maps: different ratings, different photos, different business coverage, and amenities such as "Accepts Apple Pay" that only Apple tracks.

### What you get

One dataset item per place. A single search returns 20 to 60 places; ask for more and the Actor tiles the resolved search area into a grid and searches again, de-duplicating by Apple place ID.

| Field | Description |
|---|---|
| `placeId` | Apple's stable place identifier (for example `I15FF30DE01EC121F`) |
| `muid` | Apple's numeric place ID (used in `auid=` share links) |
| `name` | Business or place name |
| `category` | Primary category as shown on the place card ("Coffee Shop") |
| `categories` | All category labels, most general first ("Dining", "Coffee Shop", "Cafe") |
| `mapsCategoryId` | Apple's machine category path (`dining.cafe.coffee_shop`) |
| `placeType` | `BUSINESS`, `LANDMARK`, `TRANSIT`, ... |
| `phone`, `phoneFormatted` | Phone in E.164 and display format |
| `website` | Business website |
| `address`, `addressLines` | Full formatted address as one string and as lines |
| `street`, `neighborhood`, `city`, `state`, `stateCode`, `county`, `postalCode`, `country`, `countryCode` | Structured address components |
| `latitude`, `longitude` | WGS-84 coordinates |
| `timezone` | IANA time zone of the place (`America/Chicago`) |
| `rating`, `maxRating`, `ratingOutOf5` | Rating score on the provider's scale (Yelp is 0-5, Apple's own ratings are 0-100) plus a normalised 0-5 value |
| `ratingCount` | Number of ratings behind the score |
| `ratingProvider` | Who supplied the rating: `Yelp`, `Apple`, `TripAdvisor`, ... |
| `priceLevel`, `priceSymbol` | Price tier when Apple exposes one (sparse) |
| `hours` | Opening hours per weekday as `[{ "open": "07:00", "close": "22:00" }]`; `24:00` means midnight; days missing hours are closed |
| `open24Hours`, `hoursType` | Convenience flags |
| `amenities` | `[{ "name": "Accepts Apple Pay", "id": "crossbusiness.payments.applepay", "available": true }]` |
| `coverPhoto`, `photos` | Business cover image and up to `maxPhotos` photos with URL, thumbnail, size, caption and provider |
| `reviews` | Review snippets from the place card (text, rating, reviewer, link) |
| `description` | Business-supplied "About" text |
| `editorial` | Editorial blurb, for example from The Infatuation |
| `accolades` | Awards and lists ("The Infatuation: Top 25") |
| `quickLinks` | Menu, reservation and ordering links |
| `dataProvider`, `dataProviderUrl` | Third-party provider behind the listing and the link back to it |
| `appleMapsUrl` | Deep link to the place on maps.apple.com |
| `language`, `query`, `scrapedAt` | Provenance |

#### Sample record

```json
{
  "placeId": "I15FF30DE01EC121F",
  "name": "Daydreamer Coffee",
  "category": "Coffee Shop",
  "categories": ["Dining", "Coffee Shop", "Cafe"],
  "phone": "+17404000238",
  "website": "https://www.daydreamer.coffee/",
  "address": "80 Rainey St, Austin, TX 78701, United States",
  "neighborhood": "Downtown",
  "city": "Austin",
  "stateCode": "TX",
  "postalCode": "78701",
  "countryCode": "US",
  "latitude": 30.2592149,
  "longitude": -97.7389039,
  "rating": 4,
  "maxRating": 5,
  "ratingOutOf5": 4.0,
  "ratingCount": 27,
  "ratingProvider": "Yelp",
  "hours": { "Monday": [{ "open": "07:00", "close": "22:00" }], "...": "..." },
  "amenities": [{ "name": "Accepts Apple Pay", "id": "crossbusiness.payments.applepay", "available": true }],
  "photos": [{ "url": "https://is1-ssl.mzstatic.com/image/thumb/.../750x1000bb.jpg", "caption": "interior", "provider": "Yelp" }],
  "appleMapsUrl": "https://maps.apple.com/place?place-id=I15FF30DE01EC121F"
}
```

### Input

```json
{
  "queries": ["coffee in Austin, TX", "dentists near Manchester"],
  "maxResults": 100,
  "language": "en-US",
  "includePhotos": true,
  "maxPhotos": 5,
  "includeReviews": true
}
```

| Field | Type | Default | Notes |
|---|---|---|---|
| `queries` | array of strings | required | Write them the way you would type into Apple Maps. Put the location in the query ("in Austin, TX", "near Soho, London") unless you set coordinates. |
| `maxResults` | integer 1-500 | 50 | Per query. Above one page the search area is tiled automatically. |
| `latitude`, `longitude` | number | - | Search around a fixed point instead of the location in the query. |
| `radiusKm` | number 0.5-100 | 5 | Radius around the point above. |
| `language` | BCP-47 tag | `en-US` | Changes names, categories, amenities and reviews (`fr-FR`, `de-DE`, `ja-JP`, ...). |
| `countryCode` | ISO-2 | - | Bias for ambiguous queries. |
| `includePhotos`, `maxPhotos` | bool, int | true, 5 | |
| `includeReviews` | bool | true | |
| `proxyConfiguration` | object | off | Not needed for Apple Maps; only enable if your runs start erroring. |

Search around coordinates:

```json
{
  "queries": ["pharmacy"],
  "latitude": 51.5074,
  "longitude": -0.1278,
  "radiusKm": 2,
  "maxResults": 40,
  "language": "en-GB"
}
```

### Pricing

Pay per place, nothing else. No charge for the run start, for empty searches or for compute.

| Plan | Price per place | Per 1,000 places |
|---|---|---|
| Free | $0.001 | $1.00 |
| Bronze | $0.0009 | $0.90 |
| Silver | $0.0008 | $0.80 |
| Gold | $0.0007 | $0.70 |

A run of 10 city-level queries at 100 places each costs about $1.00 and finishes in roughly a minute. The Actor runs on 256 MB with pure HTTP, so there is no hidden platform usage bill on top.

### Use cases

**1. Lead lists for local-business sales.** Search "roofing contractors in Phoenix, AZ" or "dental clinics in Leeds" and get phone, website, full address, rating and whether they accept Apple Pay in one pass. Feed the CSV into your CRM or an enrichment step; `placeId` stays stable across runs so you can diff for new businesses each month.

**2. Location intelligence and site selection.** Pull every "coffee shop", "gym" and "grocery store" within a radius of a candidate site using `latitude`/`longitude` + `radiusKm`, then map density, rating and price tiers against foot traffic. Apple's categories are hierarchical (`dining.cafe.coffee_shop`) which makes rolling up by vertical easy.

**3. Reputation monitoring across map providers.** Apple Maps surfaces Yelp and TripAdvisor ratings, Apple's own 0-100 "recommend" score, editorial blurbs from The Infatuation and accolades. Scrape your locations weekly and compare with Google Maps data to catch rating drops, wrong hours or missing photos on the map two billion iPhones use by default.

### How it works

The Actor talks to the JSON endpoint behind maps.apple.com search. Every response already carries the complete place card, so there is one HTTP request per search page and none per place. Queries are passed through verbatim, Apple parses "what in where" itself, and the area it resolves is reused for grid tiling when you ask for more results than one page holds. Results are de-duplicated by `placeId` across all queries in a run.

- Geographic hits (cities, streets, postcodes) are filtered out; only places are pushed.
- An empty result set from Apple finishes as a successful run with a clear status message. A run only fails when Apple Maps could not be reached for any query.
- Requests are paced at about one per second with exponential backoff on 429/5xx.

### Limitations

- Apple returns at most around 60 places per search; grid tiling extends this but very generic queries over a whole metro area top out at a few hundred distinct places.
- Full review text is not exposed by Apple Maps; you get the snippets shown on the place card (typically three).
- Price tier is only present for a subset of restaurants.
- Queries with no location and no coordinates are resolved relative to the server's IP location, which is rarely what you want. Always include a place name or set coordinates.

### Related Actors by Thirdwatch

- [Google Maps Scraper](https://apify.com/thirdwatch/google-maps-scraper) for the Google side of the same data
- [Yelp Scraper](https://apify.com/thirdwatch/yelp-scraper) for full Yelp reviews
- [TripAdvisor Scraper](https://apify.com/thirdwatch/tripadvisor-scraper)

Questions or a source you would like added? Open an issue on the Actor page.

# Actor input Schema

## `queries` (type: `array`):

One search per line, written the way you would type it into Apple Maps: 'coffee in Austin, TX', 'dentists near Manchester', 'hotels in Paris'. Include a location in the query unless you set Latitude/Longitude below.

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

Maximum number of places to return for each query (1-500). A single Apple Maps search returns 20-60 places; above that the search area is tiled into a grid and re-searched automatically.

## `latitude` (type: `number`):

Centre of the search area. When set together with Longitude, every query is searched around this point instead of the location named in the query.

## `longitude` (type: `number`):

Centre of the search area. Used only together with Latitude.

## `radiusKm` (type: `number`):

Search radius around Latitude/Longitude in kilometres (0.5-100). Ignored when coordinates are not set.

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

BCP-47 language tag for names, categories and reviews, e.g. en-US, en-GB, fr-FR, de-DE, es-ES, ja-JP. Defaults to en-US.

## `countryCode` (type: `string`):

ISO 3166-1 alpha-2 country code used to bias ambiguous queries, e.g. US, GB, IN, DE. Leave empty to let Apple infer it from the query.

## `includePhotos` (type: `boolean`):

Add a photos array (URL, caption, dimensions, provider) to each place.

## `maxPhotos` (type: `integer`):

Cap the number of photos returned per place (1-50).

## `includeReviews` (type: `boolean`):

Add the review snippets Apple Maps shows on the place card (usually up to 3, provided by Yelp/TripAdvisor).

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

Apple Maps does not require a proxy. Only enable one if your runs start returning errors.

## Actor input object example

```json
{
  "queries": [
    "coffee in Austin, TX"
  ],
  "maxResults": 50,
  "radiusKm": 5,
  "language": "en-US",
  "includePhotos": true,
  "maxPhotos": 5,
  "includeReviews": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

# 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 = {
    "queries": [
        "coffee in Austin, TX"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("thirdwatch/apple-maps-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 = {
    "queries": ["coffee in Austin, TX"],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("thirdwatch/apple-maps-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 '{
  "queries": [
    "coffee in Austin, TX"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call thirdwatch/apple-maps-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,thirdwatch/apple-maps-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/NaqTibnHOZVBU1S7b/builds/Rax6CDew6rslkXWd9/openapi.json
