Fresha Scraper icon

Fresha Scraper - Salons, Spas, Services & Reviews

Scrape Fresha salon and spa listings: business profiles, service menus with prices and durations, opening hours, team members, photos, ratings and client reviews. Search by keyword and location or paste venue and professional links. Resume, incremental updates and MCP export included.

Start using this actor on Apify ↗Need a custom scraper?Contact us ↗

Fresha Scraper at a glance

Fresha Scraper is a ready-to-run Apify actor from abotapi for collecting web data. Its output documents 61 fields, including recordtype, id, name, url and venuetype, which you can export as JSON, CSV or Excel or read through the Apify API. It costs $1.80 per 1,000 results on the Apify Free plan and from $1.00 on paid plans, with smaller per-run or optional feature charges listed on Apify.

Runs on
Apify cloud: console, API, schedules and integrations
Data type
Web data
Pricing
$1.80 per 1,000 results (Free plan), from $1.00 on paid plans
Output
61 documented fields · JSON, CSV, Excel
Inputs
28 options

What Fresha Scraper can do

  • Two ways in. Search Fresha by keyword and location (hair in Sydney, massage in London, barber in New York), or paste venue, professional, SEO landing-page and book-now links for exact scraping. No URL building needed.
  • Deep service menus. Full service catalog with per-service prices, durations, variants and per-service ratings, plus package offers with included items.
  • Reviews with replies. Client reviews carry rating, text, date, author, review photos, the service and team member involved, and the venue reply - with the full 1-5 star distribution, Fresha's own review summary, and the most-reviewed services and team members per venue.
  • Lead-gen ready. Amenities, social links, website, phone, geo coordinates, servicing areas, open/closed status and a derived 0-100 lead score per listing.
  • Built for schedules. Incremental mode returns only new and changed listings on recurring runs, and a refused run fails loudly instead of returning an empty dataset.

Choose what to collect

These inputs let you configure Fresha Scraper - Salons, Spas, Services & Reviews. Open the actor on Apify to enter your values and review the current options.

Supported input fields
InputWhat it controls
modestring · requiredSEARCH scrapes Fresha listings for a keyword and location. LISTING_URLS scrapes the exact venue pages (fresha.com/a/...) and professional profiles (fresha.com/p/...) you paste.

Choices: SEARCH, LISTING_URLS

searchQuerystringService or business keyword, e.g. hair, massage, nails, barber, facial, tattoo. Used in SEARCH mode.
searchLocationstringCity or area name, e.g. Sydney, London, New York. Resolved automatically to map coordinates. Leave blank when latitude/longitude or a venue URL list is provided.
latitudestringOptional map latitude. When set together with longitude it overrides the resolved Location.
longitudestringOptional map longitude. When set together with latitude it overrides the resolved Location.
maxPagesintegerHow many result pages (20 listings each) to walk per search. Leave blank or 0 for unlimited until Max items is reached.
sortstringOrdering of search results. RATING and DISTANCE are narrowed assertions: results come back in that order.

Choices: RECOMMENDED, RATING, DISTANCE

Show 21 more inputs
More input fields
InputWhat it controls
minPriceintegerOptional minimum service price filter in the local currency of the search area.
maxPriceintegerOptional maximum service price filter in the local currency of the search area.
hasDealsbooleanReturn only venues currently running deals or offers.
hasGroupAppointmentsbooleanReturn only venues offering group appointments or classes.
freshaVerifiedOnlybooleanReturn only venues carrying the Fresha Verified badge.
availabilityDatestringOnly venues with bookable availability on this date (YYYY-MM-DD). Used in SEARCH mode.
listingUrlsarrayFresha URLs to scrape in LISTING_URLS mode. Supported shapes, which can be mixed freely: venue pages (fresha.com/a/...), professional profiles (fresha.com/p/...), SEO landing pages (fresha.com/lp/..., harvested for the venue links they contain), localized venue links in the short locale form (e.g. fresha.com/de/a/...), and venue links carrying tracking parameters (?utm_source=..., fbclid=..., matched the same as clean venue links). Book-now links (fresha.com/book-now/...) also resolve to their venue when encountered. The URL mode is selected by Mode above.
fetchDetailsbooleanFetch each listing's full profile: description, contact number, opening hours, service menu with prices and durations, packages, team members, photo gallery, Instagram, amenities and review highlights. Adds the detail-enrichment charge per listing. Without it you still get the listing card: name, rating, review count, badges, address, geo and photos.
fetchReviewsbooleanAttach client reviews to each listing: rating, text, date, author, salon reply and review photos, plus the 1-5 star distribution. Adds the review-enrichment charge per listing. First page is included; deeper pages are walked automatically.
maxReviewsPerListingintegerStop collecting reviews for a listing after this many. 0 means no limit (walk every available page).
reviewSortingstringOrder in which reviews are collected.

Choices: LATEST, BEST, WORST, RELEVANCE

maxItemsintegerStop after this many listing records (reviews attached to a record do not count as items). Run stops gracefully at the cap.
resumeFromRunIdstringID of an interrupted run to continue. The run picks up after the last listing already saved and reuses its key-value state. Leave empty for a fresh run.
incrementalModebooleanCompare listings against the previous run for the same scope (state key) and only emit NEW or UPDATED rows (plus optional EXPIRED tombstones). Unchanged listings are skipped and not charged. A listing previously marked EXPIRED that is found again is emitted as REAPPEARED with its original firstSeenAt. What drives UPDATED: every emitted listing field except the exclusions below and run bookkeeping (scrapedAt, changeType, changedFields, firstSeenAt, lastSeenAt) - e.g. the services menu (names, prices, durations), rating, reviewsCount, address and coordinates, images, amenities, social links. Never compared, so they never mark a row UPDATED on their own (they rotate or change on their own without the listing changing): portfolioImages, recentReviewers, openingStatus, openingStatusDetails, closed, workingHours, instagramMediaCount, groupingScore, topReviewedServices, reviewTeamMembers. Review order is ignored too: reviews are compared as an orderless set of id, rating, text, date and reply. Extend the exclusions with ignoreFieldsForChanges.
stateKeystringName of the remembered baseline for incremental mode. Defaults to a hash of the current scope (mode, query, location, URL set), so two runs with the same settings compare against each other automatically. Change it to track a different baseline.
emitUnchangedbooleanIn incremental mode, also emit rows classified UNCHANGED (handy for full snapshots or debugging). Unchanged rows still carry changeType so you can filter.
emitExpiredbooleanIn incremental mode, emit an EXPIRED row for listings present in the baseline but missing from this run. Tombstones respect Max items.
ignoreFieldsForChangesarrayExtra dataset fields that must NOT mark a record UPDATED when they change (rotation noise like image CDNs). Sensible defaults are built in; anything added here is appended.
mcpConnectorsarrayOptionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify → Settings → API & Integrations, then select it here. Notion gets a rich page-per-item export; other connectors get a best-effort write/digest. Leave empty to skip; never changes the dataset output. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).
notionParentPageUrlstringURL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.
maxNotifyListingsintegerCap on items written to each connector per run. Does not affect the dataset.

Fields in the output

The documented dataset includes the fields below. Availability can depend on the source page and selected mode.

recordTyperecordType
idid
namename
urlurl
venueTypevenueType
ratingrating
reviewsCountreviewsCount
citycity
countrycountry
amenitiesamenities
serviceCountserviceCount
priceRangepriceRange
Show 49 more fields
featuredfeatured
isNewisNew
hasDealshasDeals
isFreshaVerifiedisFreshaVerified
searchQuerysearchQuery
searchLocationsearchLocation
changeTypechangeType
scrapedAtscrapedAt
descriptiondescription
contactNumbercontactNumber
currencycurrency
serviceCategoriesserviceCategories
servicesservices
packagespackages
hasPackageshasPackages
servicePriceMinservicePriceMin
servicePriceMaxservicePriceMax
durationMindurationMin
durationMaxdurationMax
teamSizeteamSize
teamteam
workingHoursworkingHours
openingStatusopeningStatus
fullAddressfullAddress
latitudelatitude
longitudelongitude
imagesimages
portfolioImagesportfolioImages
instagramUsernameinstagramUsername
hasGiftCardshasGiftCards
hasVouchershasVouchers
hasMembershipshasMemberships
hasFreshaPayhasFreshaPay
hasProductStorehasProductStore
websitewebsite
facebookUrlfacebookUrl
reviewRating1TotalreviewRating1Total
reviewRating2TotalreviewRating2Total
reviewRating3TotalreviewRating3Total
reviewRating4TotalreviewRating4Total
reviewRating5TotalreviewRating5Total
reviewSummaryTextreviewSummaryText
recentReviewersrecentReviewers
topReviewedServicestopReviewedServices
reviewTeamMembersreviewTeamMembers
detailFetcheddetailFetched
changedFieldschangedFields
firstSeenAtfirstSeenAt
lastSeenAtlastSeenAt

Example output

An example from this actor’s documentation. Values are illustrative; this is not a fresh live result.

{
  "recordType": "venue",
  "id": "235399",
  "name": "Sample Hair Studio",
  "url": "https://www.fresha.com/a/sample-hair-studio-sydney-example123",
  "venueType": "Hair Salon",
  "rating": 5,
  "reviewsCount": 625,
  "ratingLevel": "HIGHLY_RECOMMENDED",
  "reviewRating5Total": 619,
  "city": "Sydney",
  "state": "New South Wales",
  "country": "AU",
  "postalCode": "2011",
  "latitude": -33.8688,
  "longitude": 151.2093,
  "contactNumber": "+61 400 000 000",
  "currency": "AUD",
  "serviceCount": 55,
  "servicePriceMin": 15,
  "servicePriceMax": 455,
  "priceRange": "AUD 15 - 455",
  "workingHours": [
    {
      "day": "Monday",
      "closed": false,
      "hours": [
        "9:00 AM - 6:00 PM"
      ]
    }
  ],
  "amenities": [
    "Pet-friendly",
    "Wi-Fi"
  ],
  "team": [
    {
      "name": "Rachel",
      "jobTitle": "Director",
      "rating": 5
    }
  ],
  "services": [
    {
      "name": "Cutting Packages",
      "price": 65,
      "currency": "AUD",
      "durationMin": 1800
    }
  ],
  "reviews": [
    {
      "rating": 5,
      "text": "Always great",
      "authorName": "Kate M",
      "replyText": "Thank you!"
    }
  ],
  "leadScore": 87.5,
  "searchQuery": "hair",
  "searchLocation": "Sydney",
  "changeType": "NEW"
}

Ways to use this data

  • Salon and spa lead generation: collect venues by city and service with phone numbers, addresses and contact details for outreach.
  • Market research and franchising: map competitor density, pricing ranges, opening hours and service breadth across cities.
  • Review intelligence: track ratings, star distributions, review trends and how venues reply to feedback.
  • Price benchmarking: compare service prices and durations across venues and markets.
  • AI agents and dashboards: feed structured listing and review data into your own tools.

Before you run

Start with a small input and check the resulting records against your expected fields. Source content and actor options can change; the current Apify listing is the reference for availability and pricing.

Questions about this actor

What data does Fresha Scraper return?

Fresha Scraper returns 61 documented fields, including recordtype, id, name, url, venuetype, rating, reviewscount and city. Availability of each field depends on the source page and the selected mode.

How much does Fresha Scraper cost?

It costs $1.80 per 1,000 results on the Apify Free plan and from $1.00 on paid plans, with smaller per-run or optional feature charges listed on Apify. The Apify listing shows the current rate for every plan.

Can I get only new or changed listings on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new and updated listings, and unchanged ones are not billed.

Why did a run return fewer listings than the search shows on the website?

The run stops at Max items, strongest matches first. Set it higher, or to 0, to collect more of the city. Reviews attached to a listing do not count toward maxItems.

Why did my run fail instead of returning an empty dataset?

If not a single page could be read during the run - every connection was refused or the data source did not answer - the run fails with a message describing the connection problem, so "no results" is never confused with "nothing could be read". On a free plan this can mean residential connections were unavailable; the failure message says which case applies and what to do. Run it again in a few minutes. If at least some pages were read, you get what was found: some listings, or - if the pages were read but none matched - an honest empty result.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

Ready to collect with Fresha Scraper?

Run it on Apify with your own input and export the results as JSON, CSV or Excel.