# Brave Maps Scraper (`aerodynamic_tripod/brave-maps-scraper`) Actor

Scrape local business results from Brave Maps by search term and location. Get business names, categories, addresses, phone numbers, websites, coordinates, opening hours, images, observed search rank, and optional place-detail enrichment.

- **URL**: https://apify.com/aerodynamic\_tripod/brave-maps-scraper.md
- **Developed by:** [SearchShark Tools](https://apify.com/aerodynamic_tripod) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.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.

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

## 📍 Brave Maps Scraper

**Brave Maps Scraper** lets you extract **structured local business data from Brave Maps** using keywords and a location.

Generate **local business leads**, analyze competitors, research markets, and collect business contact data **without manually searching Brave Maps**.

- 🎯 **Generate business leads:** collect business names, phone numbers, websites, addresses, and coordinates
- 📊 **Analyze competitors:** compare categories, business locations, and observed Brave Maps visibility
- 📍 **Research local markets:** discover businesses operating in a specific city, state, region, or country
- 🔎 **Track search visibility:** preserve the observed Brave Maps result rank for every query
- 🧹 **Get cleaner data:** branch-safe deduplication reduces duplicate appearances without merging separate locations
- 🖼 **Collect business media:** extract primary and additional business images when available
- 🔗 **Enrich business records:** optionally request Brave Maps place details for additional structured data
- ⚡ **Automate workflows:** export structured results to Apify Dataset, API, integrations, or downstream applications

***

### 📦 What data does Brave Maps Scraper extract?

| | |
| --- | --- |
| 🏢 **Business name** | 🆔 **Brave Place ID** |
| 🏷 **Category** | 📍 **Address** |
| 📌 **Latitude** | 📌 **Longitude** |
| ☎️ **Phone number** | 🌐 **Website** |
| 🕐 **Opening hours** when available | 🖼 **Primary image** |
| 🖼 **Additional images** | 🏆 **Observed Brave Maps rank** |
| 🔍 **Search query** | 🌍 **Search location** |
| 🔗 **Brave Maps source URL** | 🕒 **Scrape timestamp** |
| ⭐ **Rating** when available | 💬 **Review count** when available |
| 💰 **Price range** when available | ✉️ **Email** when available |
| 🔗 **External profiles** when available | 🌐 **Timezone** when available |

> **Missing fields are returned as `null` or an empty array where appropriate.** The Actor does **not invent business data** that Brave Maps does not expose.

***

### 🚀 Features

Brave Maps Scraper is designed for **lead generation**, **local-search research**, and **business-data automation**.

- **Multiple search terms:** search multiple keywords or business categories in one Actor run
- **One location per run:** apply the same location to every search term
- **Up to 100 unique businesses per search term**
- **Observed Brave Maps ranking:** preserve the position where the business appeared during the scrape
- **Branch-safe deduplication:** different physical business locations are not incorrectly merged
- **Optional place-detail enrichment:** collect additional structured business data when available
- **Business images:** capture a primary image plus additional image URLs
- **Independent query results:** the same business can appear separately for different search terms
- **Retry handling:** temporary search failures are retried automatically
- **Partial failure protection:** successful queries remain available even if another query fails
- **Detail failure protection:** a failed place-detail request never removes a valid business from the Dataset
- **API-friendly output:** every Dataset row follows a predictable schema
- **Browser-backed Brave Maps session:** requests run inside a normal Brave Maps browser session

***

## ⬇️ Input

You can configure Brave Maps Scraper directly from the **Apify Console** or send input programmatically through the **Apify API**.

### 🔎 Search terms

Add one or more business keywords or categories.

Example:

```text
plumber
electrician
HVAC contractor
dentist
```

**Each search term is processed independently.**

For example:

```text
Search term:
plumber

Location:
Los Angeles, California
```

creates one Brave Maps search.

Adding:

```text
plumber
HVAC contractor
dentist
```

creates three independent searches using the same location.

***

### 📍 Location

Enter the location that should be applied to every search term.

Example:

```text
Los Angeles, California
```

Other examples:

```text
Phoenix, Arizona
Miami, Florida
Austin, Texas
New York, New York
London, United Kingdom
Sydney, Australia
```

The current version supports **one location per Actor run**.

***

### 🔢 Maximum results per search

Set the maximum number of unique businesses to collect for **each search term**.

```text
Minimum: 1
Default: 100
Maximum: 100
```

For example:

```text
Search terms:
plumber
electrician

Maximum results per search:
100
```

can return up to:

```text
100 plumbers
+
100 electricians
=
200 Dataset rows
```

The requested number is a **maximum, not a guarantee**.

If Brave Maps exposes fewer businesses for the requested search, the Actor returns the businesses that are available rather than generating fake or duplicate records.

***

### 🔎 Include place details

Enable:

```text
Include place details
```

to request the Brave Maps place-detail response for each business.

Default:

```text
true
```

When enabled, the Actor may enrich businesses with additional information such as:

```text
Additional images
External profiles
Richer opening-hours data
Contact information
Price range
Timezone
Other structured place metadata
```

Availability depends on the individual business.

#### Faster mode

Set:

```json
"includeDetails": false
```

to skip individual place-detail requests.

This can significantly reduce run time when you only need the information already available in Brave Maps search results.

***

### 🌐 Proxy configuration

**Apify Proxy is enabled by default.**

The Brave Maps search runs through a browser session using the configured proxy.

Example:

```json
{
  "useApifyProxy": true
}
```

You can adjust proxy settings through the standard Apify proxy configuration input.

***

### 🧪 Example input

```json
{
  "searchTerms": [
    "plumber",
    "HVAC contractor"
  ],
  "location": "Los Angeles, California",
  "maxResultsPerSearch": 50,
  "includeDetails": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

***

## ⬆️ Output

Results are stored in the Actor's default **Apify Dataset**.

You can access results from:

```text
Output
Storage
Apify API
Integrations
```

Each Dataset row represents **one business appearance for one search query**.

***

### 📊 Example result

```json
{
  "bravePlaceId": "loc4ASFWRYHMARAUBNEUFQT...",
  "name": "JW Plumbing, Heating and Air",
  "category": "HVAC Contractor",
  "address": "904 Wall St Ste 203, Los Angeles, CA 90015",
  "phone": "+12133795931",
  "website": "https://jwheatingandair.com/",
  "latitude": 34.0384789,
  "longitude": -118.2520235,
  "openingHours": null,
  "imageUrl": "https://...",
  "images": [
    "https://...",
    "https://..."
  ],
  "rank": 2,
  "query": "plumber",
  "location": "Los Angeles, California",
  "sourceUrl": "https://search.brave.com/maps/search?...",
  "scrapedAt": "2026-09-08T09:35:41.000Z",
  "rating": null,
  "reviewCount": null,
  "priceRange": null,
  "email": null,
  "profiles": null,
  "timezone": null
}
```

***

### 🏆 Observed Brave Maps rank

One of the most useful fields returned by the Actor is:

```text
rank
```

This means:

> **Observed Brave Maps result position for this query during this scrape.**

For example:

```text
Business A → rank 1
Business B → rank 2
Business C → rank 7
```

Rank is captured from the original Brave Maps result order.

If duplicate appearances are removed, the remaining businesses are **not renumbered**.

For example, if the same business appears at:

```text
Rank 3
Rank 19
Rank 42
```

the Actor keeps the first observed appearance:

```text
rank: 3
```

The remaining results keep their original positions.

This preserves the **actual Brave Maps search provenance**.

> Brave Maps rankings can change over time and may vary depending on search context. `rank` should not be interpreted as a permanent or universal business ranking.

***

### 🧹 Branch-safe deduplication

Businesses are deduplicated **within each search query**.

Identity is determined using the strongest available signal.

The Actor uses the following hierarchy:

```text
1. Brave Place ID
2. Normalized domain + address
3. Phone + address
4. Business name + address
5. Business name + coordinates
```

If none of those signals are available, the Actor does **not** attempt fuzzy merging.

***

### 🏪 Different business branches remain separate

Different physical locations can share:

```text
Business name
Website
Domain
Phone number
Brand
```

while still representing different businesses or branches.

If Brave Maps provides different Place IDs for the locations, they remain separate.

Example:

```text
Business Name — Address A — Brave Place ID A
Business Name — Address B — Brave Place ID B
```

remain two Dataset rows.

The Actor does not merge different branches simply because their names are similar.

***

### 🔍 Multiple search terms

Every search term has its own search context.

For example, the same business may appear as:

```text
ABC Home Services
Query: plumber
Rank: 4
```

and:

```text
ABC Home Services
Query: HVAC contractor
Rank: 11
```

**Both rows are retained.**

This is intentional because they represent **two different search appearances**.

The Actor does **not globally deduplicate businesses across different search terms**.

This makes the output useful for analyzing which businesses appear across multiple categories and how their observed positions differ.

***

### ⭐ Ratings and review counts

`rating` and `reviewCount` are included in the output schema but should be considered **optional fields**.

Brave Maps does not currently expose authoritative structured rating and review-count data for every place.

The Actor only uses structured business data when it is actually available.

It does **not** derive review counts from unrelated web-result snippets or text such as:

```text
Read 150 reviews
```

If an authoritative structured value is unavailable, the Actor returns:

```json
"rating": null,
"reviewCount": null
```

rather than inventing or estimating values.

***

### 🔗 External profiles

When **Include place details** is enabled, Brave Maps may expose external profile information.

For example:

```text
Official website
Facebook
Twitter / X
Other business profiles
```

These are returned in:

```text
profiles
```

when available.

Not every business provides profile data.

***

### 🖼 Business images

The Actor can return:

```text
imageUrl
images
```

`imageUrl` contains the primary selected business image.

`images` contains the available image URLs collected for that business.

Image availability varies by listing.

Some businesses may return:

```json
"imageUrl": null,
"images": []
```

***

### 🕐 Opening hours

Opening-hours information is returned in:

```text
openingHours
```

when Brave Maps exposes structured opening-hours data.

The exact information available can vary by business.

The Actor does not fabricate missing schedules.

***

### ⚡ Performance

Brave Maps Scraper uses a **browser-backed architecture**.

Brave Maps search traffic is collected from a normal browser session and then parsed into structured Dataset records.

#### With place details disabled

Using:

```json
"includeDetails": false
```

requires only the main Brave Maps search workflow and is generally faster.

#### With place details enabled

Using:

```json
"includeDetails": true
```

requests additional place details for individual businesses.

A 100-business search therefore performs substantially more work than a list-only search.

Use detail enrichment when you need the additional metadata.

***

### 🛡 Reliability

Temporary search failures are automatically retried.

If you search:

```text
plumber
electrician
roofing contractor
```

and only one query fails after retries, successful results from the other queries remain in the Dataset.

If **every search fails**, the Actor run fails instead of silently reporting a successful empty run.

***

### 🛡 Detail enrichment protection

A failed place-detail request does **not** discard the valid Brave Maps search result.

For example, if Brave Maps returns:

```text
Business name
Address
Phone
Website
Coordinates
```

but its individual detail request fails, the Actor still saves the available list-level business data.

This helps prevent temporary detail-response problems from causing otherwise valid business leads to disappear.

***

## 🔌 API & integrations

Brave Maps Scraper can be used programmatically through the **Apify API**.

You can connect the results to workflows such as:

- Google Sheets
- Make
- Zapier
- CRMs
- Internal APIs
- Data warehouses
- Lead-generation systems
- AI agents
- MCP workflows

Each Actor run stores structured results in the default **Apify Dataset**, making them easy to consume from another application.

***

## 💡 Example use cases

#### 🎯 Local lead generation

Search:

```text
roofing contractor
HVAC contractor
plumber
```

Location:

```text
Phoenix, Arizona
```

Build prospect lists containing:

```text
Business name
Phone
Website
Address
Category
Coordinates
Observed rank
```

Use the results for:

```text
Outbound sales
Business prospecting
CRM imports
Local marketing
Market expansion
```

***

#### 📊 Competitor research

Search a business category and analyze:

```text
Which companies appear highest
Which businesses appear across multiple keywords
Business locations
Website coverage
Phone availability
Category coverage
Observed Brave Maps visibility
```

***

#### 📍 Market research

Compare businesses Brave Maps exposes for different categories within a market.

Use results to identify:

```text
Market saturation
Potential service gaps
Competitive categories
Local business concentration
Geographic coverage
```

***

#### 🔎 Local search visibility research

Run the same business category periodically and compare:

```text
Observed result rank
New businesses appearing
Businesses disappearing
Changes in category visibility
Changes in local competition
```

Remember that Brave Maps rank is an **observed result position**, not a guaranteed permanent ranking.

***

#### 🤖 Automated business-data pipelines

Use the Apify API to automatically:

```text
Start Brave Maps searches
Download Dataset results
Push business data into a CRM
Feed local business data into AI workflows
Update internal lead databases
Trigger downstream enrichment
```

***

## ⚠️ Current limitations

The current version focuses on **reliable Brave Maps keyword + location search**.

It currently supports:

```text
Multiple search terms
One location per run
Up to 100 results per search term
Optional place-detail enrichment
Business contact information
Business images
Observed search rank
Structured Dataset output
```

It does **not currently perform**:

```text
Multiple locations in one run
Grid-based geographic crawling
Hidden map panning
Unlimited result pagination
Detailed review extraction
Full customer review scraping
Business website crawling
Website email discovery
Employee/contact enrichment
Deep social-media enrichment
```

These capabilities are intentionally separate from the core Brave Maps search workflow.

***

## ❓ FAQ

### How does Brave Maps Scraper work?

The Actor combines each search term with your selected location and opens the corresponding Brave Maps search.

It then:

```text
Loads Brave Maps
Captures structured business results
Preserves result order
Removes duplicate appearances within the query
Optionally fetches place details
Normalizes business information
Stores results in an Apify Dataset
```

***

### How many businesses can I scrape?

The current maximum is:

```text
100 unique businesses per search term
```

Brave Maps may expose fewer businesses.

For example, if you request:

```text
100
```

and only 73 unique businesses are available from the returned Brave Maps result pool, the Actor returns those available businesses.

***

### Can I search multiple business categories?

**Yes.**

Example:

```json
{
  "searchTerms": [
    "plumber",
    "electrician",
    "HVAC contractor",
    "roofing contractor"
  ]
}
```

Each term is searched independently.

***

### Can I search multiple locations in one run?

**Not in the current version.**

One location is applied to all search terms.

For example:

```json
{
  "searchTerms": [
    "plumber",
    "electrician"
  ],
  "location": "Los Angeles, California"
}
```

runs both searches in Los Angeles.

***

### Why are some fields null?

Brave Maps does not expose every field for every business.

The Actor deliberately returns:

```text
null
```

when information cannot be determined confidently.

It does not fabricate missing business data.

***

### Why are rating and review count often null?

Brave Maps place responses do not currently provide authoritative structured ratings and review counts for every business.

The Actor only outputs those values when they are available from structured business data.

It does not infer them from unrelated web-result snippets.

***

### Why do rank numbers sometimes have gaps?

Because rank represents the **original Brave Maps result position**.

If a duplicate appearance is removed, the remaining results are not renumbered.

Example:

```text
Original Brave positions:

1
2
3
4
5
```

If the business at rank `3` is a duplicate, the Dataset may contain:

```text
1
2
4
5
```

This preserves the actual observed Brave Maps ordering.

***

### Can the same business appear more than once?

Yes, when it appears under **different search terms**.

Example:

```text
Business: ABC Home Services
Query: plumber
Rank: 3
```

and:

```text
Business: ABC Home Services
Query: HVAC contractor
Rank: 7
```

Both are retained because they represent different search appearances.

***

### What does Include place details do?

When enabled, the Actor makes an additional Brave Maps place request for each business.

This can provide richer data such as:

```text
Additional images
External profiles
Additional contact information
Opening-hour details
Price information
Timezone information
```

when Brave Maps exposes it.

***

### Should I disable Include place details?

Disable it when speed matters more than enrichment.

Example:

```json
{
  "includeDetails": false
}
```

The Actor will still return the business information available from the main Brave Maps search results.

***

### Can I use Brave Maps Scraper through an API?

**Yes.**

Every Actor can be started through the **Apify API**, and its Dataset can be downloaded programmatically.

This makes the scraper suitable for automated lead-generation and business-data pipelines.

***

### Can I export the results?

**Yes.**

Apify Dataset results can be exported in supported formats such as:

```text
JSON
CSV
Excel
XML
HTML
```

***

### Is a browser required?

**Yes for the current Brave Maps workflow.**

Brave Maps Scraper uses a normal browser-backed session to access the Brave Maps search transport reliably.

The Actor does not require a Brave API key.

***

### Does Brave Maps Scraper use the official Brave Search API?

**No.**

This Actor extracts results from the Brave Maps web experience.

It does not require users to provide a Brave Search API key.

***

## 🧭 Recommended workflow

For strong local lead-generation coverage, use **distinct business categories** instead of many nearly identical search terms.

Good:

```text
plumber
electrician
HVAC contractor
roofing contractor
```

Less useful:

```text
plumber
plumbers
plumbing
plumbing company
plumbing companies
```

Very similar keywords may return heavily overlapping business pools.

Distinct categories generally provide more useful coverage.

***

### 💡 Fast lead-generation workflow

If you mainly need:

```text
Business name
Address
Phone
Website
Category
Coordinates
Rank
```

use:

```json
{
  "includeDetails": false
}
```

This avoids individual business-detail requests and can make large runs significantly faster.

***

### 💡 Enriched-data workflow

If you also want the maximum available Brave Maps metadata, use:

```json
{
  "includeDetails": true
}
```

This is the default.

The Actor will attempt to enrich every selected business while preserving the original list result even when enrichment is unavailable.

***

## 💬 Feedback & support

Found a bug or have a feature request?

Use the Actor's **Issues** tab on Apify.

Useful future additions may include:

```text
Multiple locations
Area/grid search
Additional local-search intelligence
Website contact enrichment
Additional business detail fields
Social profile normalization
Enhanced export fields
```

***

### 🚀 Brave Maps business data without the manual searching

Enter your keywords, choose a location, run the Actor, and receive **structured Brave Maps business data** ready for:

```text
Lead generation
Competitor research
Local market analysis
APIs
CRM workflows
Automation
AI agents
```

**Search Brave Maps once. Use the business data everywhere.**

# Actor input Schema

## `searchTerms` (type: `array`):

Business types or keywords to search for. Each search term is searched independently using the same location.

## `location` (type: `string`):

The location applied to every search term.

## `maxResultsPerSearch` (type: `integer`):

Maximum number of Brave Maps results to save for each search term. Brave Maps may return fewer results when fewer businesses are available.

## `includeDetails` (type: `boolean`):

Fetch the Brave Maps place detail response for each business to enrich fields such as profiles, additional images, and richer business information when available.

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

Proxy settings used for the Brave Maps browser session.

## Actor input object example

```json
{
  "searchTerms": [
    "plumber"
  ],
  "location": "Los Angeles, California",
  "maxResultsPerSearch": 100,
  "includeDetails": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Normalized Brave Maps business results saved to the default Dataset.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("aerodynamic_tripod/brave-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("aerodynamic_tripod/brave-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 '{}' |
apify call aerodynamic_tripod/brave-maps-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,aerodynamic_tripod/brave-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/BNs9qVRQ8HZcMTnEX/builds/aQ772YhnXI3wR9oWP/openapi.json
