Extract business emails, phone numbers, company names and registration details from Airbnb professional hosts. Search by city — Europe countries only. Built for B2B outreach, property management agencies, and lead generation. Export-ready results.
Input validation: graceful exit instead of crash — throw new Error() on invalid input (missing country, no valid URLs) replaced with await Actor.fail(statusMessage). The Actor now exits cleanly with a human-readable status message visible in the Apify console, instead of crashing with a Node.js stacktrace.
Smart country suggestion on validation error — when a city is entered without a country, the error message now suggests the correct country for 50+ common cities (US, UK, Germany, Italy, Portugal, Greece, Australia, etc.). Example: "London" → Did you mean "London, United Kingdom"? instead of the misleading "London, Spain" or "London, France".
No charge for empty results (onlyProHosts: true) — the final dataset push now filters out pro host listings that have no contact data at all (no companyEmail, companyPhone, or companyName). Users are only charged for results that actually contain extracted contact information.
Changed
Input prefill — updated to ["Marbella, Spain", "Miami, United States"] to show users that non-EU cities are supported and to reinforce the City, Country format.
Actor title — updated to Airbnb Pro Host Business Email Scraper for better Store discoverability.
Actor description & SEO metadata — rewritten to highlight emails, phone numbers, company names, and global city coverage (Europe, US, UK, 50+ countries).
[1.9.0] - 2026-03-26
Removed
Post-search geographic filter on cards (isListingInSearchLocation): listings returned by Airbnb search are no longer excluded based on the city line on the card (avoided false negatives e.g. Thessalonique vs Thessaloniki). The search area remains whatever Airbnb’s search URL covers. isListingInSearchLocation remains in searchUtils.js for unit tests.
Added
CSV column Photo count (immediately after Photo URLs); photo URL list is unchanged.
**hostContactCacheByHostId**: when **deduplicateHosts: true**, after the first successful contact fetch per Airbnb **hostId** (from listing HTML), company/contact fields are reused for the same host’s other listings so redundant Puppeteer modal runs are skipped when possible.
Structured English runtime logs: separator line LOG_SEP, clearer section headers, progress lines unchanged (bars, %, ETA).
Changed
Apify dataset · onlyProHosts (défaut true) : plus de **Actor.pushData pendant l’extraction** — envoi une fois à la fin, après filtre pro, dédup listing et dédup hôte. **onlyProHosts: false** réactive le push progressif (comme avant pour les runs « tous les types d’hôtes »).
Co-host columns (CSV + Google Sheets): single Co-host names replaced by **Co-host name 1**, **Co-host name 2**, **Co-host name 3** (max three names; comma/newline-split for strings). Helper **coHostNamesToThreeColumns** in searchUtils.js. Dataset JSON still exposes **coHostNames** as an array.
Local CSV export (output.csv): UTF-8 BOM (\uFEFF) so Excel detects encoding; prices formatted to two decimals; rating normalized (e.g. New / numeric); discount % formatting aligned; **exportToCSV** receives **input** for CSV-related flags.
Google Sheets: **EXPORT_HEADERS / buildListingRow** aligned with CSV (including Photo count and three co-host columns).
Apify Store input form: removed **disclosureDomain** from input_schema.json (advanced options remain available via raw JSON / API where applicable).
Fixed
Discount % in CSV: French locale uses a consistent numeric format with decimal separator.
[1.8.1] - 2026-03-25
Fixed
Apify : 0 annonce sur airbnb.fr pour certaines villes UE hors France (ex. Thessaloniki) : la page JSON peut renvoyer searchResults vide depuis IP datacenter. Repli automatique vers le domaine logique (**airbnb.com) une fois par run (log d’avertissement) ; la divulgation reste sur **airbnb.fr. Le flag _useLogicalSearchDomain sur l’objet cityInput évite de retenter .fr à chaque page de pagination.
[1.8] - 2026-03-25
Changed
Recherche UE sur airbnb.com (ex. Grèce) : autocomplete, URL /s/… et fetch HTML StaysSearch passent par **airbnb.fr** quand le pays est UE/EEE et que le domaine « logique » serait .com, afin d’obtenir les cartes « Hôte professionnel » et un pré-filtre onlyProHosts fiable depuis Apify / proxy. Le suffixe d’URL reste le pays réel (ex. --Greece). getLocaleConfig inchangé pour le reste ; divulgation toujours via getDisclosureFetchDomain.
[1.7] - 2026-03-25
Fixed
Apify vs local (emails pros vides sur le cloud) : pour les pays UE/EEE, le chargement du bloc légal (email, tél, raison sociale) se fait désormais via airbnb.fr + Accept-Language aligné, même quand la recherche reste sur airbnb.com (ex. Grèce). Sur airbnb.com depuis des IP datacenter, Airbnb omet souvent la même divulgation qu’en Europe — d’où des résultats en local et quasi rien sur Apify. Option JSON **disclosureDomain** pour forcer un autre site (ex. airbnb.es).
[1.6] - 2026-03-25
Fixed
**deduplicateHosts: true + Apify** : les lignes n’étaient envoyées au dataset qu’à la fin du run ; en cas d’arrêt manuel, le dataset restait vide alors que l’extraction avait trouvé des pros. Désormais, chaque hôte dédoublonné avec email / téléphone / raison sociale est poussé au fur et à mesure (re-push si les champs contact s’enrichissent après fusion).
[1.5] - 2026-03-25
Added
**coHostNames**: extraction des co-hôtes depuis le JSON PDP "cohosts":[{"name":"…"},…] (fiable sur airbnb.fr / .com même sans libellés « Your co-host » en français), avec repli sur le texte « Your co-host » / « Votre co-hôte » si présent. CSV / Sheets (v1.9) : trois colonnes Co-host name 1–3 au lieu d’une seule colonne « Co-host names ».
[1.4] - 2026-03-25
Store / apify push: version must be **MAJOR.MINOR** (e.g. 1.5). package.json uses 1.5.0 for npm.
Fixed
English search cards (airbnb.com): Pro hosts are labeled “Business host” on listing cards, not “Professional host” — search-step detection now matches both, so onlyProHosts pre-filters contact extraction again instead of opening every listing.
Added
Automatic Airbnb site: Domain (airbnb.com, airbnb.fr, airbnb.es, …) is inferred from the country in City, Country — no UI field; optional locale in JSON API still overrides.
Fixed
Wrong country in results (e.g. Greece): Domain follows the parsed country instead of defaulting to airbnb.fr when cities share one country.
Autocomplete: Uses the same country-aware domain as search (per city).
English card titles (Apartment in Thessaloniki, …): City parsed from the title so geographic filtering works on airbnb.com.
Local npm start: Merging root input.json clears stale searchLocale / locale from Apify local storage when those keys are absent from the file.
Changed
Location filter: Removed from the Actor form (historical; post-search city-line filter dropped in [1.9]).
Google Sheets & Drive: Removed from the Actor input form (Step 3). Same keys still work when passed in raw JSON input or API (googleSheetsEnabled, googleDriveUploadPhotos, …).
[1.3.0] - 2026-03
Added
onlyProHosts in UI: Toggle to include all host types (pro + individual) — unchecked = more listings, takes longer
Modes reduced to 2: Host profile mode removed — only City search and Listing URLs
Output in English: Amenities and rating normalized (French → English: "Nouveau" → "New", "4,96 (24)" → 4.96)
Interface: Emojis removed from step titles and mode labels
[1.2.0] - 2025-03-11
Added
City name autocomplete: Resolves city names via Airbnb autocomplete API — variants (Iraklio, Irakleio, Chaniá…) are converted to the canonical form for the locale (e.g. Heraklion, Chania on airbnb.fr). Fixes zero-result searches for cities with translated spellings.
useCityAutocomplete: Input option (enabled by default). Set to false to disable.
COUNTRY_TO_ISO: Complete country mapping (445 entries) in multiple languages (EN, FR, ES, DE, IT, PT, EL…) to filter autocomplete results correctly.
input.locale : Override the domain (en, fr, es, de, it, pt). Leave empty for auto-detection from city country.
Changed
Global fallback : No longer defaults to airbnb.fr. Greece, USA, UK, Canada, Australia → airbnb.com. France, Spain, Germany… → their local domain.
Contact extraction : Uses the locale domain (airbnb.com for Greece) instead of always fetching from airbnb.fr — output labels, URLs and content now match the city’s country.
[1.1.1] - 2025-02-25
Changed
Streaming memory: Push + remove from memory after each batch — no longer holds 10k listings in RAM
Default memory: Back to 4 GB (streaming keeps usage low)
Large runs: Concurrency reduced when >2000 listings
Run log: Buffer capped at 2000 lines
Fixed
OOM: Streaming architecture avoids OOM on 10k+ listings without paying for 8–16 GB RAM
[1.1.0] - 2025-02-24
Added
RUN_LOG: Live progress log in Key-Value Store — users can open the Run Log link during execution to monitor scraping progress (bars, %, ETA, pro hosts found)
Progressive push: Results stream to the dataset as each contact is extracted — no need to wait until the end to see data
CHANGELOG: Version history visible on the Apify Store page
Changed
Output schema: Added "Run Log (live)" link pointing to Key-Value Store RUN_LOG record
onlyProHosts: Default true (pro hosts only). Set false in input to include all host types (individual + pro)
[1.0.0] - 2025-02
Added
Initial release
City search, Listing URLs modes
Contact extraction: email, phone, company name, address
Professional host detection via Airbnb labels + page scraping