# Gym Lead Scraper - Maps Social Booking (Unofficial) (`brainy_frostfield/gym-intelligence-engine`) Actor

UNOFFICIAL Google Maps gym lead scraper: Instagram/TikTok/Facebook, booking tech, gym type, amenities, phones and emails. Not affiliated with Google. No AI. Follow Apify AUP, privacy and anti-spam laws. Not for unsolicited mass messaging.

- **URL**: https://apify.com/brainy\_frostfield/gym-intelligence-engine.md
- **Developed by:** [Viv K](https://apify.com/brainy_frostfield) (community)
- **Categories:** Lead generation, Social media, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 place leads

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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

## Gym Lead Scraper – Maps Social Booking (Unofficial)

Build **CRM-ready fitness leads** from Google Maps: gyms, CrossFit boxes, yoga and pilates studios, boutique studios, combat gyms, and personal-training spaces. Beyond the basic listing, each result can include **Instagram / TikTok / Facebook**, a detected **booking or membership stack** (Mindbody, Wodify, PushPress, Glofox, and similar), a **gym type label**, **amenity and free-trial signals**, **validated phones**, and **public website emails** (optional free **MX** check on the domain).

**No AI language models. No Google Places API key required.**

> **UNOFFICIAL** — not affiliated with, endorsed by, or sponsored by Google LLC. Google Maps is a trademark of Google LLC.\
> You are solely responsible for complying with Google’s Terms of Service, privacy laws (GDPR/CCPA), anti-spam rules (CAN-SPAM/CASL), website terms, and [Apify’s Acceptable Use Policy](https://docs.apify.com/legal/acceptable-use-policy).\
> **Do not use for unsolicited mass messaging.** Scraping Google Maps may violate Google’s contractual terms even when data is publicly visible.

***

### What you get

This Actor is built for **fitness marketing agencies**, **gym software vendors**, **supplement and apparel brands**, **equipment suppliers**, and **local lead teams** who need more than a phone number:

| Layer | Examples |
|---|---|
| Maps listing | Name, address, phone, website, rating, reviews, hours, Maps URL, unclaimed signal |
| Social presence | Instagram handle + URL, TikTok, Facebook (from public site links only) |
| Booking technology | Mindbody, Wodify, Momence / Mariana Tek, Zen Planner, PushPress, Glofox, TeamUp, Pike13, GymMaster, Vagaro, and more |
| Studio type | CrossFit, Yoga, Pilates, Cycling, Barre, Martial Arts / Combat, Climbing, Dance Fitness, PT studio, Strength & Conditioning, Boutique, Traditional Gym |
| Offers & amenities | Free trial, 24/7 access, personal training, sauna, pool, childcare, group classes |
| Contact | E.164 phones, public emails, optional MX domain check |
| Prioritization | Opportunity score **HOT / WARM / COLD** plus contactability & intelligence scores |

Contacts, social profiles, and software signals are taken only from **Google Maps** and text/links that appear on **public** website pages. Nothing is invented by AI.

***

### Features

- Search **Google Maps** by city, region, or ZIP and fitness keywords
- Pull core place fields: **name, address, phone, website, rating, review count, category, hours, coordinates, Maps URL**
- Flag **unclaimed** listings when Maps shows claim-style language
- Crawl public pages (home, contact, classes, membership, booking, trial…) for deeper signals
- Extract **Instagram, TikTok, and Facebook** with handle validation (junk paths like `reel` / `explore` filtered out)
- Detect **booking / CRM widgets** from scripts, iframes, and membership links
- Classify **gym archetype** from name, Maps category, search query, and page text
- Detect **amenities** and marketing offers (free trial, 24/7, PT, sauna…)
- Note **pricing / membership** and **class schedule** page signals when visible
- Normalize phones with country-aware parsing (E.164 + national format)
- Collect **public emails**; optional free **MX** check (domain can receive mail — not mailbox proof)
- Score each lead for **sales opportunity** (missing Instagram, no website, no booking stack → higher score)
- Filters: phone only, email only, Instagram only, any social, booking stack only, include/exclude no website

***

### How to use

1. Add one or more **locations** (city or ZIP), e.g. `Austin, TX`.
2. Add **search terms**, e.g. `gyms`, `crossfit`, `yoga studio`, `pilates`, `martial arts`.
3. Keep **Max results per query** modest on the first run (default is **5**; try **10–20** once proxy works).
4. Leave **social graph**, **booking detection**, **gym type**, and **amenities** on for full intelligence (or turn off what you do not need).
5. Turn on **Extract emails** / **MX check** if you want website contacts.
6. Set proxy to **Apify Proxy → RESIDENTIAL** (strongly recommended for Maps).
7. Click **Start**, then open the dataset and export CSV/JSON.

#### Example input

```json
{
  "locations": ["Austin, TX"],
  "searchTerms": ["gyms"],
  "maxPlacesPerQuery": 10,
  "scanSocialGraph": true,
  "detectBookingSystems": true,
  "classifyGymType": true,
  "detectAmenities": true,
  "extractEmails": true,
  "extractWebsitePhones": true,
  "validateMxRecords": true,
  "maxWebsitePagesPerPlace": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

#### Input fields

| Field | Description |
|---|---|
| Target locations | Cities, states, or ZIPs to search |
| Search terms | Maps keywords (`gyms`, `crossfit`, `yoga studio`…) |
| Max results per query | Cap per location × term (defaults stay small for Store tests) |
| Max total places | Optional cap for the entire run |
| Extract Instagram / TikTok / Facebook | Social profiles from public website pages |
| Detect booking technology | Fitness booking / membership software signatures |
| Classify gym archetype | Studio type label for segmentation |
| Detect amenities & offers | Free trial, 24/7, PT, sauna, pool, childcare… |
| Extract emails | Public emails from website pages |
| Extract website phones | Extra phones from `tel:` links and page text |
| Validate MX | Free check that the email **domain** can receive mail |
| Max pages per website | How many public pages to open per domain |
| Min social confidence | Drop weak social matches (default 60) |
| Proxy for Google Maps | Prefer **RESIDENTIAL** |
| Filters | Phone / email / Instagram / social / booking only; include places with no website |

***

### Output example

```json
{
  "query": "gyms in Austin, TX",
  "businessName": "Iron Box Athletics",
  "gymTypePrimary": "CrossFit",
  "category": "Gym",
  "address": "1200 E 6th St, Austin, TX 78702",
  "primaryPhone": "+15125550142",
  "primaryPhoneNational": "(512) 555-0142",
  "hasPhone": true,
  "website": "https://ironbox.example",
  "emails": [
    {
      "email": "coach@ironbox.example",
      "source": "mailto",
      "confidence": 95,
      "mxValid": true
    }
  ],
  "primaryEmail": "coach@ironbox.example",
  "hasEmail": true,
  "instagramHandle": "ironbox_austin",
  "instagramUrl": "https://www.instagram.com/ironbox_austin",
  "instagramConfidence": 95,
  "hasInstagram": true,
  "tiktokHandle": null,
  "hasTikTok": false,
  "facebookUrl": "https://www.facebook.com/IronBoxAustinGym",
  "hasFacebook": true,
  "bookingSystems": [
    {
      "provider": "Mindbody",
      "category": "fitness_booking",
      "confidence": 91
    }
  ],
  "primaryBookingSystem": "Mindbody",
  "hasBookingSystem": true,
  "amenities": ["Free Trial", "Personal Training", "Group Classes"],
  "hasFreeTrialOffer": true,
  "hasPricing": true,
  "hasSchedule": true,
  "is24_7": false,
  "leadScore": 48,
  "leadTier": "COLD",
  "leadReasons": [
    "Instagram present — strong social foothold",
    "Booking system detected — possible upsell / integration play"
  ],
  "contactabilityScore": 42,
  "intelligenceScore": 45,
  "leadQualityScore": 87,
  "rating": 4.8,
  "reviewsCount": 214,
  "isUnclaimed": false,
  "googleMapsUrl": "https://www.google.com/maps/place/...",
  "scrapedAt": "2026-08-10T12:00:00.000Z"
}
```

#### How to read lead tiers

| Tier | Typical meaning |
|---|---|
| **HOT** | Weak digital footprint — often no website, no Instagram, unclaimed Maps, or no booking stack (high opportunity for agencies / software) |
| **WARM** | Some presence, but clear gaps (e.g. site without Instagram, missing schedule/pricing, thin reviews) |
| **COLD** | Stronger stack already (social + booking + contacts) — still useful for research, partnerships, or competitive lists |

Scores are **heuristics** to help you prioritize outreach. They are not purchase intent scores and are not guaranteed.

***

### Pricing

This Actor uses **pay per event + platform usage**. You pay both:

1. **Event fees** (below) — paid to the Actor developer
2. **Platform usage** — paid to Apify for compute, data transfer, storage, and **proxies**

#### Platform usage & residential proxy (important)

- Google Maps discovery runs a real browser. That traffic is **much heavier** than simple HTTP scrapes.
- For reliable Maps results, use **Apify Proxy → RESIDENTIAL**.
- Residential traffic is billed by Apify **per GB** (rate depends on your plan; often roughly **$7–$8 / GB** on lower plans — check your plan).
- On short test runs, **proxy + compute usually cost more than event fees**.
- Start small: **1 location × 1 keyword × low max results** before multi-city jobs.
- Without residential proxy you often get **0 Maps results** (you avoid that proxy charge, but you also get little or no data).

#### Event fees

| Event | When charged | Price |
|---|---|---|
| **Place lead** (`placeLead`) | Each fitness business saved to the dataset | **$0.004** ($4.00 per 1,000) |
| **Phone enrichment** (`phoneLead`) | Lead has at least one validated phone | **$0.005** ($5.00 per 1,000) |
| **Instagram enrichment** (`instagramLead`) | At least one Instagram profile found | **$0.006** ($6.00 per 1,000) |
| **Booking technology** (`bookingTechLead`) | At least one booking/CRM signature found | **$0.006** ($6.00 per 1,000) |

A small **Actor start** fee may also apply in Console (platform setting). Do not also charge per dataset row on top of these events, or you may be double-billed for the same lead.

#### Event fee examples (platform usage — including residential proxy — is extra)

| Result mix | Approx. event cost only |
|---|---|
| 1,000 places, phones only, no Instagram / booking | $4.00 places + $5.00 phones ≈ **$9.00 + usage** |
| 1,000 places, all with phone + Instagram | $4 + $5 + $6 ≈ **$15.00 + usage** |
| 1,000 places, ~50% Instagram, ~30% booking, all phones | $4 + $5 + ~$3 + ~$1.80 ≈ **~$13.80 + usage** |

Total cost scales with **locations × keywords × max results**, **website pages crawled**, **residential proxy GB**, and **compute**. Defaults stay small for Store auto-tests and inexpensive first runs.

***

### Tips

- **Always verify residential proxy** on a 3–5 place test before large city lists.
- Boutique studios and CrossFit boxes often expose richer **Instagram + booking** signals than big-box chains.
- Use search terms that match your offer (`yoga studio`, `crossfit`, `bjj`) for cleaner archetypes.
- Raise max website pages only when you care about membership/booking pages (more pages = more time and cost).
- Filter to **only with Instagram** or **only with booking tech** when building narrow lists for social or SaaS outreach.
- Many independent gyms hide email behind a form — check phones and socials even when `primaryEmail` is empty.
- More cities × more keywords × higher max results = longer runs and higher **proxy + compute** cost.

***

### Compliance & acceptable use

By running this Actor you agree to use it only for **lawful purposes** and in line with:

- [Apify Acceptable Use Policy](https://docs.apify.com/legal/acceptable-use-policy) (including **no unsolicited mass messaging**, no fraud, no abusive automation)
- [Apify General Terms and Conditions](https://docs.apify.com/legal/general-terms-and-conditions)
- Google’s Terms of Service and any website terms for domains you crawl
- Privacy laws (e.g. GDPR/CCPA) and anti-spam laws (e.g. CAN-SPAM/CASL) where they apply

This Actor is designed for **public business information only**. It does **not**:

- Bypass logins, CAPTCHAs, paywalls, or member-only areas
- Access private booking dashboards or authenticated APIs
- Invent contacts or fabricate reviews
- Send messages on your behalf

Business emails and phone numbers may still be personal data under privacy law. You are responsible for lawful collection, storage, and outreach. **Do not use this Actor for spam, phishing, harassment, or other illegal activity.** This is not legal advice.

***

### Limitations

- Google Maps may block or throttle non-residential traffic.
- Social links or booking widgets that load only after heavy client-side JavaScript may be missed.
- Booking detection is **signature-based**: custom or fully offline systems may not appear; shared scripts can occasionally over-match.
- Gym type is inferred from public text and labels — it is not an official Google category.
- Social accounts are not verified as active, official, or owned by the business.
- Emails hidden in images, PDFs, or complex apps may be missed.
- `mxValid` checks the **domain**, not that a specific mailbox is active or monitored.
- Maps does not return unlimited listings for every area; results can change over time as the Maps UI changes.

***

### Troubleshooting

| Problem | What to try |
|---|---|
| **0 results** | Enable **RESIDENTIAL** proxy; lower max results; try another city; check the run log for blocks/consent |
| Places but no Instagram | Common when the site never links socials; crawl more pages; lower min social confidence slightly |
| Places but no booking system | Stack may be fully JS-rendered, white-label, or offline — not always detectable from HTML |
| Places but no emails | Many gyms are form-only; use phone + socials; raise website page count |
| Slow or costly run | Fewer locations/terms; lower max places and pages; residential GB is usually the big cost |
| Empty after filters | Turn off “only with Instagram / booking / email” for testing |
| Odd gym type | Archetype is heuristic — use `category` and `searchTerm` as secondary fields |

***

### Support

Open an Issue on this Actor with:

1. **Run ID**
2. **Input JSON** (remove tokens and secrets)
3. What you expected vs what you got

We do not need your Apify token or proxy passwords.

# Actor input Schema

## `locations` (type: `array`):

Cities, states, or ZIP codes (e.g. Austin, TX).

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

Maps keywords (gyms, crossfit, yoga studio, pilates, martial arts…).

## `maxPlacesPerQuery` (type: `integer`):

Maximum businesses per location × term. Default is small for fast Store tests.

## `maxTotalPlaces` (type: `integer`):

Optional run-wide cap. Leave empty/0 for no global cap.

## `scanSocialGraph` (type: `boolean`):

Parse public website pages for social profile links with confidence scoring.

## `detectBookingSystems` (type: `boolean`):

Detect Mindbody, Wodify, PushPress, Glofox, Zen Planner, and other fitness booking stacks from public HTML.

## `classifyGymType` (type: `boolean`):

Label CrossFit, yoga, pilates, combat, boutique, traditional gym, etc.

## `detectAmenities` (type: `boolean`):

Flag free trial, 24/7, PT, sauna, pool, childcare, group classes, etc.

## `extractEmails` (type: `boolean`):

Collect public emails from business websites.

## `extractWebsitePhones` (type: `boolean`):

Also collect phones from website tel links and text.

## `validateMxRecords` (type: `boolean`):

Free DNS check that email domains can receive mail.

## `maxWebsitePagesPerPlace` (type: `integer`):

Pages to check (home, contact, classes, membership, booking, trial…).

## `websiteRequestDelayMs` (type: `integer`):

Polite delay between website page requests.

## `minSocialConfidence` (type: `integer`):

Drop social profiles below this confidence score.

## `defaultCountryCode` (type: `string`):

ISO country code used when parsing phone numbers.

## `includeNoWebsite` (type: `boolean`):

Keep listings even without a website (often HOT for agencies).

## `onlyWithPhone` (type: `boolean`):

Only keep leads with at least one validated phone.

## `onlyWithEmail` (type: `boolean`):

Only keep leads with at least one public email.

## `onlyWithInstagram` (type: `boolean`):

Only keep leads where Instagram was found.

## `onlyWithSocial` (type: `boolean`):

Only keep leads with Instagram, TikTok, or Facebook.

## `onlyWithBookingSystem` (type: `boolean`):

Only keep leads where a booking/CRM stack was detected.

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

Residential proxy is strongly recommended for Maps.

## `websiteProxyConfiguration` (type: `object`):

Optional separate proxy for website enrichment. Leave empty to crawl sites directly.

## `maxScrolls` (type: `integer`):

How far to scroll the Maps results feed per query.

## `debugLog` (type: `boolean`):

Verbose crawler logs for troubleshooting.

## Actor input object example

```json
{
  "locations": [
    "Austin, TX"
  ],
  "searchTerms": [
    "gyms"
  ],
  "maxPlacesPerQuery": 5,
  "scanSocialGraph": true,
  "detectBookingSystems": true,
  "classifyGymType": true,
  "detectAmenities": true,
  "extractEmails": true,
  "extractWebsitePhones": true,
  "validateMxRecords": true,
  "maxWebsitePagesPerPlace": 3,
  "websiteRequestDelayMs": 800,
  "minSocialConfidence": 60,
  "defaultCountryCode": "US",
  "includeNoWebsite": true,
  "onlyWithPhone": false,
  "onlyWithEmail": false,
  "onlyWithInstagram": false,
  "onlyWithSocial": false,
  "onlyWithBookingSystem": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "maxScrolls": 10,
  "debugLog": false
}
```

# Actor output Schema

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

Dataset of gym intelligence leads.

# 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 = {
    "locations": [
        "Austin, TX"
    ],
    "searchTerms": [
        "gyms"
    ],
    "maxPlacesPerQuery": 5,
    "maxWebsitePagesPerPlace": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("brainy_frostfield/gym-intelligence-engine").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 = {
    "locations": ["Austin, TX"],
    "searchTerms": ["gyms"],
    "maxPlacesPerQuery": 5,
    "maxWebsitePagesPerPlace": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("brainy_frostfield/gym-intelligence-engine").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 '{
  "locations": [
    "Austin, TX"
  ],
  "searchTerms": [
    "gyms"
  ],
  "maxPlacesPerQuery": 5,
  "maxWebsitePagesPerPlace": 3
}' |
apify call brainy_frostfield/gym-intelligence-engine --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,brainy_frostfield/gym-intelligence-engine"
        }
    }
}

```

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/hXmdcKTEQmYdxLOFP/builds/8i1VsaPlE5GDuF00y/openapi.json
