Yahoo Finance est l'une des plateformes les plus consultées pour suivre les actions, les indices et les cryptomonnaies, et ses pages de cotation contiennent exactement les données de marché structurées qui alimentent le suivi des cours, le screening et la recherche : le dernier prix, la variation du jour, le cours de clôture précédent, la capitalisation boursière, le volume et la plage journalière. Pour quiconque surveille une liste de valeurs, ces données de cotation publiques sont la matière première, et les lire manuellement sur des dizaines de symboles est lent et source d'erreurs.
Ce guide vous montre comment scraper Yahoo Finance avec Python de manière fiable. Vous construisez un petit scraper exécutable qui récupère les pages de cotation rendues via la Crawling API, analyse les champs souhaités avec BeautifulSoup, boucle sur une liste de symboles et exporte du JSON et du CSV propres. L'ensemble du tutoriel se limite aux données de marché publiques, et la section sur la légalité en fin d'article n'est pas du remplissage, lisez-la avant de pointer cet outil sur un volume réel.
Ce que vous allez construire
Un script Python qui prend une liste de symboles boursiers, récupère chaque page de cotation rendue de Yahoo Finance via la Crawling API et extrait un enregistrement structuré par symbole. L'exemple fil rouge utilise AAPL, TSLA et BTC-USD. Nous extrayons ces champs :
- Prix le dernier cours de transaction du symbole.
- Variation la variation de prix par rapport à la clôture précédente, en valeur absolue et en pourcentage.
- Clôture précédente le cours de clôture de la session précédente.
- Capitalisation boursière la capitalisation boursière totale affichée dans les statistiques de cotation.
- Volume le nombre d'actions ou d'unités échangées au cours de la session en cours.
- Plage journalière la bande de prix minimum-maximum pour la journée de trading en cours.
Pourquoi une requête ordinaire échoue sur Yahoo Finance
Si vous demandez l'URL d'une cotation Yahoo Finance avec un simple client HTTP, vous obtenez une réponse avec le statut 200 et seulement une fraction des chiffres dans le corps. Deux obstacles se dressent contre vous. D'abord, la page de cotation rend son cours en direct, sa variation et son tableau de statistiques dans le navigateur via JavaScript, donc le HTML initial est une coquille vide qui ne se remplit qu'après l'exécution des scripts de la page. Analysez cette première réponse et vous capturerez des espaces réservés ou des nœuds vides au lieu des chiffres réels. Ensuite, Yahoo signale rapidement le trafic automatisé : les adresses IP de datacenters et les schémas de requêtes qui ne ressemblent pas à un vrai navigateur sont soumis à des limites de débit, redirigés vers une page de consentement ou mis en attente avant d'atteindre le contenu rendu.
Un scraper Yahoo Finance fonctionnel a donc besoin de deux choses dans une seule requête : un navigateur qui rend réellement la page, et une IP que la plateforme lit comme un vrai visiteur. Vous pouvez assembler cela vous-même avec un navigateur sans tête et un pool de proxies résidentiels rotatifs, mais relier ces éléments et les maintenir en bonne santé représente la majeure partie du travail. La Crawling API regroupe les deux en un seul appel : vous lui envoyez l'URL avec un token JavaScript, elle rend la page derrière une IP de confiance, et elle retourne le HTML final à analyser. Si vous voulez des informations de fond sur les cibles nécessitant un rendu comme celle-ci, le guide pour scraper les pages JavaScript avec Python est un bon complément.
Crawlbase propose deux types de tokens. Le token normal récupère le HTML statique ; le token JavaScript (JS) rend d'abord la page dans un vrai navigateur. Yahoo Finance remplit ses champs de prix et de statistiques côté client, donc vous avez besoin du token JS ici. Le token normal retourne la même coquille vide qu'une simple requête, et il y a peu d'utile à en extraire.
Prérequis
Quelques éléments à mettre en place avant d'écrire le moindre 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 packages avec pip. Si vous êtes novice côté analyse, le guide BeautifulSoup est un bon complément à ce tutoriel.
Python 3.8 ou version ultérieure. Vérifiez votre version avec python --version. Si vous ne l'avez pas, installez-le depuis python.org ou via une distribution comme Anaconda, et assurez-vous que Python est dans votre PATH.
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. Crawlbase inclut jusqu'à 20 000 requêtes gratuites pour commencer, ce qui est largement suffisant pour suivre ce guide. Traitez le token comme un mot de passe : il authentifie vos requêtes, donc gardez-le en dehors du contrôle de version.
Configurer le projet
Créez un environnement virtuel pour que les dépendances du projet restent isolées, puis installez les bibliothèques dont le scraper a besoin.
python --version python -m venv yahoo_env source yahoo_env/bin/activate pip install crawlbase beautifulsoup4
Sous Windows, activez l'environnement avec yahoo_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 que vous puissiez extraire les champs individuels par sélecteur CSS. json et csv font partie de la bibliothèque standard, il n'y a donc rien de plus à installer pour l'étape d'export.
Étape 1 : Récupérer une page de cotation rendue
Commencez par obtenir une page complète. Importez la classe CrawlingAPI, initialisez-la avec votre token JS et demandez l'URL d'une cotation Yahoo Finance. Yahoo charge son prix et ses statistiques de manière asynchrone, donc passez ajax_wait et page_wait pour attendre le contenu dynamique avant la capture de la page. Vérifier le cb_status (legacy pc_status) de Crawlbase avant d'analyser permet de garder les échecs visibles plutôt que silencieux.
from crawlbase import CrawlingAPI api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) OPTIONS = { "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/122.0", "ajax_wait": "true", "page_wait": 5000, } def crawl(page_url): response = api.get(page_url, OPTIONS) if response["headers"]["cb_status"] == "200": return response["body"].decode("utf-8") print(f"Request failed: {response['headers']['cb_status']}") return None if __name__ == "__main__": quote_url = "https://finance.yahoo.com/quote/AAPL" html = crawl(quote_url) print(html[:500] if html else "No HTML returned")
Les deux options d'attente sont importantes pour une cible rendue côté client comme celle-ci. ajax_wait indique à l'API d'attendre que le contenu asynchrone finisse de charger, et page_wait maintient un nombre fixe de millisecondes après le chargement pour que le cours en direct se stabilise avant la capture de la page. Cinq secondes est un bon point de départ ; augmentez si les chiffres reviennent vides. Exécutez le script avec python yahoo_scraper.py et vous devriez voir un vrai balisage de cotation, et non la coquille que retourne une simple requête. Cela confirme que le rendu fonctionne avant d'écrire le moindre sélecteur.
Une cotation Yahoo Finance nécessite une page rendue derrière une IP de confiance, en un seul appel, ce que les options ajax_wait et page_wait ci-dessus configurent exactement. La Crawling API prend un token JS, exécute la page dans un vrai navigateur, fait tourner des IP résidentielles côté serveur et vous remet le HTML final, ce qui vous évite de gérer vous-même une flotte sans tête et un pool de proxies. Pointez-la sur une page de cotation publique avec le niveau gratuit d'abord.
Étape 2 : Analyser le prix et la variation en en-tête
Yahoo Finance expose ses données en direct via des attributs data-testid stables sur l'en-tête de cotation, ce qui en fait des cibles d'analyse fiables. Chargez le HTML rendu dans BeautifulSoup et lisez le titre, le prix et la variation à partir de ces attributs. Chaque recherche est protégée pour qu'un champ manquant retourne None au lieu de faire 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_header(html): soup = BeautifulSoup(html, "html.parser") return { "title": text_of(soup, "div.hdr h1"), "price": text_of(soup, '.livePrice[data-testid="qsp-price"]'), "change": text_of(soup, '.priceChange[data-testid="qsp-price-change"]'), "change_percent": text_of(soup, '[data-testid="qsp-price-change-percent"]'), }
L'assistant text_of interroge un élément et retourne son texte nettoyé, ou None si l'élément est absent, ce qui évite qu'un symbole sans un certain champ ne casse la boucle. Les sélecteurs proviennent directement de l'en-tête de cotation de Yahoo : title lit le nom de la société et le symbole depuis l'en-tête div.hdr h1, price lit le nœud de cours en direct marqué qsp-price, et les deux sélecteurs de variation lisent le mouvement absolu (qsp-price-change) et le mouvement en pourcentage (qsp-price-change-percent) qui lui sont adjacents.
Étape 3 : Analyser le tableau de statistiques
Sous l'en-tête, Yahoo Finance rend un petit bloc de statistiques avec la clôture précédente, la capitalisation boursière, le volume, la plage journalière et plus encore. Chaque métrique se trouve dans un élément de liste marqué par un attribut data-field, donc vous lisez le nœud de valeur par nom de champ plutôt que par une position fragile. Cela rend l'analyse stable même lorsque Yahoo réorganise la grille.
STAT_FIELDS = { "previous_close": "regularMarketPreviousClose", "market_cap": "marketCap", "volume": "regularMarketVolume", "day_range": "regularMarketDayRange", } def scrape_stats(soup): stats = {} for key, field in STAT_FIELDS.items(): stats[key] = text_of( soup, f'li[data-field="{field}"] span.value, li[data-field="{field}"] fin-streamer' ) return stats
La correspondance STAT_FIELDS associe chaque nom de sortie au nom de champ interne de Yahoo. Yahoo encapsule les valeurs en direct dans un élément fin-streamer et les valeurs statiques dans un span.value, donc le sélecteur essaie les deux et prend celui qui est présent. Pour trouver le nom de champ exact d'une métrique, ouvrez une page de cotation dans votre navigateur, faites un clic droit sur la valeur et lisez l'attribut data-field sur son élément de liste. La plage journalière revient comme une seule chaîne du type 168.49 - 171.05, que vous pouvez ensuite diviser sur le tiret pour obtenir les valeurs basse et haute séparément.
Yahoo Finance retravaille périodiquement le balisage de ses cotations, et les noms de classes générés changent avec. Les attributs data-testid et data-field utilisés ici sont plus stables que les noms de classes, mais traitez tout sélecteur comme un modèle de départ, pas 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 le sélecteur à jour. Une 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 4 : Assembler le script complet
Reliez maintenant les pièces en un seul script exécutable : bouclez sur une liste de symboles, récupérez chaque page de cotation rendue avec un petit gestionnaire de nouvelles tentatives, analysez l'en-tête et les statistiques en un seul enregistrement, et exportez les enregistrements en JSON et en CSV.
import csv import json import time from crawlbase import CrawlingAPI from bs4 import BeautifulSoup api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"}) OPTIONS = { "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/122.0", "ajax_wait": "true", "page_wait": 5000, } STAT_FIELDS = { "previous_close": "regularMarketPreviousClose", "market_cap": "marketCap", "volume": "regularMarketVolume", "day_range": "regularMarketDayRange", } def crawl(page_url): response = api.get(page_url, OPTIONS) if response["headers"]["cb_status"] == "200": return response["body"].decode("utf-8") print(f"Request failed: {response['headers']['cb_status']}") return None def fetch_html(page_url, max_retries=2): for attempt in range(max_retries + 1): html = crawl(page_url) if html: return html if attempt < max_retries: time.sleep(1) return None def text_of(soup, selector): el = soup.select_one(selector) return el.get_text(strip=True) if el else None def scrape_quote(html, symbol): soup = BeautifulSoup(html, "html.parser") record = { "symbol": symbol, "title": text_of(soup, "div.hdr h1"), "price": text_of(soup, '.livePrice[data-testid="qsp-price"]'), "change": text_of(soup, '.priceChange[data-testid="qsp-price-change"]'), "change_percent": text_of(soup, '[data-testid="qsp-price-change-percent"]'), } for key, field in STAT_FIELDS.items(): record[key] = text_of( soup, f'li[data-field="{field}"] span.value, li[data-field="{field}"] fin-streamer' ) return record def save_outputs(records): with open("yahoo_quotes.json", "w") as f: json.dump(records, f, indent=2) if not records: return with open("yahoo_quotes.csv", "w", newline="") as f: writer = csv.DictWriter(f, fieldnames=records[0].keys()) writer.writeheader() writer.writerows(records) def main(): symbols = ["AAPL", "TSLA", "BTC-USD"] records = [] for symbol in symbols: url = f"https://finance.yahoo.com/quote/{symbol}" html = fetch_html(url) if html: records.append(scrape_quote(html, symbol)) time.sleep(2) save_outputs(records) print(f"Saved {len(records)} quotes") if __name__ == "__main__": main()
Le script boucle sur la liste de symboles, récupère chaque page de cotation avec le gestionnaire de nouvelles tentatives, fusionne les champs d'en-tête et les statistiques en un seul enregistrement, et cadence la boucle avec un délai de deux secondes. save_outputs écrit à la fois un fichier JSON et un CSV en utilisant les clés du premier enregistrement comme en-tête, de sorte que vous ayez les données dans la forme que votre outil en aval préfère. Ajoutez ou supprimez des symboles dans la liste symbols selon votre propre liste de surveillance.
À quoi ressemble la sortie
Exécutez le script complet avec python yahoo_scraper.py et vous obtenez un enregistrement structuré propre par symbole, prêt pour l'analyse, une base de données ou un tableur. Les valeurs ci-dessous sont illustratives ; les chiffres en direct changent à chaque session.
[ { "symbol": "AAPL", "title": "Apple Inc. (AAPL)", "price": "168.99", "change": "-3.70", "change_percent": "(-2.14%)", "previous_close": "172.69", "market_cap": "2.61T", "volume": "54,318,920", "day_range": "168.49 - 171.05" }, { "symbol": "TSLA", "title": "Tesla, Inc. (TSLA)", "price": "156.90", "change": "-4.58", "change_percent": "(-2.84%)", "previous_close": "161.48", "market_cap": "499.81B", "volume": "112,045,300", "day_range": "155.41 - 160.39" } ]
Le CSV correspondant contient les mêmes colonnes, une ligne par symbole, ce qui s'intègre directement dans pandas ou n'importe quel tableur pour tracer une liste de surveillance ou comparer les variations journalières sur plusieurs valeurs.
Passer à l'échelle sur de nombreux symboles et rester non bloqué
Même avec le rendu géré, Yahoo surveille le trafic ayant la forme d'un scraper. Quelques habitudes maintiennent une exécution longue en bonne santé, et elles s'appliquent à toute cible commerciale difficile.
- Cadencez vos requêtes. Marteler les pages de cotation dans une boucle serrée est le moyen le plus rapide de se faire ralentir ou mettre en attente. Espacez les requêtes et variez vos symboles plutôt que de crawler un seul chemin à pleine vitesse.
- Misez sur la rotation. Un pool d'adresses IP résidentielles répartit les requêtes sur de nombreuses adresses d'utilisateurs réels pour 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 à bien maîtriser.
-
Lisez les codes de statut. Une exécution qui commence à retourner des valeurs
cb_statusautres que 200 vous signale que le débit ou le niveau d'IP actuels ne sont plus suffisants. Traitez cela comme un signal pour ralentir, pas comme du bruit à ignorer.
Pour une grande liste de surveillance, le Crawler asynchrone met les requêtes en file d'attente et livre les résultats dans un webhook, ce qui convient pour récupérer des centaines de pages de cotation sans maintenir des connexions ouvertes. Pour le guide complet, consultez comment scraper des sites web sans être bloqué et les notes sur le scraping financier à grande échelle. Le même schéma d'analyse se transpose à d'autres sources de marché, comme le scraping de cours de crypto depuis CoinMarketCap.
Est-il légal de scraper Yahoo Finance ?
La légitimité du scraping de Yahoo Finance dépend des conditions d'utilisation de Yahoo, de votre juridiction et de ce que vous faites avec les données. Les conditions de Yahoo restreignent l'accès automatisé et la collecte de données en masse, donc le scraping peut aller à l'encontre de ces conditions quelle que soit la précision de vos outils. Les chiffres affichés sur une page de cotation sont des données de marché factuelles plutôt que des données personnelles, ce qui réduit les enjeux de confidentialité, mais cela ne vous place pas en dehors des conditions du site. Aucun code ici ne change quoi que ce soit ; il fait seulement fonctionner la partie technique. Lisez les Conditions d'utilisation de Yahoo Finance et son robots.txt, et traitez les deux comme la limite de ce que vous collectez.
La contrainte la plus forte sur les données financières est la licence, pas la confidentialité. Les prix, la capitalisation boursière et le volume que Yahoo affiche ne sont pas les propres relevés de Yahoo : ils proviennent des bourses et de fournisseurs tiers de données de marché, et ces flux ont leurs propres restrictions de redistribution. Collecter un nombre sur une page publique ne vous accorde pas de licence pour le republier, le revendre ou construire un produit commercial par-dessus. Restez sur les pages publiques de cotation et de statistiques, gardez votre volume de requêtes suffisamment modeste pour ne pas solliciter les serveurs de Yahoo, et ne scrapez rien derrière une connexion, un payant ou un niveau premium comme Yahoo Finance Plus.
Ce guide se limite délibérément aux données de marché publiques car c'est la ligne qui rend le travail défendable. Pour tout ce qui dépasse la recherche légère, l'analyse ponctuelle ou une liste de surveillance personnelle, la bonne voie est un flux sous licence : Yahoo et ses partenaires de données, ainsi que les fournisseurs de données de marché dédiés et les API de bourses, offrent un accès officiel et conforme aux conditions pour une utilisation en production. Si vous évaluez les options, notre tour d'horizon des meilleurs fournisseurs de données financières est un bon point de départ. Un flux sous licence, et non un scraper plus malin, est la bonne solution pour un usage commercial ou à fort volume.
Points clés
- Yahoo Finance est rendu côté client. Une simple requête retourne une coquille vide avec des valeurs de remplacement, vous devez donc rendre la page avant d'analyser le prix et les statistiques.
-
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 combien de temps elle attend les chiffres en direct. -
Analysez par attributs stables. Lisez l'en-tête via les valeurs
data-testidcommeqsp-priceet les statistiques via les nomsdata-fieldcommemarketCap, qui résistent mieux aux changements de balisage que les noms de classes. - Bouclez et exportez. Itérez sur une liste de symboles, cadencez l'exécution avec de courts délais et écrivez les enregistrements en JSON et CSV pour que les données s'intègrent dans pandas ou un tableur.
- Respectez les licences. Les chiffres proviennent des bourses et des fournisseurs de données avec leurs propres conditions de redistribution ; restez sur les pages publiques et utilisez un flux sous licence pour tout usage commercial ou à fort volume.
Foire aux questions
Pourquoi une simple requête retourne-t-elle des prix vides depuis Yahoo Finance ?
Parce que Yahoo charge son cours en direct, sa variation et son tableau de statistiques côté client avec JavaScript. Le HTML initial est une coquille qui ne se remplit qu'après l'exécution des scripts de la page dans un navigateur, donc une requête HTTP brute retourne le statut 200 avec des nœuds de valeur vides ou de remplacement. Pour obtenir les vrais chiffres, vous devez d'abord rendre la page, ce que le token JS de la Crawling API gère pour vous.
Ai-je besoin du token normal ou du token JS pour Yahoo Finance ?
Le token JS. Le token normal récupère le HTML statique, qui sur une page de cotation Yahoo est la même coquille vide qu'une simple requête retourne. Le token JS rend la page dans un vrai navigateur avant de restituer le HTML, de sorte que le prix, la variation et les statistiques sont présents quand BeautifulSoup les analyse.
Quels champs puis-je extraire d'une page de cotation Yahoo Finance ?
Les données de marché publiques sur la page : le dernier prix, la variation absolue et en pourcentage par rapport à la clôture précédente, la clôture précédente elle-même, la capitalisation boursière, le volume et la plage journalière. Ce sont des champs de cotation et de statistiques factuels, pas des données personnelles. Restez sur les pages de cotation publiques et évitez tout ce qui est derrière une connexion ou un niveau premium.
Mes sélecteurs retournent None. Qu'est-ce qui a changé ?
Très probablement le balisage de Yahoo. Le site retravaille périodiquement la mise en page de ses cotations, et les noms de classes générés changent avec. Les attributs data-testid (qsp-price, qsp-price-change) et les noms data-field (marketCap, regularMarketVolume) utilisés ici sont plus stables que les classes, mais ils peuvent aussi évoluer. Réinspectez une page en direct dans les outils de développement de votre navigateur et mettez les sélecteurs à jour ; une maintenance périodique est normale pour tout scraper en production.
Comment scraper de nombreux symboles sans être bloqué ?
Bouclez sur votre liste de symboles, gardez un court délai entre les requêtes, et laissez la Crawling API faire tourner les IP résidentielles pour qu'aucune adresse individuelle ne déclenche une limite de débit. Pour une grande liste de surveillance, passez au Crawler asynchrone, qui met les requêtes en file d'attente et poste les résultats dans un webhook plutôt que de maintenir des connexions ouvertes. Surveillez l'en-tête cb_status et ralentissez s'il commence à retourner des valeurs autres que 200.
Puis-je utiliser commercialement des données Yahoo Finance scrapées ?
Traitez cela comme une question juridique, pas technique. Les prix et statistiques sur Yahoo proviennent des bourses et de fournisseurs de données de marché sous licence avec leurs propres conditions de redistribution, et les propres Conditions d'utilisation de Yahoo restreignent la collecte et la réutilisation automatisées. Pour un usage commercial ou à fort volume, la bonne voie est un flux de données de marché sous licence ou une API officielle, et non un scraper. Examinez les conditions et consultez un conseiller juridique avant de construire un produit sur la base de ces données.
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.

