# Treatwell Scraper: UK Salons, Service Prices & Reviews (`softprodlabs/treatwell-scraper`) Actor

Find UK Treatwell salons by city or search URL. Extract full service menus with price and duration options, phone numbers, ratings and opening hours. Collect paginated reviews filtered by date and rating. Export JSON/CSV with source links; no login.

- **URL**: https://apify.com/softprodlabs/treatwell-scraper.md
- **Developed by:** [Software Production Labs](https://apify.com/softprodlabs) (community)
- **Categories:** Lead generation, E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.28 / 1,000 salon or reviews

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

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

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

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

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

# README

## Treatwell Scraper: UK Salons, Service Prices & Reviews

Turn public Treatwell UK listings into salon research data. Discover salons by city and treatment category, extract full menus with individual price and duration options, or collect customer reviews across multiple pages. No Treatwell login or API key is required.

### Start with five salons

```json
{"city":"London","treatmentGroup":"hair","maxItems":5}
```

For a specific neighbourhood or treatment, paste its Treatwell search URL into `urls`. You can also supply individual salon URLs. Use either URLs or city/category inputs; mixing them returns a helpful validation error.

```json
{"urls":["https://www.treatwell.co.uk/place/catori-beauty-within-mario-s-hair-beauty/"],"maxItems":1}
```

### Collect and filter reviews

```json
{
  "mode":"reviews",
  "urls":["https://www.treatwell.co.uk/place/catori-beauty-within-mario-s-hair-beauty/"],
  "maxItems":20,
  "maxPages":10,
  "reviewDateFrom":"2026-01-01"
}
```

Each review is its own row. Add `maxReviewRating: 2` to analyse low-rated experiences. Dates refer to review publication in UTC, not the appointment date. `maxReviewsPerVenue` prevents one salon from consuming the whole output allowance. Reviews mode also accepts city or search inputs to discover salons first. A `/reviews/page-2/` URL starts from that review page.

### What you receive

**Salon rows:** stable venue ID, name, source URL, address, postcode, coordinates, public phone when present, rating and rating count, opening hours, published date, public staff details, images, awards, and a deduplicated service menu. Each service includes categories, published price ranges, full-price ranges, discount types, duration ranges and individual options with employee names. Prices are numeric GBP amounts, not pennies. A zero-price patch test remains zero; missing prices remain null.

**Review rows:** review ID, venue ID/name/source, exact review-page URL, text, star rating, publication and visit dates, verification flag, public display name when not anonymous, treatment names and employee description. Review text is returned as published, without invented sentiment or claims.

`ratingCount` counts the salon's published ratings. It can exceed the number of written reviews; `SUMMARY.coverage.reportedTextReviews` records the separate written-review total. Services inside salon rows are nested arrays; JSON preserves all options. CSV/Excel exports are available through Apify.

### Controls and coverage

- `maxItems`: global maximum unique salon or review rows (default 20).
- `maxPages`: pages per search and per salon's review list (default 5).
- `maxRequests`: global page request cap (default 100), excluding robots checks and retries.
- `fetchDetails: false`: faster listing-only salon extraction. Full menus are null in this mode. Direct salon URLs and reviews always fetch the salon page.
- `minRating`: filters salons; `keyword` matches salon names, descriptions and fetched service names.

The Actor follows public next-page links and deduplicates venues/reviews. `SUMMARY` records each listing's coverage, page counts, stop reason and budget limits. `ERRORS` records individual failures. A failed URL can coexist with successful results; if all requested extraction fails, the run fails rather than silently returning an empty success. Valid filters producing zero matches are successful, and page caps still apply.

Treatwell currently exposes 20 venues or 5 written reviews per page. Requests respect its public crawl delay (currently five seconds), so review history and detailed city crawls take longer than listing-only runs. Set a suitable run timeout for large requests.

### Practical uses

- Agencies: research UK salons by area, services and rating before relevant outreach.
- Salon operators: compare treatment duration, full prices and advertised discounts.
- Customer research teams: collect recent or low-rated reviews with source URLs.
- AI agents: discover salons, compare extracted menus or summarise returned reviews using cited source pages.

Example agent request: “Use softprodlabs/treatwell-scraper to find five Manchester hair salons with ratings of at least 4.5. Return their source links, service prices and phone numbers where available.”

### Limits

UK `treatwell.co.uk` only. No appointment booking, checkout, customer accounts or live slot availability. Published price ranges may depend on staff, off-peak discounts or service options; they are not guaranteed prices for a specific appointment. No external website crawling or inferred emails. Missing source fields remain null. Search listings reflect Treatwell's public ordering and may change between page requests; this is not a guaranteed exhaustive census. A page-format change, network failure or blocked request is reported explicitly.

### Pricing

**$1.50 per 1,000 saved results** on the Free plan, whether salon rows or review rows. Service options nested within a salon row incur no additional result charge. The start charge is **$0.00025 per allocated GB, minimum one unit**, including empty or failed runs.

| Apify plan | Per 1,000 results |
| --- | ---: |
| Free | $1.50 |
| Bronze | $1.425 |
| Silver | $1.35 |
| Gold, Platinum, Diamond | $1.275 |

Apify platform costs are included in these event charges. Set maximum run cost to bound spending; the Actor stops when it cannot charge another result. Filtered, duplicate and failed records incur no result charge. The Pricing tab shows the current rates.

Built by [Software Production Labs](https://softwareproductionlabs.com). Independent tool; not affiliated with or endorsed by Treatwell. For support, include the run URL and expected result. Never share account passwords or private customer data in issues.

# Actor input Schema

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

Venues returns one row per salon with nested service options. Reviews returns one row per public review; venue URLs or discovery inputs work in either mode.

## `city` (type: `string`):

For example London, Manchester, Bristol or Edinburgh. Supply city/category OR URLs. For smaller areas and individual treatments, copy a Treatwell search URL.

## `treatmentGroup` (type: `string`):

Optional category for city discovery. Omit to search all treatments.

## `urls` (type: `array`):

Public /place/salon/, /places/... search URLs, or /place/salon/reviews/ URLs in reviews mode. Review page URLs resume from that page. Tracking query parameters are removed.

## `maxItems` (type: `integer`):

Global cap on unique output rows across every input. In reviews mode this counts reviews, not salons.

## `fetchDetails` (type: `boolean`):

For venue discovery, fetch each salon page for its full menu, options, phone and staff. Disable for listing-only rows (services and phone can be absent). Direct venue URLs and reviews always fetch the venue page.

## `minRating` (type: `number`):

Filter salons by their published average rating. Also filters which salons contribute reviews.

## `keyword` (type: `string`):

Case-insensitive phrase in salon name, description or extracted service names. This is a local filter, not a global site search. Service matching requires full details.

## `reviewDateFrom` (type: `string`):

Reviews mode only. Inclusive YYYY-MM-DD, based on review publication date in UTC.

## `reviewDateTo` (type: `string`):

Reviews mode only. Inclusive YYYY-MM-DD, based on review publication date in UTC.

## `maxReviewRating` (type: `integer`):

Reviews mode only. E.g. 2 returns one- and two-star reviews for complaint analysis.

## `maxReviewsPerVenue` (type: `integer`):

Reviews mode: cap matching reviews saved per salon; maxItems still applies globally.

## `maxPages` (type: `integer`):

Per search input and per salon review listing. Treatwell currently serves 20 venues or 5 reviews per page. Date filters may need a larger page cap.

## `maxRequests` (type: `integer`):

Global page request budget; robots.txt and transient retries are additional. SUMMARY reports limits and incomplete coverage. Public crawl delay is respected.

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

Direct access is the default. Optional proxy costs are borne by the developer under pay-per-event pricing. Proxies do not enable private data.

## Actor input object example

```json
{
  "mode": "venues",
  "urls": [
    "https://www.treatwell.co.uk/places/treatment-group-hair/offer-type-local/in-london-uk/"
  ],
  "maxItems": 20,
  "fetchDetails": true,
  "maxReviewsPerVenue": 100,
  "maxPages": 5,
  "maxRequests": 100,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

## `summary` (type: `string`):

No description

## `errors` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        "https://www.treatwell.co.uk/places/treatment-group-hair/offer-type-local/in-london-uk/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("softprodlabs/treatwell-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 = { "urls": ["https://www.treatwell.co.uk/places/treatment-group-hair/offer-type-local/in-london-uk/"] }

# Run the Actor and wait for it to finish
run = client.actor("softprodlabs/treatwell-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 '{
  "urls": [
    "https://www.treatwell.co.uk/places/treatment-group-hair/offer-type-local/in-london-uk/"
  ]
}' |
apify call softprodlabs/treatwell-scraper --silent --output-dataset

```

## MCP server setup

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