Les pages d'annonces Airbnb contiennent exactement le type d'informations tarifaires qui alimentent la recherche de voyages, l'analyse de marché et le suivi concurrentiel : un tarif nuitée, un titre d'annonce, une note des voyageurs et la localisation publique indiquée par l'hôte. Le problème est qu'Airbnb effectue le rendu de ces pages côté client et les protège vigoureusement contre le trafic automatisé, de sorte qu'une simple requête HTTP vous retourne une coquille vide sans aucun prix.
Ce guide vous montre comment extraire les prix Airbnb avec Python de manière fiable. Vous construisez un petit scraper fonctionnel qui récupère une page d'annonce rendue via la Crawling API, analyse les champs souhaités avec BeautifulSoup et affiche un enregistrement structuré et propre. Nous limitons le tutoriel aux données d'annonces publiques, et la section sur la légalité vers la fin n'est pas du remplissage, alors lisez-la avant de pointer cela sur un volume réel.
Ce que vous allez construire
Un script Python qui prend une URL d'annonce Airbnb publique, récupère le HTML rendu via la Crawling API et extrait un enregistrement structuré pour l'annonce. Nous utiliserons une URL de chambre unique comme exemple fil conducteur et extrairons ces champs :
- Titre le nom de l'annonce affiché en haut de la page.
- Prix le tarif nuitée pour les dates demandées.
- Note la note publique des voyageurs, comme "4.92".
- Localisation le secteur qu'Airbnb affiche publiquement pour l'annonce.
Pourquoi une simple requête échoue sur Airbnb
Si vous envoyez une requête vers une URL de chambre Airbnb avec un simple client HTTP, vous obtenez une réponse avec le statut 200 et pratiquement aucune donnée d'annonce dans le corps. Deux facteurs jouent contre vous. Premièrement, Airbnb effectue le rendu du contenu de ses annonces dans le navigateur avec JavaScript, de sorte que le HTML initial n'est qu'une coquille qui ne se remplit qu'après l'exécution des scripts de la page. Deuxièmement, Airbnb détecte rapidement le trafic automatisé : les IP de datacenter et les schémas de requêtes qui ne ressemblent pas à un vrai navigateur sont bloqués ou mis en défi avant d'atteindre le contenu rendu.
Il existe une troisième complication propre à la tarification. Depuis la refonte du système de prix d'Airbnb, le tarif nuitée n'apparaît que lorsque la page dispose de dates d'arrivée et de départ ainsi que d'un nombre de voyageurs. La tarification est dynamique : la même annonce affiche un prix différent selon les dates, les week-ends et les saisons. Un scraper de prix Airbnb fonctionnel a donc besoin d'un navigateur qui rende la page, d'une IP que la plateforme reconnaît comme un visiteur réel, et de paramètres de dates dans l'URL pour que le prix s'affiche.
Vous pouvez assembler cela vous-même avec un navigateur headless et un pool de proxies résidentiels rotatifs, mais les assembler et les maintenir en bon état représente l'essentiel du travail. La Crawling API regroupe les parties difficiles en un seul appel : vous lui envoyez l'URL de l'annonce avec un token JavaScript, elle effectue le rendu de la page derrière une IP de confiance et vous retourne le HTML terminé à analyser.
Crawlbase propose deux types de tokens. Le token normal récupère le HTML statique ; le token JavaScript (JS) effectue d'abord le rendu de la page dans un vrai navigateur. Airbnb est rendu côté client, vous avez donc besoin du token JS ici. Utiliser le token normal retourne la même coquille vide qu'une requête ordinaire, sans prix à analyser.
Prérequis
Vous avez besoin de quelques éléments en place avant d'écrire du code. Aucun ne prend beaucoup de temps.
Python de base. Vous devez être à l'aise pour écrire et exécuter un script Python et installer des paquets avec pip. Si vous êtes novice en analyse HTML, notre guide sur comment utiliser BeautifulSoup en Python couvre les bases des sélecteurs que ce tutoriel suppose acquises.
Python 3.8 ou ultérieur. Vérifiez votre version avec python --version. Si vous ne l'avez pas, installez-le depuis python.org ou via une distribution comme Anaconda.
Un compte Crawlbase et un token JS. Inscrivez-vous, ouvrez votre tableau de bord et copiez votre token JavaScript (JS) depuis la page de documentation du compte. Traitez le token comme un mot de passe : il authentifie vos requêtes, alors gardez-le hors du contrôle de version.
Configurer le projet
Créez un environnement virtuel pour isoler les dépendances du projet, puis installez les deux bibliothèques dont le scraper a besoin.
python --version python -m venv airbnb_env source airbnb_env/bin/activate pip install crawlbase beautifulsoup4
Sous Windows, activez l'environnement avec airbnb_env\Scripts\activate à la place de la ligne source. Deux dépendances font le travail : crawlbase est le client officiel de la Crawling API, et beautifulsoup4 analyse le HTML retourné pour extraire les champs individuels par sélecteur CSS.
Étape 1 : Récupérer l'annonce rendue
Commencez par obtenir la page terminée. Importez la classe CrawlingAPI, initialisez-la avec votre token JS et demandez l'URL de l'annonce avec les dates en paramètres. Vérifier le code de statut avant d'analyser rend les échecs visibles plutôt que silencieux.
from crawlbase import CrawlingAPI api = CrawlingAPI({"token": "YOUR_CRAWLBASE_JS_TOKEN"}) def crawl(page_url): options = {"ajax_wait": "true", "page_wait": 5000} response = api.get(page_url, options) if response["status_code"] == 200: return response["body"].decode("latin1") print(f"Request failed: {response['status_code']}") return None if __name__ == "__main__": page_url = ( "https://www.airbnb.com/rooms/721540609203378406" "?check_in=2026-07-09&check_out=2026-07-12&adults=2" ) html = crawl(page_url) print(html[:500] if html else "No HTML returned")
Les paramètres de requête check_in, check_out et adults ne sont pas optionnels pour la tarification. Sans eux, la page se charge, mais le tarif nuitée reste masqué et le champ prix revient vide quel que soit votre sélecteur. Les deux options d'attente importent pour une cible rendue côté client comme celle-ci : ajax_wait indique à l'API d'attendre la fin du chargement du contenu asynchrone, et page_wait maintient une attente fixe en millisecondes après le chargement pour que les éléments à rendu tardif apparaissent avant la capture de la page. Cinq secondes est un bon point de départ ; augmentez si le prix revient vide. Airbnb envoie des pages dans diverses encodages, donc le décodage en latin1 évite les erreurs d'octets qu'un décodage strict UTF-8 peut générer. Exécutez le script et vous devriez voir le vrai balisage de l'annonce, pas la coquille vide qu'une requête ordinaire retourne.
Airbnb nécessite une page rendue derrière une IP de confiance, en un seul appel. La Crawling API prend un token JS, exécute la page dans un vrai navigateur, fait tourner les IP résidentielles côté serveur et vous remet le HTML terminé, vous évitant ainsi de gérer une flotte headless et un pool de proxies. Pointez-la sur une annonce publique avec le niveau gratuit d'abord.
Étape 2 : Analyser les champs de l'annonce avec BeautifulSoup
HTML rendu en main, chargez-le dans BeautifulSoup et extrayez chaque champ par son sélecteur. Airbnb dispose les détails principaux dans des conteneurs de section stables, vous pouvez donc associer titre, prix, note et localisation à des sélecteurs individuels. Encapsulez toute l'extraction dans un try/except pour qu'un champ manquant ne fasse pas planter l'exécution.
from bs4 import BeautifulSoup def text_of(soup, selector): el = soup.select_one(selector) return el.get_text(strip=True) if el else None def scrape_listing(html): soup = BeautifulSoup(html, "html.parser") return { "title": text_of(soup, 'div[data-section-id="TITLE_DEFAULT"] h1'), "price": text_of(soup, 'div[data-testid="book-it-default"] span > span'), "rating": text_of(soup, 'div[data-testid="pdp-reviews-highlight-banner-host-rating"] span'), "location": text_of(soup, 'div[data-section-id="LOCATION_DEFAULT"] h3'), }
L'assistant text_of fait deux choses utiles à la fois : il interroge un seul élément et retourne None lorsque l'élément est absent, au lieu de lever une exception sur un appel .get_text() contre rien. Cela rend l'extraction résistante quand un champ est absent, ce qui est courant puisqu'une toute nouvelle annonce peut ne pas avoir de note. Les attributs data-section-id et data-testid d'Airbnb sont plus stables que ses noms de classe CSS hachés, préférez donc ces attributs de données comme ancres.
Le balisage d'Airbnb, en particulier ses noms de classe hachés, change sans préavis. Traitez les sélecteurs ci-dessus comme un modèle de départ, non comme un contrat. Quand un champ revient None, réinspectez la page en direct dans les outils de développement de votre navigateur et mettez à jour le sélecteur. La maintenance périodique des sélecteurs est normale pour tout scraper en production, ce n'est pas le signe que quelque chose est cassé.
Étape 3 : Tout assembler
Maintenant reliez la récupération et l'analyse en un seul script exécutable. Récupérez le HTML rendu, transmettez-le au parseur et affichez l'enregistrement structuré au format JSON.
import json from crawlbase import CrawlingAPI from bs4 import BeautifulSoup api = CrawlingAPI({"token": "YOUR_CRAWLBASE_JS_TOKEN"}) def crawl(page_url): options = {"ajax_wait": "true", "page_wait": 5000} response = api.get(page_url, options) if response["status_code"] == 200: return response["body"].decode("latin1") print(f"Request failed: {response['status_code']}") return None def text_of(soup, selector): el = soup.select_one(selector) return el.get_text(strip=True) if el else None def scrape_listing(html): soup = BeautifulSoup(html, "html.parser") return { "title": text_of(soup, 'div[data-section-id="TITLE_DEFAULT"] h1'), "price": text_of(soup, 'div[data-testid="book-it-default"] span > span'), "rating": text_of(soup, 'div[data-testid="pdp-reviews-highlight-banner-host-rating"] span'), "location": text_of(soup, 'div[data-section-id="LOCATION_DEFAULT"] h3'), } def main(): page_url = ( "https://www.airbnb.com/rooms/721540609203378406" "?check_in=2026-07-09&check_out=2026-07-12&adults=2" ) html = crawl(page_url) if not html: return data = scrape_listing(html) print(json.dumps(data, indent=2)) if __name__ == "__main__": main()
À quoi ressemble la sortie
Exécutez le script complet avec python scraper.py et vous obtenez un enregistrement structuré propre pour l'annonce, prêt à écrire en JSON, CSV ou dans une base de données.
{ "title": "Lovely Studio with Burj Khalifa views from Balcony", "price": "$187 per night", "rating": "4.92", "location": "Dubai, United Arab Emirates" }
Extraire les prix sur plusieurs dates
Une plage de dates est une démonstration ; le vrai travail de tarification consiste à comparer la même annonce sur de nombreuses dates, car les prix Airbnb évoluent avec le calendrier. La structure reste la même : conservez une liste de paires de dates, reconstruisez l'URL pour chacune, récupérez-la via la Crawling API et analysez-la avec la même fonction. Comme la structure de l'annonce ne change pas, le parseur que vous avez déjà écrit fonctionne pour chaque date sans modification.
room_id = "721540609203378406" date_ranges = [ ("2026-07-09", "2026-07-12"), ("2026-08-13", "2026-08-16"), ] results = [] for check_in, check_out in date_ranges: url = ( f"https://www.airbnb.com/rooms/{room_id}" f"?check_in={check_in}&check_out={check_out}&adults=2" ) html = crawl(url) if html: row = scrape_listing(html) row["check_in"] = check_in results.append(row) with open("airbnb_prices.json", "w") as f: json.dump(results, f, indent=2)
Pour trouver des URL d'annonces au départ, vous pouvez récupérer les résultats de recherche publics d'Airbnb avec le même schéma, collecter les liens de chambres puis visiter chacun avec des dates. Gardez simplement le volume raisonnable et respectez les attentes en matière de débit couvertes ci-dessous. Si vous comptez alimenter un modèle de tarification, notre guide sur l'utilisation du web scraping pour l'intelligence des prix explique comment les équipes transforment un flux de tarifs en quelque chose utilisable pour la décision.
Rester non bloqué
Même avec le rendu géré, Airbnb surveille le trafic à l'allure d'un scraper. Quelques habitudes maintiennent une exécution saine, et elles s'appliquent à toute cible JavaScript-intensive difficile.
- Espacez vos requêtes. Marteler une annonce sur des dizaines de plages de dates en boucle serrée est le moyen le plus rapide d'être limité. Répartissez les requêtes et variez vos cibles au lieu de parcourir un seul chemin à pleine vitesse.
- Misez sur la rotation. Un pool d'IP résidentielles répartit les requêtes sur de nombreuses adresses d'utilisateurs réels afin qu'aucune ne déclenche une limite de débit. La Crawling API gère cela pour vous ; si vous construisez votre propre pile, c'est la partie à soigner.
- Lisez les codes de statut. Une exécution qui commence à retourner des défis ou des erreurs vous indique que le débit ou le niveau d'IP actuels ne suffisent plus. Traitez cela comme un signal pour lever le pied, pas comme du bruit à ignorer.
Pour le guide complet, voir comment scraper des sites web sans être bloqué et l'analyse approfondie sur comment contourner les captchas lors du web scraping. Comme Airbnb est très JavaScript-intensif, notre tutoriel sur comment crawler des sites web JavaScript vaut également la lecture. Si vous préférez acheminer votre propre trafic via un pool rotatif plutôt qu'utiliser l'API gérée, le Smart AI Proxy vous offre la même rotation d'IP résidentielles comme endpoint proxy plug-and-play.
Est-il légal de scraper Airbnb ?
La question de savoir si le scraping d'Airbnb est autorisé dépend des conditions d'utilisation d'Airbnb, de votre juridiction et de l'usage que vous faites des données. Les conditions d'Airbnb restreignent spécifiquement l'accès automatisé, de sorte que le scraping peut aller à l'encontre de ces conditions quelle que soit la prudence de vos outils. Aucun code ici ne change cela ; il fait simplement fonctionner la partie technique. Lisez les Conditions d'utilisation d'Airbnb et son robots.txt, et traitez les deux comme les limites de ce que vous collectez.
Quelques lignes à tenir. Collectez uniquement les données d'annonces publiques : le titre, le prix nuitée, la note publique et la localisation qu'Airbnb affiche sur l'annonce sans compte. Respectez les attentes de débit d'Airbnb et gardez votre volume de requêtes suffisamment bas pour ne pas solliciter ses serveurs. Ce guide est délibérément limité aux pages d'annonces publiques car c'est la ligne qui rend le travail défendable.
Ce qu'il ne couvre pas est tout aussi important. Ne collectez pas de données personnelles d'hôtes ou de voyageurs, de coordonnées ou de messages. Ne touchez pas aux pages protégées par connexion, aux données de compte ou de réservation derrière une connexion, ni à quoi que ce soit nécessitant de contourner l'authentification. Cela est hors de portée ici et va à l'encontre des conditions d'Airbnb. Pour une utilisation commerciale ou à grand volume, la bonne voie est un partenariat officiel ou un accord API avec Airbnb, pas un scraper plus sophistiqué. Données d'annonces publiques uniquement.
Points clés
- Airbnb est rendu côté client. Une simple requête retourne une coquille vide, vous devez donc rendre la page avant de l'analyser.
-
La tarification nécessite des dates. Passez
check_in,check_outetadultsdans l'URL sinon le tarif nuitée ne s'affiche jamais ; les prix sont dynamiques et évoluent avec le calendrier. -
Vous avez besoin du rendu et d'une IP de confiance ensemble. La Crawling API avec un token JS fait les deux en un seul appel ;
ajax_waitetpage_waitcontrôlent la durée d'attente du contenu. -
BeautifulSoup fait l'extraction. Ancrez-vous sur les attributs
data-section-idetdata-testidpour le titre, le prix, la note et la localisation, et attendez-vous à ce que les sélecteurs évoluent. - Restez sur les données publiques. Respectez les CGU et robots.txt d'Airbnb, préférez un partenariat officiel pour un usage commercial et ne touchez jamais aux données personnelles d'hôtes ou de voyageurs, aux messages ou aux pages protégées par connexion.
Foire aux questions
Pourquoi une simple requête ne retourne-t-elle aucun prix depuis Airbnb ?
Deux raisons. Premièrement, Airbnb rend son contenu d'annonce côté client avec JavaScript, de sorte que le HTML brut n'est qu'une coquille qui ne se remplit qu'après l'exécution des scripts de la page. Deuxièmement, le tarif nuitée ne s'affiche que lorsque l'URL comporte des dates d'arrivée et de départ ainsi qu'un nombre de voyageurs. Une simple requête HTTP sans dates retourne le statut 200 sans aucun prix. Rendre la page avec le token JS de la Crawling API, avec les dates dans l'URL, est ce qui fait apparaître le prix.
Ai-je besoin du token normal ou du token JS pour Airbnb ?
Le token JS. Le token normal récupère le HTML statique, qui sur Airbnb est la même coquille vide qu'une requête ordinaire retourne. Le token JS rend la page dans un vrai navigateur avant de transmettre le HTML, de sorte que les champs de l'annonce, y compris le prix, sont présents quand BeautifulSoup les analyse.
Pourquoi la même annonce affiche-t-elle des prix différents ?
Airbnb utilise une tarification dynamique. Le tarif nuitée change avec les dates demandées, les week-ends par rapport aux jours de semaine, la demande et la saison, et certains hôtes appliquent des remises selon la durée de séjour. C'est prévu, pas un bug dans votre scraper. Si vous voulez comparer les prix, parcourez plusieurs plages de dates pour la même chambre et enregistrez le tarif pour chacune, comme le fait l'exemple multi-dates dans ce guide.
Mes sélecteurs retournent None. Qu'est-ce qui a changé ?
Très probablement le balisage d'Airbnb. Ses noms de classe CSS hachés changent fréquemment et les mises en page des sections évoluent dans le temps, de sorte que les sélecteurs qui fonctionnaient le mois dernier peuvent casser. Ancrez-vous sur les attributs plus stables data-section-id et data-testid quand vous le pouvez, réinspectez une page en direct dans les outils de développement de votre navigateur quand un champ revient vide et mettez à jour le sélecteur. La maintenance périodique des sélecteurs est normale pour tout scraper en production.
Comment éviter d'être bloqué en scrapant Airbnb ?
Gardez votre débit de requêtes par IP faible, variez vos cibles au lieu de parcourir une annonce sur de nombreuses dates dos à dos, et routez via des IP résidentielles rotatives pour qu'aucune adresse unique ne déclenche une limite de débit. La Crawling API gère la rotation et un pool d'IP de confiance pour vous ; si vous construisez votre propre pile, c'est la partie à soigner. Surveillez les codes de statut et levez le pied quand vous commencez à voir des défis.
Quelles données Airbnb puis-je collecter légalement ?
Tenez-vous aux données d'annonces publiques : le titre, le prix nuitée, la note publique et la localisation affichée sur l'annonce sans connexion. Ne collectez pas de données personnelles d'hôtes ou de voyageurs, coordonnées, messages ou quoi que ce soit derrière une connexion, et ne contournez jamais l'authentification. Respectez les conditions d'utilisation et robots.txt d'Airbnb, et pour une utilisation commerciale ou en volume poursuivez un partenariat officiel ou un accord API plutôt que de faire évoluer un scraper contre le site public.
Crawlez n'importe quel site à grande échelle, sans combattre l'infrastructure.
Crawlbase gère les proxies, les empreintes et les CAPTCHA afin que votre équipe livre des pipelines de données au lieu de maintenir la plomberie de crawl. 1 000 requêtes gratuites, sans carte requise.
