Skip to content

About

Scrape Apple Maps search results with a simple API. Get places with their addresses, phone numbers, websites, ratings, opening hours, and photos.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 

Repository files navigation

Apple Maps Scraper

Scrape Apple Maps search results with SerpApi's Apple Maps API. Search places by keyword and area, and get each place's MUID, name, coordinates, address, phone, website, ratings, reviews, opening hours, amenities, photos, and the guides that feature it.

How to scrape Apple Maps

Search Apple Maps with a simple GET request:

https://serpapi.com/search?engine=apple_maps&query=coffee&location=Austin,+Texas,+United+States&api_key=SERPAPI_API_KEY
  • query is the search query: anything you'd use in an Apple Maps search, such as a category, a business name, or an address.
  • location is the area to search in, e.g., Austin, Texas, United States. Use center with latitude,longitude coordinates instead for a precise point. One of them is required.
  • api_key is your SerpApi API key. Replace SERPAPI_API_KEY with it.
  • sort orders the places by distance or ratings instead of the best match.
  • toggles and multi_select_options filter the places with the keys in refinement from a previous response, e.g., OPEN_NOW.
  • locale sets the language and region of the results, e.g., en-US or fr-FR.

Register at SerpApi to get your API key, and keep it private.

Playground

Try the request live in the SerpApi Playground.

Apple Maps API results in the SerpApi Playground

Code examples

The code examples read your API key from the SERPAPI_API_KEY environment variable:

export SERPAPI_API_KEY="SERPAPI_API_KEY"

Each example searches Apple Maps for coffee in Austin, Texas, and prints the position, title, and address of each place.

curl integration

Send the request with curl, which prints the full JSON response:

curl --get https://serpapi.com/search \
 --data-urlencode engine="apple_maps" \
 --data-urlencode query="coffee" \
 --data-urlencode location="Austin, Texas, United States" \
 --data-urlencode api_key="$SERPAPI_API_KEY"

JavaScript integration

Install the SerpApi JavaScript library and set your project to use ES modules:

npm install serpapi
npm pkg set type=module

Create an index.js file:

import { getJson } from "serpapi";

const results = await getJson({
  engine: "apple_maps",
  api_key: process.env.SERPAPI_API_KEY,
  query: "coffee",
  location: "Austin, Texas, United States",
});

for (const place of results.local_results ?? []) {
  console.log(place.position, place.title, place.address);
}

Run it with node index.js.

Python integration

Install the SerpApi Python library:

pip install serpapi

Create a main.py file:

import os
import serpapi

client = serpapi.Client(api_key=os.getenv("SERPAPI_API_KEY"))
results = client.search({
    "engine": "apple_maps",
    "query": "coffee",
    "location": "Austin, Texas, United States",
})

for place in results.get("local_results", []):
    print(place["position"], place["title"], place["address"])

Run it with python main.py.

Ruby integration

Install the SerpApi Ruby library:

gem install serpapi

Create a main.rb file:

require "serpapi"

client = SerpApi::Client.new(engine: "apple_maps", api_key: ENV.fetch("SERPAPI_API_KEY"))
results = client.search(query: "coffee", location: "Austin, Texas, United States")

results.fetch(:local_results, []).each do |place|
  puts "#{place[:position]} #{place[:title]} #{place[:address]}"
end

client.close

Run it with ruby main.rb.

PHP integration

Install the SerpApi PHP library:

composer require serpapi/serpapi-php

Create an index.php file:

<?php
require 'vendor/autoload.php';

use SerpApi\Client;

$client = new Client(getenv('SERPAPI_API_KEY'), 'apple_maps');
$results = $client->search([
  'query' => 'coffee',
  'location' => 'Austin, Texas, United States',
]);

foreach ($results->local_results ?? [] as $place) {
  echo $place->position . ' ' . $place->title . ' ' . $place->address . PHP_EOL;
}

Run it with php index.php.

Go integration

Create a Go module and install the SerpApi Go library:

go mod init example.com/maps
go get github.com/serpapi/serpapi-golang

Create a main.go file:

package main

import (
	"fmt"
	"os"

	"github.com/serpapi/serpapi-golang"
)

func main() {
	setting := serpapi.NewSerpApiClientSetting(os.Getenv("SERPAPI_API_KEY"))
	setting.Engine = "apple_maps"
	client := serpapi.NewClient(setting)

	results, err := client.Search(map[string]string{
		"query":    "coffee",
		"location": "Austin, Texas, United States",
	})
	if err != nil {
		panic(err)
	}

	localResults, _ := results["local_results"].([]interface{})
	for _, item := range localResults {
		place := item.(map[string]interface{})
		fmt.Println(place["position"], place["title"], place["address"])
	}
}

Run it with go run ..

Rust integration

Create a Cargo project and add the SerpApi Rust library and Tokio:

cargo new maps && cd maps
cargo add serpapi tokio --features tokio/full

Replace src/main.rs with:

use serpapi::serpapi::Client;
use std::collections::HashMap;
use std::env;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut default = HashMap::new();
    default.insert("api_key".to_string(), env::var("SERPAPI_API_KEY")?);
    default.insert("engine".to_string(), "apple_maps".to_string());
    let client = Client::new(default)?;

    let mut parameter = HashMap::new();
    parameter.insert("query".to_string(), "coffee".to_string());
    parameter.insert("location".to_string(), "Austin, Texas, United States".to_string());

    let results = client.search(parameter).await?;
    if let Some(local_results) = results["local_results"].as_array() {
        for place in local_results {
            println!(
                "{} {} {}",
                place["position"],
                place["title"].as_str().unwrap_or_default(),
                place["address"].as_str().unwrap_or_default()
            );
        }
    }
    Ok(())
}

Run it with cargo run.

Other programming languages

Official libraries are also available for Java, .NET, Swift, and C++. See SerpApi integrations for setup guides, or use a simple GET request from any programming language.

Errors

Failed requests return an HTTP error status and a JSON body with an error message. The most common are 401 for an invalid API key, 400 for a missing required parameter such as query, and 429 when you exceed your hourly throughput limit or run out of searches. See API status and error codes for the full list.

Output formats: JSON and Markdown

Choose structured JSON for applications or Markdown for LLMs and AI agents:

  • JSON is the default output and is useful when you need individual result fields.
  • Add output=md to receive Markdown instead, which is more token-efficient.

Markdown is plain text, not JSON: YAML front matter with the search metadata, followed by tables of the places. Read the response body as text instead of parsing it.

Client Markdown request
curl --data-urlencode output="md"
Python client.search({..., "output": "md"})
PHP $client->md([...])
Rust client.md(parameter).await?

If your SDK doesn't have a Markdown helper yet, send a plain HTTP request with output=md and read the body as text. Learn more about Markdown output.

Apple Maps API parameters

See the Apple Maps API documentation for more details.

Name Description Requirement
Search query
query The search query: anything you'd use in a regular Apple Maps search (e.g., coffee). Required
Geographic location
center The center of the area to search, as latitude,longitude (e.g., 30.324639,-97.7304611 for Austin, Texas). Either center or location is required, and they can't be used together. Optional
span The width and height of the area to search, as latitudeDelta,longitudeDelta (e.g., 0.05,0.05). Smaller values search a smaller area. Optional
location The location to search from (e.g., Austin, Texas, United States). Either center or location is required, and they can't be used together. Optional
Refinement parameters
sort The order of the places: default for the best match (default), distance from the center or location, or ratings. Optional
toggles Comma-separated toggle keys to filter the places by (e.g., OPEN_NOW). The available toggles are in refinement.toggles of the response. Optional
multi_select_options Comma-separated option keys to filter the places by, such as chains, prices, or amenities. The available options are in refinement.multi_select of the response. Optional
open_at Only return places open at this time, as a Unix timestamp in the next 24 hours (e.g., 1793819769). Optional
Localization
locale The language and region of the results, as <LANGUAGE>-<REGION> (e.g., en-US, fr-FR). Defaults to en-US. See Apple Maps locales for supported locales. Optional
SerpApi parameters
engine Set to apple_maps. Required
api_key Your private SerpApi API key. Required
no_cache Set to true to request fresh results instead of using the one-hour cache. Can't be combined with async. Optional
async Set to true for later retrieval through the Searches Archive API. Can't be combined with no_cache or used with Ludicrous Speed enabled. Optional
zero_trace Enterprise only. Set to true to skip storing search parameters, files, and metadata on SerpApi servers. Optional
output Set to json (default), html for the raw HTML retrieved, or md for Markdown. Optional
json_restrictor Limit the JSON response to the fields you need. See the JSON Restrictor documentation. Optional

Available data on Apple Maps (JSON response)

Each item in local_results is a place, and each item in guide_results is a guide of places, such as The Best Coffee Shops In Austin. When the query matches a single place, it's returned in place_results instead. The field guides below describe the possible fields and their types; they aren't literal API responses.

What you get depends on the place

Some fields appear only when Apple Maps shows them:

Place Fields
A place with reviews from Yelp or Tripadvisor user_reviews with the most relevant reviews, plus SerpApi links to the place and its reviews with the matching API
A place with a price level price, e.g., $$, price_score, and max_price_score
A place with online ordering actions, e.g., Order or Menu, and order_online
A place described by a publisher text, e.g., a review from The Infatuation
A place featured in guides collection with the guides
A place inside a larger place contained_place and located_in, e.g., Downtown, Austin

Each place has a muid and a serpapi_link to its details with the Apple Maps Places API.

Local results

Each place in local_results can include these fields:

{
  "local_results": [
    {
      "position": "Integer - Position of the place in the local results",
      "position_in_page": "Integer - Position of the place on the page, counting guides",
      "muid": "String - Apple Maps ID of the place",
      "provider_id": "Integer - ID of the data provider",
      "link": "String - Link to the place on Apple Maps",
      "serpapi_link": "String - SerpApi link to the details of the place",
      "title": "String - Name of the place",
      "gps_coordinates": {
        "latitude": "Float - Latitude of the place",
        "longitude": "Float - Longitude of the place"
      },
      "rating": "Float - Rating of the place, e.g., 4.46 out of 5, or 91 out of 100 for Apple ratings",
      "max_rating": "Integer - Maximum rating: 5, or 100 for Apple ratings",
      "reviews": "Integer - Number of reviews",
      "ratings": {
        "attribution": {
          "name": "String - Source of the ratings, e.g., Apple, Yelp, or Foursquare",
          "link": "String - Link to the place on the source"
        },
        "values": [
          {
            "type": "String - Type of rating: USER_RATING, APPLE_RATING, or PRICE_RANGE",
            "category": "String - What Apple Maps users rated, e.g., Food & Drink",
            "rating": "Float - Rating, e.g., 4.46, or a percentage for Apple ratings",
            "max_rating": "Integer - Maximum rating, e.g., 5, or 100 for Apple ratings",
            "reviews": "Integer - Number of reviews or ratings"
          }
        ]
      },
      "address": "String - Full address of the place",
      "structured_address": {
        "short": "String - Short address, e.g., 401 Congress Ave, Austin",
        "formatted_lines": "Array[String] - Lines of the address",
        "city_and_above": "String - City, state, and country, e.g., Austin, TX United States",
        "country": "String - Country, e.g., United States",
        "country_code": "String - Two-letter country code, e.g., US",
        "administrative_area": "String - State or region, e.g., Texas",
        "sub_administrative_area": "String - County, e.g., Travis",
        "locality": "String - City, e.g., Austin",
        "post_code": "String - Postal code, e.g., 78701",
        "sub_locality": "String - Neighborhood, e.g., Congress Ave District",
        "thoroughfare": "String - Street, e.g., Congress Ave",
        "full_thoroughfare": "String - Street and number, e.g., 401 Congress Ave",
        "dependent_locality": "Array[String] - Areas the place is in, e.g., Downtown"
      },
      "phone": "String - Phone number, e.g., +15123946051",
      "phone_formatted": "String - Formatted phone number, e.g., +1 (512) 394-6051",
      "website": "String - Website of the place",
      "about": "String - Description of the place by the business",
      "unclaimed_listing": "Boolean - Whether the business hasn't claimed the place on Apple Business Connect",
      "claim_listing_link": "String - Link to claim the place",
      "amenities": [
        {
          "name": "String - Amenity, e.g., Accepts Apple Pay",
          "id": "String - ID of the amenity, e.g., crossbusiness.payments.applepay"
        }
      ],
      "timezone": "String - Time zone of the place, e.g., America/Chicago",
      "open_state": "String - Whether the place is open now, e.g., Open till 7 PM",
      "weekly_hours": {
        "monday": "Array[String] - Opening hours on Monday, e.g., 06:30 - 19:00"
      },
      "images": [
        {
          "thumbnail": "String - Link to the photo",
          "title": "String - Caption of the photo",
          "category_id": "String - ID of the photo category, e.g., foodanddrink",
          "category_name": "String - Name of the photo category, e.g., Food & Drink",
          "attribution": {
            "name": "String - Source of the photo, e.g., Foursquare",
            "link": "String - Link to the photo on the source"
          }
        }
      ],
      "contained_place": {
        "type": "String - Type of the place, e.g., Coffee Shop",
        "name": "String - Name of the larger place, e.g., Downtown, Austin",
        "muid": "String - Apple Maps ID of the larger place",
        "link": "String - Link to the larger place on Apple Maps",
        "serpapi_link": "String - SerpApi link to the details of the larger place"
      },
      "located_in": "String - Name of the larger place",
      "actions": [
        {
          "title": "String - Action, e.g., Order or Menu",
          "links": "Array[String] - Links to take the action"
        }
      ],
      "order_online": "String - Link to order online",
      "text": {
        "title": "String - Source of the description, e.g., The Infatuation",
        "value": "String - Description of the place",
        "attribution_url": "String - Link to the description on the source"
      },
      "user_reviews": {
        "attribution": {
          "name": "String - Source of the reviews, e.g., Yelp",
          "link": "String - Link to the place on the source",
          "serpapi_yelp_place_link": "String - SerpApi link to the place with the Yelp Place API",
          "serpapi_yelp_reviews_link": "String - SerpApi link to the reviews with the Yelp Reviews API"
        },
        "most_relevant": [
          {
            "username": "String - Name of the reviewer",
            "rating": "Integer - Rating of the review",
            "max_rating": "Integer - Maximum rating, e.g., 5",
            "user_thumbnail": "String - Link to the photo of the reviewer",
            "description": "String - Text of the review",
            "link": "String - Link to the review",
            "date": "String - Date of the review, e.g., 2026-09-01 14:24:58 +0000",
            "id": "String - ID of the review"
          }
        ]
      },
      "price": "String - Price level, e.g., $$",
      "price_score": "Integer - Price level as a number, e.g., 2",
      "max_price_score": "Integer - Maximum price level, e.g., 4",
      "types": "Array[String] - Types of the place, e.g., Dining, Coffee Shop, Cafe",
      "type_ids": "Array[String] - IDs of the types, e.g., dining, coffee_shop, cafe",
      "type": "String - Main type of the place, e.g., Coffee Shop",
      "type_id": "String - ID of the main type, e.g., coffee_shop",
      "collection": "Array[Object] - Guides featuring the place, with the same fields as guide_results",
      "attribution": {
        "name": "String - Main data provider of the place, e.g., Foursquare or Yelp",
        "link": "String - Link to the place on the provider",
        "serpapi_yelp_place_link": "String - SerpApi link to the place with the Yelp Place API, if the provider is Yelp"
      }
    }
  ]
}

weekly_hours has a key for each day of the week, from monday to sunday.

Guide results

Each guide in guide_results can include these fields:

{
  "guide_results": [
    {
      "position": "Integer - Position of the guide in the guide results",
      "position_in_page": "Integer - Position of the guide on the page, counting places",
      "muid": "String - Apple Maps ID of the guide",
      "title": "String - Title of the guide, e.g., The Best Coffee Shops In Austin",
      "description": "String - Description of the guide",
      "link": "String - Link to the guide on the publisher's website",
      "apple_maps_link": "String - Link to the guide on Apple Maps",
      "item_count": "Integer - Number of places in the guide",
      "publisher": {
        "name": "String - Name of the publisher, e.g., The Infatuation",
        "subtitle": "String - Tagline of the publisher",
        "link": "String - Website of the publisher"
      },
      "photos": [
        {
          "link": "String - Link to the cover photo",
          "width": "Integer - Width in pixels",
          "height": "Integer - Height in pixels"
        }
      ],
      "items": [
        {
          "muid": "String - Apple Maps ID of a place in the guide",
          "link": "String - Link to the place on Apple Maps",
          "serpapi_link": "String - SerpApi link to the details of the place"
        }
      ]
    }
  ]
}

Refinement

refinement lists the filters available for the search. Pass the key values to toggles or multi_select_options:

{
  "refinement": {
    "toggles": {
      "open_now": {
        "display_name": "String - Name of the filter, e.g., Open Now",
        "key": "String - Value for the toggles parameter, e.g., OPEN_NOW"
      }
    },
    "multi_select": {
      "price": {
        "display_name": "String - Name of the filter, e.g., All Prices",
        "options": [
          {
            "display_name": "String - Name of the option, e.g., $",
            "key": "String - Value for the multi_select_options parameter"
          }
        ]
      }
    },
    "sort": "String - Sort order applied to the search: default, distance, or ratings"
  }
}

The available filters depend on the search, e.g., Open Now, Top Rated, and Free Wi-Fi toggles, or chain, price, and amenity options for coffee shops.

AI agents and no-code

MCP

Give AI agents and assistants an Apple Maps search tool with the hosted SerpApi MCP server at https://mcp.serpapi.com/mcp.

Claude Code:

claude mcp add --transport http serpapi https://mcp.serpapi.com/mcp --header "Authorization: Bearer $SERPAPI_API_KEY"

Codex, which reads the key from SERPAPI_API_KEY:

codex mcp add serpapi --url https://mcp.serpapi.com/mcp --bearer-token-env-var SERPAPI_API_KEY

Other MCP clients:

{
  "mcpServers": {
    "serpapi": {
      "type": "http",
      "url": "https://mcp.serpapi.com/SERPAPI_API_KEY/mcp"
    }
  }
}

The server's engine catalog includes the apple_maps engine, and its serpapi://engines/apple_maps resource describes the parameters. Ask your agent to search Apple Maps with the apple_maps engine. The resulting tool call looks like this:

{
  "name": "search",
  "arguments": {
    "params": {
      "engine": "apple_maps",
      "query": "coffee",
      "location": "Austin, Texas, United States"
    }
  }
}

See the MCP integration guide for more clients and self-hosting.

CLI

Search Apple Maps from your terminal or from AI agent workflows with the SerpApi CLI:

brew tap serpapi/homebrew-tap
brew install serpapi-cli

The CLI picks up SERPAPI_API_KEY from your environment. You can also run serpapi login to save a key.

serpapi search engine=apple_maps query=coffee location="Austin, Texas, United States"
serpapi search engine=apple_maps query=coffee location="Austin, Texas, United States" --fields "local_results[].{title, address, rating}"
serpapi search engine=apple_maps query=coffee location="Austin, Texas, United States" output=md

No-code tools

Use SerpApi APIs without writing code:

Use cases

  • Build lead lists of local businesses with phone numbers, websites, and addresses.
  • Monitor how your business and its competitors appear on Apple Maps, including ratings and opening hours.
  • Find places that haven't been claimed on Apple Business Connect.
  • Compare Apple Maps and Google Maps results for the same search.
  • Discover popular places from guides by publishers like The Infatuation.
  • Give AI agents and RAG pipelines a local search tool.

Related scrapers

Resources

Contact

Feel free to reach out at contact@serpapi.com.

About

Scrape Apple Maps search results with a simple API. Get places with their addresses, phone numbers, websites, ratings, opening hours, and photos.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors