# Fresha.com Scraper - Salon & Spa Data Extractor (`malikgen/fresha-scraper`) Actor

Extract salon, spa & beauty business data from Fresha.com. Scrape services with prices, reviews, team members, ratings, and operating hours. Search by city or neighborhood worldwide (Dubai,   London, NYC, etc.). Perfect for market research, lead generation, price comparison, and chatbot integration.

- **URL**: https://apify.com/malikgen/fresha-scraper.md
- **Developed by:** [Malikgen](https://apify.com/malikgen) (community)
- **Categories:** E-commerce, Lead generation, Automation
- **Features:** Limited permissions
- **Stats:** 117 total users, 3 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: 4.00 out of 5 stars

## Pricing

from $7.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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?

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

## Fresha Scraper - Salon & Spa Data Extractor

Extract salon, spa, and beauty service data from [Fresha.com](https://www.fresha.com) - the world's largest booking platform for beauty and wellness services.

This Actor supports **two powerful modes** for different use cases:

### Features

- Complete service catalog — every service captured via real-browser booking-flow fetch
- Two scraping modes: venue (deep) and search (discovery)
- Up to 1000 venues per search run
- Multi-category aggregation — search all 10 Fresha categories at once
- Customer reviews with ISO 8601 dates and `reviewsSince` for incremental pipelines
- Review reply text and author (including business owner replies)
- Day-by-day operating hours
- GPS coordinates and Google Maps URL
- Team members with roles and ratings
- Packages and bundled service offers
- Three output formats: full / services-only / chatbot-optimised (WhatsApp / n8n)
- Webhook integration (n8n, Make, Zapier)
- CSV / Excel exports via dataset views (services, team, reviews)
- Resilience: graceful fallback with `partial: true` flag — never returns zero
- No proxy required

***

### What Data Can You Extract?

| Data Type | Venue Mode | Search Mode |
|-----------|:----------:|:-----------:|
| Business name & details | ✅ | ✅ |
| Services with prices | ✅ (full list) | ❌ |
| Operating hours | ✅ | ❌ |
| Team members & ratings | ✅ | ❌ |
| Customer reviews | ✅ | ❌ |
| Overall rating | ✅ | ✅ |
| Review count | ✅ | ✅ |
| Location/address | ✅ | ✅ |
| Direct booking URL | ✅ | ✅ |
| Packages & offers | ✅ | ❌ |

***

### Mode 1: Venue Scraping (Specific Business)

**Best for:** Getting complete details about specific salons you already know.

Scrape detailed information from specific Fresha venue pages including all services, prices, team members, reviews, and operating hours.

#### Example Input

```json
{
  "mode": "venue",
  "venueUrls": [
    "https://www.fresha.com/a/sofitel-spa-dubai-downtown-dubai-sofitel-dubai-downtown-sheikh-zayed-rd-downtown-dubai-4s5674wx",
    "https://www.fresha.com/a/jalal-hafed-gents-salon-dubai-building-6-al-raya-street-city-walk-dubai-z0atp2ev"
  ],
  "outputFormat": "full",
  "includeReviews": true,
  "includeTeam": true,
  "maxReviews": 10
}
```

#### Example Output (Full Format)

```json
{
  "venueName": "Sofitel Spa Dubai Downtown",
  "url": "https://www.fresha.com/a/sofitel-spa-dubai-downtown...",
  "description": "Experience luxury wellness at Sofitel Spa...",
  "phone": "+971 4 503 6666",
  "rating": 4.9,
  "reviewsCount": 1156,
  "currency": "AED",
  "priceMin": 150,
  "priceMax": 2500,
  "serviceCount": 47,
  "hours": {
    "Monday": ["10:00 AM - 10:00 PM"],
    "Tuesday": ["10:00 AM - 10:00 PM"]
  },
  "categories": [
    {
      "name": "Massage",
      "services": [
        {
          "name": "Swedish Massage",
          "price": "AED 450",
          "duration": "1 hr",
          "priceValue": 450
        },
        {
          "name": "Deep Tissue Massage",
          "price": "AED 550",
          "duration": "1 hr",
          "priceValue": 550
        }
      ]
    },
    {
      "name": "Facial Treatments",
      "services": [...]
    }
  ],
  "packages": [
    {
      "name": "Couples Retreat",
      "price": "AED 1200",
      "discount": { "description": "Save 20%", "value": 300 },
      "includes": ["Couples Massage", "Facial", "Spa Access"]
    }
  ],
  "team": [
    {
      "name": "Maria",
      "role": "Spa Therapist",
      "rating": 4.9
    }
  ],
  "reviews": [
    {
      "rating": 5,
      "comment": "Amazing spa experience, highly recommend!",
      "author": "Ahmed",
      "date": "Jan 15, 2026"
    }
  ]
}
```

#### Output Formats

| Format | Description | Best For |
|--------|-------------|----------|
| `full` | All venue data including raw fields | Data analysis, backup |
| `services_only` | Just services and prices | Price comparison |
| `chatbot_optimized` | Compact format for AI processing | WhatsApp bots, n8n chatbots |

***

### Mode 2: Search (By Location)

**Best for:** Discovering salons in a location - either by category or across all categories.

Search for salons and spas by location. Select a specific category or choose **"All Categories"** for maximum discovery.

#### Option A: Search Specific Category

```json
{
  "mode": "search",
  "searchLocation": "Dubai, UAE",
  "serviceCategory": "spa",
  "maxSearchResults": 50
}
```

**Output:**

```json
{
  "searchQuery": {
    "location": "Dubai, UAE",
    "serviceCategory": "spa",
    "totalFound": 156,
    "resultsReturned": 6
  },
  "venues": [
    {
      "name": "Sofitel Spa Dubai Downtown",
      "slug": "sofitel-spa-dubai-downtown-dubai-sofitel-dubai-downtown-sheikh-zayed-rd-downtown-dubai-4s5674wx",
      "url": "https://www.fresha.com/a/sofitel-spa-dubai-downtown...",
      "rating": 4.9,
      "reviewsCount": 1156,
      "location": "Downtown Dubai, Dubai"
    }
  ],
  "scrapedAt": "2026-01-23T08:01:20.527Z"
}
```

#### Option B: Search All Categories (Maximum Discovery)

Select **"All Categories"** in the dropdown (or leave empty) to automatically search **all 10 service categories** with **automatic deduplication**.

```json
{
  "mode": "search",
  "searchLocation": "Dubai, UAE",
  "serviceCategory": "",
  "maxSearchResults": 100
}
```

**Output:**

```json
{
  "searchQuery": {
    "location": "Dubai, UAE",
    "mode": "multi-category",
    "categoriesSearched": 10,
    "totalUniqueFound": 24,
    "resultsReturned": 24
  },
  "categoryBreakdown": {
    "spa": { "found": 6, "new": 6 },
    "hair-salon": { "found": 6, "new": 4 },
    "barbershop": { "found": 4, "new": 3 },
    "nail-salon": { "found": 5, "new": 2 },
    "beauty-salon": { "found": 6, "new": 3 },
    "massage": { "found": 4, "new": 1 },
    "skin-care": { "found": 5, "new": 2 },
    "brows-lashes": { "found": 6, "new": 2 },
    "makeup": { "found": 4, "new": 1 },
    "waxing": { "found": 5, "new": 0 }
  },
  "venues": [
    {
      "name": "Sensasia Emirates Golf Club",
      "slug": "sensasia-emirates-golf-club-dubai-...",
      "url": "https://www.fresha.com/a/sensasia-emirates-golf-club-dubai-...",
      "rating": 4.9,
      "reviewsCount": 2017,
      "discoveredInCategory": "spa"
    }
  ],
  "scrapedAt": "2026-01-23T08:30:00.000Z"
}
```

#### Search Mode Comparison

| Category Selection | Unique Venues | Time | Best For |
|--------------------|---------------|------|----------|
| Specific category | 4-10 | ~30 sec | Quick category lookup |
| All Categories | 15-40+ | ~5 min | Comprehensive discovery |

#### ⚠️ Important: Search Modes Return Featured Venues

Fresha's search page uses a **map-centric design**:

- The "X venues nearby" count refers to **map markers**, not a scrollable list
- The list view only shows **6-10 featured/promoted venues per category**
- Selecting "All Categories" maximizes discovery by searching all 10 categories

**This is a Fresha platform limitation, not a scraper limitation.**

#### Recommended Workflow for Full Data

```json
// Step 1: Discover venues with "All Categories" search
{ "mode": "search", "searchLocation": "Dubai, UAE", "serviceCategory": "" }

// Step 2: Scrape full details for discovered venues
{
  "mode": "venue",
  "venueUrls": [
    "https://www.fresha.com/a/sensasia-emirates-golf-club-dubai-...",
    "https://www.fresha.com/a/curve-beauty-salon-dubai-..."
  ]
}
```

#### Available Service Categories

- `hair-salon` - Hair salons
- `barbershop` - Barbershops
- `nail-salon` - Nail salons
- `spa` - Spas
- `beauty-salon` - Beauty salons
- `massage` - Massage therapy
- `skin-care` - Skin care
- `brows-lashes` - Brows & lashes
- `makeup` - Makeup services
- `waxing` - Waxing services

#### Supported Locations (Optimized)

The scraper includes GPS coordinates for accurate results in:

- **UAE:** Dubai, Abu Dhabi
- **Saudi Arabia:** Riyadh, Jeddah
- **Qatar:** Doha
- **Kuwait:** Kuwait City
- **Bahrain:** Manama
- **Oman:** Muscat

Other locations work but may have less accurate results depending on proxy IP.

***

### Input Parameters Reference

#### Common Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `mode` | string | `venue` | Scraping mode: `venue` (specific business) or `search` (by location) |
| `webhookUrl` | string | - | URL to POST results after scraping |
| `proxyConfiguration` | object | Auto | Proxy settings (not required for Fresha) |

#### Venue Mode Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `venueUrls` | array | - | List of Fresha venue URLs |
| `venueSlug` | string | - | Single venue slug (alternative) |
| `includeReviews` | boolean | `true` | Include customer reviews |
| `includeTeam` | boolean | `true` | Include team members |
| `maxReviews` | integer | `10` | Max reviews to include (`0` = all available) |
| `reviewsSince` | string | - | ISO 8601 date (e.g. `2026-04-14`). Only returns reviews newer than this. Ideal for incremental Mon/Wed/Fri pipelines. |
| `outputFormat` | string | `full` | `full` / `services_only` / `chatbot_optimized` |

#### Search Mode Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `searchLocation` | string | - | Location to search (required) |
| `serviceCategory` | string | `""` | Category: empty for all categories (30-60+ venues), or specific category |
| `maxSearchResults` | integer | `50` | Max venues to return (1–1000). Values above 500 take 10–20 min and use the actor's default 4 GB memory. |

#### Review Object Schema

Each review in `reviews[]` always contains all of these keys — `null` is used where Fresha doesn't supply a value, so pipelines can destructure safely:

| Field | Type | Notes |
|-------|------|-------|
| `id` | string | Fresha review ID |
| `rating` | integer 1–5 | Always present |
| `comment` | string | `null` | `null` for rating-only reviews |
| `date` | ISO 8601 UTC | e.g. `2026-04-16T22:34:00.000Z` — parseable by `new Date()` |
| `dateFormatted` | string | `null` | Human-readable, e.g. `Thu, Apr 16, 2026 at 10:34 PM` |
| `author` | string | `"Anonymous"` if redacted |
| `employeeName` | string | `null` | Staff member who delivered the service, if attributed |
| `reply` | object | `null` | `{ text, date, author }` when the salon replied |

Reviews are returned **newest-first** as provided by Fresha's API.

***

### Integration with n8n

This Actor is designed for seamless integration with n8n workflows.

#### Option 1: Using Official Apify Node (Recommended)

1. **Install the Apify node** in n8n (if not already installed)

2. **Create Apify API Token:**
   - Go to [Apify Console](https://console.apify.com/) → Settings → API & Integrations
   - Create a new API token and copy it

3. **Configure n8n Apify Node:**

   **For Venue Mode:**

   ```
   Node: Apify
   Operation: Run Actor
   Actor ID: malikgen/fresha-scraper
   Input Body:
   {
     "mode": "venue",
     "venueUrls": ["https://www.fresha.com/a/sofitel-spa-dubai-downtown-dubai-sofitel-dubai-downtown-sheikh-zayed-rd-downtown-dubai-4s5674wx"],
     "outputFormat": "chatbot_optimized",
     "includeReviews": true,
     "maxReviews": 5
   }
   ```

   **For Search Mode:**

   ```
   Node: Apify
   Operation: Run Actor
   Actor ID: malikgen/fresha-scraper
   Input Body:
   {
     "mode": "search",
     "searchLocation": "Dubai, UAE",
     "serviceCategory": "spa",
     "maxSearchResults": 20
   }
   ```

4. **Get Results:**
   - Add another Apify node with Operation: "Get Dataset Items"
   - Connect it to get the scraped data

#### Option 2: Using HTTP Request Node

If you prefer not to use the Apify node, you can use HTTP requests:

1. **Start the Actor Run:**
   ```
   Node: HTTP Request
   Method: POST
   URL: https://api.apify.com/v2/acts/malikgen~fresha-scraper/runs?token=YOUR_API_TOKEN
   Body Type: JSON
   Body:
   {
     "mode": "venue",
     "venueUrls": ["https://www.fresha.com/a/sofitel-spa-dubai-downtown-dubai-sofitel-dubai-downtown-sheikh-zayed-rd-downtown-dubai-4s5674wx"],
     "outputFormat": "chatbot_optimized"
   }
   ```

2. **Wait for Completion (add Wait node):**
   - Add a Wait node: 30-60 seconds for venue mode, 2-3 minutes for search mode

3. **Get Results:**
   ```
   Node: HTTP Request
   Method: GET
   URL: https://api.apify.com/v2/acts/malikgen~fresha-scraper/runs/last/dataset/items?token=YOUR_API_TOKEN
   ```

#### Option 3: Using Webhooks (Real-time)

Configure the Actor to POST results directly to your n8n webhook:

1. **Create n8n Webhook:**
   - Add a Webhook node in n8n
   - Copy the webhook URL

2. **Run Actor with Webhook:**
   ```json
   {
     "mode": "venue",
     "venueUrls": ["https://www.fresha.com/a/sofitel-spa-dubai-downtown-dubai-sofitel-dubai-downtown-sheikh-zayed-rd-downtown-dubai-4s5674wx"],
     "webhookUrl": "https://your-n8n-instance.com/webhook/fresha-results"
   }
   ```

3. **Webhook Payload Structure:**
   ```json
   {
     "source": "fresha-scraper",
     "timestamp": "2026-01-23T12:00:00Z",
     "data": { /* scraped venue or search data */ }
   }
   ```

#### Complete n8n Workflow Example: WhatsApp Salon Assistant

```
[WhatsApp Trigger]
    → [Check if cached data < 1 hour]
    → [If stale: Run Fresha Scraper]
    → [OpenAI: Process data and user query]
    → [Send WhatsApp response with service info]
```

**Workflow Steps:**

1. **WhatsApp Trigger:** Receives user message like "What massage services does Sofitel Spa offer?"

2. **Check Cache:** Query your database/Redis for recent data

3. **Run Scraper (if needed):**
   - Use Apify node with `chatbot_optimized` format
   - This format is compact and AI-friendly

4. **AI Processing:**
   - Send scraped data + user question to OpenAI/Claude
   - Get formatted response

5. **Send Reply:** Return service info to WhatsApp

***

### Technical Details

#### Performance

- **Venue mode:** ~15-30 seconds per venue (real-browser fetch ensures complete service catalog)
- **Search mode:** ~30-90 seconds (browser-based, handles JavaScript)

#### Proxy Recommendations

> ⚡ **GOOD NEWS: No proxy is required!** Fresha.com works perfectly without any proxy configuration.

Our testing shows:

| Proxy Type | Duration | Cost | Recommendation |
|------------|----------|------|----------------|
| **No Proxy** | ~25s | **$0.004** | ✅ **BEST** - Use this! |
| Datacenter | ~72s | $0.012 | Works but slower |
| Residential | ~119s | $0.042 | Not needed, expensive |

**Bottom line:** Leave proxy configuration empty/disabled for the best performance and lowest cost. Fresha.com does not have aggressive anti-bot measures.

#### Rate Limiting

The Actor includes built-in delays and respects Fresha's servers with reasonable request rates.

***

### Use Cases

1. **Price Comparison:** Compare service prices across multiple salons
2. **Market Research:** Analyze salon ratings and reviews in a region
3. **Chatbot Integration:** Power WhatsApp/Telegram bots with real salon data
4. **Lead Generation:** Find salons for B2B outreach
5. **Competitive Analysis:** Monitor competitor pricing and services
6. **Booking Aggregator:** Build salon discovery platforms

***

### Support & Resources

- **Issues:** Report bugs on [GitHub](https://github.com/apify/actor-issues)
- **API Documentation:** [Apify API Reference](https://docs.apify.com/api/v2)
- **n8n Integration:** [Apify n8n Docs](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.apify/)

***

### Changelog

#### v0.1.6 (Current)

- **FIXED: Incomplete service catalogs.** Fresha's SSR ships only the initial Apollo cache snapshot (typically 55–70 % of services for deep catalogs). v0.1.6 switches venue mode to Playwright-first with booking-page GraphQL interception — the `bookingFlowInitialize` response contains the full service catalog. Classic Manicure and other previously missing services are now captured.
- **NEW: `extractionPath` field.** Values: `playwright` (SSR was complete), `playwright+booking` (booking-page fetch used), `cheerio-fallback`, `jsonld-fallback`.
- **NEW: `extractedServiceCount` field.** Actual number of services extracted for easy comparison against `serviceCount` (venue's reported total).
- **NEW: `partial` field.** `false` when Playwright succeeded; `true` on fallback paths.
- **RELIABILITY: 3-level fallback chain.** Playwright → Cheerio on captured HTML → JSON-LD metadata. Never returns zero.

#### v0.1.5

- **FIXED: Search returning ~6 venues instead of requested count.** Root cause: greedy `extractTotalVenuesCount` regex matched any small number on the page and capped the scroll target. Now always uses `maxSearchResults` as the target.
- **FIXED: 120 s timeout when collecting 100+ venues.** Bumped `requestHandlerTimeoutSecs` to 1200 (20 min), set `maxRequestRetries: 0` (retries restart the page from scratch and lose all scroll progress), wrapped the scroll in try/catch with DOM salvage so partial results are always saved.
- **NEW: 1000-venue ceiling.** `maxSearchResults` raised from 200 to 1000. Internal soft time-budget (17.5 min) ensures `page.evaluate()` exits cleanly with whatever was collected before Node-side timeout fires.
- **NEW: ISO 8601 review dates.** `review.date` is now ISO 8601 UTC (`2026-04-16T22:34:00.000Z`); the human-readable string is preserved as `review.dateFormatted`.
- **NEW: `reviewsSince` input parameter.** ISO date string filters reviews to only those newer than the given date — perfect for incremental Mon/Wed/Fri pipelines.
- **PERF: Scroll cadence tuned for 1k.** `scrollDelay` 800 → 500 ms, `maxScrollAttempts` 500 → 1500, `MAX_NO_NEW_STREAK` 20 → 25.
- **MEMORY: 2–4 GB allocation.** `minMemoryMbytes` 512 → 2048, `maxMemoryMbytes` 2048 → 4096. Prevents the 95 %-pressure stalls observed at 1 GB during 100+ venue runs.
- **VERIFIED:** City of London + hair-salon @ maxResults=100 → 100 venues in 44 scrolls (~30 s, no timeout).

#### v0.1.20

- **SIMPLIFIED: Merged 3 modes into 2 modes** for cleaner UX
  - `venue` - Scrape specific business (unchanged)
  - `search` - Search by location (now includes "All Categories" option)
- **IMPROVED: Category dropdown** now clearly shows "All Categories (searches all 10, discovers 30-60+ venues)"
- **UPDATED: Venue URL placeholder** uses Dubai salon example
- **REMOVED: search-all mode** (legacy support maintained for backward compatibility)
- Categories are based on Fresha.com's official URL parameters

#### v0.1.18

- **FIXED: Search mode now collects 90+ venues** instead of only 4-6
- Implemented incremental scroll-and-collect strategy to handle DOM virtualization
- **Confirmed: No proxy required** - Fresha works perfectly without proxy (fastest & cheapest)
- Added memory limits (512MB min, 2GB max) for cost optimization

#### v0.1.17

- **NEW: Search-All Mode** - Multi-category search for maximum venue discovery
- Automatically searches all 10 service categories and deduplicates results
- Discovers 15-40+ unique venues instead of 4-10 per single search
- Added category breakdown in output showing discovery stats

#### v0.1.16

- Updated examples to use Dubai, UAE
- Improved documentation for search mode limitations
- Added two-step discovery workflow guide

#### v0.1.14

- Improved location extraction accuracy
- Better handling of Arabic text
- Enhanced error handling for search mode
- Comprehensive n8n integration documentation

#### v0.1.0

- Added search mode with PlaywrightCrawler
- Dual-mode architecture (venue + search)
- GCC region geolocation support
- Webhook integration for n8n

#### v0.0.1

- Initial release
- Venue scraping with CheerioCrawler
- Multiple output formats

# Actor input Schema

## `mode` (type: `string`):

Choose 'venue' to scrape specific salon pages with full details, or 'search' to discover salons by location. In search mode, select a category or 'All Categories' for maximum discovery (30-60+ venues).

## `venueUrls` (type: `array`):

⚠️ VENUE MODE ONLY - List of Fresha venue URLs to scrape. Leave empty/ignore when using search mode.

## `venueSlug` (type: `string`):

⚠️ VENUE MODE ONLY - Single venue slug as alternative to full URL. Leave empty when using search mode.

## `searchLocation` (type: `string`):

🔍 SEARCH MODE ONLY - City or area to search (e.g., 'Dubai, UAE', 'Riyadh, Saudi Arabia'). GCC cities have optimized coordinates.

## `serviceCategory` (type: `string`):

🔍 SEARCH MODE ONLY - Select a specific category or 'All Categories' to search all 10 categories and maximize venue discovery with automatic deduplication.

## `maxSearchResults` (type: `integer`):

🔍 SEARCH MODE ONLY - Maximum venues to return (uses infinite scroll to load more). Values above 500 may take 10–20 minutes and require the actor's default 4 GB memory.

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

Whether to include customer reviews in the output (venue mode only).

## `includeTeam` (type: `boolean`):

Whether to include team/staff members in the output (venue mode only).

## `maxReviews` (type: `integer`):

Maximum number of reviews to include (0 = all available). Venue mode only.

## `reviewsSince` (type: `string`):

Only include reviews published after this date (ISO 8601 format, e.g. '2026-04-01'). Ideal for incremental scraping pipelines — set to your last run date to fetch only new reviews. Venue mode only.

## `outputFormat` (type: `string`):

Output format for venue scraping. Search mode always uses a compact listing format.

## `webhookUrl` (type: `string`):

Optional n8n webhook URL to POST results after scraping. Works with both modes.

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

⚡ PROXY NOT REQUIRED - Fresha.com works perfectly without proxy. Tests show: No Proxy ($0.004) vs Datacenter ($0.012) vs Residential ($0.042). Only enable if you experience blocks.

## Actor input object example

```json
{
  "mode": "venue",
  "venueUrls": [
    "https://www.fresha.com/a/sofitel-spa-dubai-downtown-dubai-sofitel-dubai-downtown-sheikh-zayed-rd-downtown-dubai-4s5674wx"
  ],
  "searchLocation": "Dubai, UAE",
  "serviceCategory": "",
  "maxSearchResults": 50,
  "includeReviews": true,
  "includeTeam": true,
  "maxReviews": 10,
  "outputFormat": "full"
}
```

# Actor output Schema

## `overview` (type: `string`):

Overview of scraped venue data with services and prices

## `services` (type: `string`):

Detailed view of all services with prices

## `chatbot` (type: `string`):

Compact format optimized for chatbot integration

# 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 = {
    "venueUrls": [
        "https://www.fresha.com/a/sofitel-spa-dubai-downtown-dubai-sofitel-dubai-downtown-sheikh-zayed-rd-downtown-dubai-4s5674wx"
    ],
    "searchLocation": "Dubai, UAE"
};

// Run the Actor and wait for it to finish
const run = await client.actor("malikgen/fresha-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 = {
    "venueUrls": ["https://www.fresha.com/a/sofitel-spa-dubai-downtown-dubai-sofitel-dubai-downtown-sheikh-zayed-rd-downtown-dubai-4s5674wx"],
    "searchLocation": "Dubai, UAE",
}

# Run the Actor and wait for it to finish
run = client.actor("malikgen/fresha-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 '{
  "venueUrls": [
    "https://www.fresha.com/a/sofitel-spa-dubai-downtown-dubai-sofitel-dubai-downtown-sheikh-zayed-rd-downtown-dubai-4s5674wx"
  ],
  "searchLocation": "Dubai, UAE"
}' |
apify call malikgen/fresha-scraper --silent --output-dataset

```

## MCP server setup

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