StarOfService Scraper | Pros | Coverage | Leads
Pricing
from $4.90 / 1,000 results
StarOfService Scraper | Pros | Coverage | Leads
Scrape StarOfService professional profiles, coverage areas and catalog data for service business lead generation and home services market research. Covers ~1,010 trades across France with contact details in structured rows.
Pricing
from $4.90 / 1,000 results
Rating
0.0
(0)
Developer
Ahmed Jasarevic
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
7 days ago
Last modified
Categories
Share
StarOfService Scraper — French Service-Pro Leads And Trade × City Coverage Counts
Extract pro profiles from starofservice.com, the French professional-services directory — ~1,010 trades (plumbers, electricians, roofers…) with ratings, review counts and locations — for service business lead generation, plus one coverage row per trade × city combination so you can size a local market before scraping it. Runs as plain HTTP against the site's own internal JSON:API (CheerioCrawler, no browser, ~256 MB RAM), because StarOfService's CloudFront WAF returns HTTP 403 to datacenter IPs.
Main Use Cases: Service Business Lead Generation, Contractor Leads And Local Market Analysis
- Service business lead generation for French trades — pro rows (name, trade, city, ZIP, rating, review count) as contractor leads, plumber leads or cleaning business leads (
nettoyage), any French city. - Home services market research — trade × city coverage counts (
proCount,proCountCapped) size a local market before you spend budget. - Find plumbers in Paris — and every other trade, city by city — start from the ~1,010-trade catalog and city resolver, then enumerate profiles per pair.
- Business directory data scraping — profile, coverage and catalog rows in one dataset, three views (Pros, Trade × city coverage, Catalog).
- Local service leads on a schedule — weekly runs refresh a lead list and catch new pros, ratings and premium profiles.
How The StarOfService Scraper Works
StarOfService is a Next.js site behind a CloudFront WAF returning HTTP 403 to datacenter IPs — including Apify's proxy ranges — so a headless browser fails too. The Actor skips the website and talks to the internal "zeus" JSON:API its own pages call: host and token come from the server-rendered __NEXT_DATA__ blob, then paginated JSON flows through Crawlee (CheerioCrawler, no DOM parsing, ~256 MB). Modes: profiles, coverage, trades, cities, profilesByUrl. Rows are pushed in batches of 50 with pushed N row(s) … combination d/t logs. Coverage is France-only (Accept-Country: fr).
Input Parameters For Modes, Trades, Cities And Run Caps
Modes: profiles (default) — pros per trade × city pair, each pair fetched three times (default, sort=nb_reviews, sort=-nb_reviews) for ~23 unique pros, plus one coverage row. coverage — counts only, 1 request per pair. trades — full catalog; run first for valid slugs. cities — names → UUIDs, slugs, postcodes, coordinates. profilesByUrl — profiles from startUrls.
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
mode | string (select) | No | profiles | profiles, coverage, trades, cities, profilesByUrl. |
startUrls | array | No | (empty) | profilesByUrl mode; /inv/professionnel/… and /professionnel/… accepted. |
trades | array of string | No | (empty) | Slugs like plomberie, electricite. Empty → defaultTrades. |
cities | array of string | No | ["Paris"] | Names or slugs (Paris, Aix-en-Provence), resolved via /cities. |
defaultTrades | array of string | No | 10 common trades | Fallback when trades is empty — 10 slugs from the /services catalog. |
maxPairs | integer | No | 0 | Backstop on trade × city pairs; 0 = auto (enough to reach maxProfiles). |
maxProfiles | integer | No | 500 | Target profile rows; sort variants continue until reached. Free accounts: 10. |
maxTrades | integer | No | 1010 | Max trade catalog rows (trades mode). |
maxCities | integer | No | 200 | Max city rows per searched name (cities mode). |
includeDetails | boolean | No | false | Extra request per pro: bio, registration date, gallery. |
apiToken | string | No | (empty) | Override zeus token; empty = built-in, auto-refreshed from the SSR blob. |
country | string | No | fr | Accept-Country header (fr = French marketplace). |
maxRequestsPerCrawl | integer | No | 1000 | Hard cap on HTTP requests. |
maxConcurrency | integer | No | 8 | Parallel requests (1–10). |
proxy | object | No | { "useApifyProxy": false } | Apify Proxy picker, off by default; applies to every Crawlee call if on. |
Output Fields: Pros, Coverage And Catalog Views
Every row carries type — profile, coverage, trade or city — selecting its shape. Fields are strings unless annotated; unavailable values are null. Output tabs: Pros, Trade × city coverage, Catalog.
profile rows (Pros view)
| Field | Description |
|---|---|
proUuid / name | Profile UUID (zeus /pro_profiles id); pro or company name. |
url / landingPageUrl | Public profile URL; trade × city landing page. |
tradeUuid / tradeSlug / tradeName | Trade UUID, slug (e.g. plomberie) and display name. |
cityUuid / citySlug / city / cityId (integer) | City UUID (zeus API), slug, name; legacy numeric city id from profile URLs. |
zipCode / department | Postcode and department name. |
latitude / longitude (number) | Address coordinates (city rows: city centre). |
rating (number) / reviewCount (integer) | Average rating 0–5; published review count. |
description / presentation / workDescription | Profile, presentation and work description texts. |
bio / phone | Bio (only with includeDetails); phone usually null (hidden until quote request). |
startingYear / employees / premium | Year founded, employee count (int), paid premium flag. |
createdAt / registeredAt | Creation and registration timestamps (ISO 8601); registeredAt only with includeDetails. |
photo / logo / hasAvatar (boolean) | Primary photo and logo URLs; custom-avatar flag. |
photos / services (array) | All photo URLs; service names — often empty (API returns ids). |
coverage rows (Trade × city coverage view)
| Field | Description |
|---|---|
tradeSlug / tradeName / cityName | Trade and city counted. |
proCount (integer) / proCountCapped (boolean) | Pros for the pair — a lower bound (max 10 per pair); true = full 10-profile page, at least 10. |
listingUrl | Public /dir/<region>/<department>/<city>/<trade> page. |
trade rows (Catalog view)
| Field | Description |
|---|---|
tradeUuid / tradeSlug / tradeName | Trade UUID, slug and display name. |
availableOnLandings (boolean) | Bookable via request-a-quote landing pages. |
city rows (Catalog view)
| Field | Description |
|---|---|
cityUuid / citySlug / cityName / zipCode | City UUID, slug, name and postcode. |
fullCityName / fullName | Site labels, e.g. 75008 — Paris, 69001 — Lyon. |
latitude / longitude (number) | City-centre coordinates (population is not exposed). |
Example Input: Build A Plumber Lead List For Paris
Run {"mode": "trades"} first for valid trade slugs, then:
{"mode": "profiles","trades": ["plomberie", "electricite", "menuiserie"],"cities": ["Paris", "Lyon", "Marseille"],"maxProfiles": 200,"includeDetails": true}
Example Output: Profile And Coverage Rows
An abbreviated profile row (real field names; unavailable fields return null — phone usually is):
{"type": "profile","proUuid": "562163b3-e344-b858-d4c7-a87c86a53a3e","name": "Duchateau & fils","url": "https://www.starofservice.com/professionnel/plomberie/paris/173009619/duchateau-fils","tradeSlug": "plomberie","tradeName": "plomberie","city": "Paris","zipCode": "75008","latitude": 48.8739,"longitude": 2.3126,"rating": 5,"reviewCount": 10,"phone": null,"premium": false,"services": ["Dépannage plomberie"]}
The matching coverage row (trades/cities modes emit the trade and city catalog rows above):
{"type": "coverage","tradeSlug": "plomberie","tradeName": "plomberie","cityName": "Paris","proCount": 10,"proCountCapped": true,"listingUrl": "https://www.starofservice.com/dir/ile-de-france/paris/paris/plomberie"}
Scrape StarOfService Profiles: Batched Writes And Three Sort Variants
- Batched writes — 50 rows per push, with
pushed N row(s) … combination d/tlogs keeping runs traceable. - Three sort variants per pair — each
pro_profilesrequest caps at 10 pros with no pagination, so pairs are requested in default,sort=nb_reviewsandsort=-nb_reviewsorder — ~23 unique pros per pair. - Two products in one run — profile lead rows and one coverage row per pair.
- Bounded —
maxRequestsPerCrawl(1000),maxConcurrency(1–10),maxProfiles/maxPairs; free accounts: 10 profiles.
StarOfService API Access — No Public API Required
www.starofservice.com sits behind a CloudFront WAF returning HTTP 403 to datacenter IPs (Apify proxy ranges included) — a headless browser fails the same way — and there is no public StarOfService developer API: API Evangelist and apis.io both maintain a StarOfService profile stating so. The Actor reads the API coordinates from the site's own pages:
- Next.js pages embed a
__NEXT_DATA__blob whosepageProps.apiDataholds the host and token:{ "pageProps": { "apiData": { "zeusHost": "https://zeus.starofservice.com", "token": "…" } } } - The site's JS bundles reference that API as
SOS-NOID.
A JSON:API service on https://zeus.starofservice.com requiring these headers:
| Header | Value |
|---|---|
Authorization | SOS-NOID <token> |
X-App-Identifier | SOS.WebInternal/1.0 |
Accept-Country | fr |
Accept / Content-Type | application/vnd.api+json |
| Endpoint | Purpose |
|---|---|
GET /services?filter[available_on_landings]=true | Trade catalog (~1,010 trades, 100/page) |
GET /cities?filter[name]=…&sort=-population | City lookup + region/department relations |
GET /regions/{id}, GET /departments/{id} | Slugs for public /dir/… URLs |
GET /pro_profiles?filter[service.id]=…&filter[city.id]=… | Profiles for a trade + city (10/page max) |
GET /pro_profiles/{uuid} | Single profile (bio, registration date, gallery) |
Token handling. The built-in token comes from the site's data blob; when StarOfService rotates it, the Actor re-reads a fresh one or logs a clear error. Paste your own into apiToken anytime.
Size The Local Market First: Trade × City Coverage Counts
coverage mode answers "how many pros serve this trade in this city?" with 1 request per pair — no profile rows. Rows carry proCount, proCountCapped and the public listingUrl. Two rules: proCount is a lower bound (no exact totals exist), and proCountCapped: true means 10+, not 10. Compare coverage across cities for a go/no-go read before spending a profiles run or ad budget — local coverage data, not a market-size figure.
Directory Scraping The French Services Marketplace: ~1,010 Trades And Artisans In France
tradesmode — ~1,010 real slugs from/services(100/page) withtradeUuid,tradeSlug,tradeName,availableOnLandings. Run first; feed slugs back intotrades.citiesmode — plain names (Paris,Aix-en-Provence) → UUIDs, slugs, postcodes, coordinates; up tomaxCities(200) rows per name.populationisn't exposed — coordinates come instead.profilesByUrlmode — paste profile URLs intostartUrls(both variants).- France-only by design —
Accept-Country: fr: plumbers in Paris, electricians in Lyon, cleaners in Bordeaux, enumerated the same way for every trade.
Service Marketplace Data: Ratings, Reviews And The Phone-Number Limitation
Beyond rating, reviewCount, location and company facts (full tables above), bio and registeredAt arrive with includeDetails. Limitations:
- Phone numbers are usually
null— StarOfService hides contact details until a quote request, so the API returnsphone_number: nullfor most profiles. That's the site's behaviour, not a scraping failure: plan lead capture around profile URLs, not cold lists. - Max 10 pros per request, no reliable pagination or totals; the three sort variants (~23 per pair) mitigate this, and
proCountstays a lower bound. - Review text is not extracted — only
ratingandreviewCount; text is gated behind the profile page. - City
populationis not exposed; coordinates are returned instead. - The internal API is unofficial and could change without notice.
Run starofservice-scraper From The Apify API, Console Or Schedule
- Apify Console — set inputs, press Run; rows appear under the three views, with
pushed N row(s)in the log tab. - Apify API — start actor
LKqjH7YCD1On7Rs0TviaPOST https://api.apify.com/v2/acts/LKqjH7YCD1On7Rs0T/runs(orrun-sync-get-dataset-items), then readGET https://api.apify.com/v2/datasets/<datasetId>/dataset/items. - Schedule — save the input as a task and schedule it (cron, UTC).
Integrations & Automation
Native Apify integrations only. Apify API: start runs, fetch dataset items. Webhooks: ACTOR.SUCCEEDED → POST rows to Slack, Google Sheets, Airtable or your CRM. Zapier / Make: native Apify modules. Schedules: a realistic pattern is a weekly coverage run (cron 0 6 * * 1, Mondays 06:00 UTC) per trade list, plus a monthly profiles refresh — keeping your trade × city baseline current.
Related Actors
- local-service-leads-scraper — local service businesses by trade and city (Google Maps): phone, website, rating — the US complement to France-only data.
- home-service-business-lead-scraper — home service leads from Houzz, Yellow Pages and BuildZoom.
- thumbtack-scraper — Thumbtack pro listings: ratings, reviews, hire counts, pricing (US).
- angi-scraper — Angi contractor profiles, 150+ categories, with phones and reviews.
- homeguide-scraper — HomeGuide contractor leads by ZIP and trade: rating, reviews, hire count, Top Pro badges.
StarOfService Scraper FAQ: API, Coverage, Contact Data And Alternatives
Does StarOfService have a public API?
No — API Evangelist and apis.io both maintain StarOfService profiles stating so. This Actor uses the internal JSON:API the frontend itself calls (zeus.starofservice.com, SOS-NOID auth, host and token from the __NEXT_DATA__ blob).
Can you scrape StarOfService?
Yes — but not by rendering the site: the WAF 403s datacenter IPs, browsers included. The Actor queries the internal API the site itself calls: paginated, filterable JSON, no DOM parsing.
How many plumbers are there in Paris?
coverage mode with trades: ["plomberie"], cities: ["Paris"] returns proCount, proCountCapped and listingUrl. proCount is a lower bound; proCountCapped: true means the 10-profile page was full (at least 10). Works for any trade, any French city.
How do I get leads for a cleaning business?
trades: ["nettoyage"] plus your cities in profiles mode → one row per cleaning company: name, profile URL, city, ZIP, rating, reviews. Coverage mode first shows which cities list most.
Where can I get a list of local service businesses with contact details?
Name, trade, city, ZIP, coordinates, rating, review count, description, size, founding year — but StarOfService hides contact details until a quote request, so most phone values are null. Treat profile URLs as the path.
What are the alternatives to this actor — Thumbtack, Angi or something else?
US options (see Related Actors): thumbtack-scraper, angi-scraper, local-service-leads-scraper, home-service-business-lead-scraper, homeguide-scraper. None cover France and this actor covers only the French marketplace — pick by geography.
SEO Keywords
starofservice scraper, scrape starofservice, starofservice api, starofservice alternative, starofservice.com, service business lead generation, local lead generation, contractor leads, plumber leads, cleaning business leads, home service business leads, local service leads, lead scraping, directory scraping, business directory data scraping, service marketplace data, home services market size, home services market research, thumbtack alternative, angi vs thumbtack, local market analysis, find plumbers in paris, artisans in france, service provider directory scraping
For AI Agents & LLM Apps
Purpose: Extract French service-pro profiles and trade × city coverage counts from StarOfService's internal JSON:API — a lead-generation and market-sizing source where no public API exists.
Minimal working input:
{ "mode": "trades" }
Variant — cheapest billed run (1 request per pair):
{ "mode": "coverage", "trades": ["plomberie"], "cities": ["Paris"], "maxPairs": 1 }
Output fields (40, one type per row):
- profile: proUuid, name, url, landingPageUrl, tradeUuid, tradeSlug, tradeName, cityUuid, citySlug, city, cityId, zipCode, department, latitude, longitude, rating, reviewCount, description, presentation, workDescription, bio, phone, startingYear, employees, premium, createdAt, registeredAt, hasAvatar, photo, logo, photos, services
- coverage: tradeSlug, tradeName, cityName, proCount, proCountCapped, listingUrl
- trade: tradeUuid, tradeSlug, tradeName, availableOnLandings
- city: cityUuid, citySlug, cityName, zipCode, fullCityName, fullName, latitude, longitude
Behaviors an agent should know:
modedefaults toprofiles; emptytradesfalls back todefaultTrades(10 slugs);citiesdefaults to["Paris"]. Runmode=tradesfirst for valid slugs.profilesfetches each pair in three sort orders (~23 unique pros) and emits onecoveragerow per pair;coverageemits counts only, 1 request per pair.proCountis a lower bound;proCountCapped: truemeans "≥10, likely more" — never an exact total.maxProfiles(default 500) is a target, not a page limit;maxPairs: 0auto-computes pairs;maxRequestsPerCrawl(1000) caps requests; free accounts are capped at 10 profiles.includeDetailsdefaults tofalse—bioandregisteredAtare absent unless enabled (+1 request per profile).phoneis usuallynullby platform design, not an extraction failure.- The API token auto-refreshes from the SSR blob;
apiTokenoverrides it. An enabled proxy applies to every Crawlee request;maxConcurrencymust be 1–10 (default 8).
Billing: pay-per-event — result $0.005 per result, Actor Start $0.00005 per run start.
Legal & Compliance Disclaimer
- This Actor is an independent third-party tool and is not affiliated with, endorsed by, sponsored by, or connected to StarOfService or starofservice.com.
- It accesses only publicly available data: public profile and directory pages and the unauthenticated JSON:API endpoints those pages call — no login, no account creation, no auth bypass. The API token is read from the site's own publicly served pages.
- StarOfService's terms restrict commercial reuse of its directory. You are responsible for compliance with those terms and applicable data-protection law — for France/EU data, that includes the GDPR.
- Output rows may occasionally contain a phone number. Contact data must not be used for unsolicited commercial outreach in violation of applicable law (including GDPR and ePrivacy direct-marketing rules).
- The internal API is unofficial and may change without notice. Rate-limit your runs, respect
robots.txt, and use the data for legitimate market research and lead generation.