TL;DR — Une macro de scraping reçoit le HTML envoyé par le serveur, pas la page que vous voyez. Votre navigateur exécute du JavaScript une fois la page arrivée et construit souvent à ce moment-là le tableau qui vous intéresse, si bien que celui-ci n'apparaît jamais dans ce que VBA télécharge. Vérifiez d'abord : ouvrez Afficher le code source de la page (Ctrl+U) et recherchez une valeur dont vous avez besoin. Si elle y est, téléchargez la page avec
XMLHTTPet lisez-la avec un documenthtmlfile. Sinon, la page charge ses données via une requête JSON, et appeler directement cette requête est plus simple et plus stable que n'importe quel scraping. L'automatisation d'Internet Explorer n'est plus une option.
Dim http As Object, doc As Object
Set http = CreateObject("MSXML2.XMLHTTP.6.0")
http.Open "GET", "https://example.com/prices", False
http.send
Set doc = CreateObject("htmlfile")
doc.body.innerHTML = http.responseText
Debug.Print doc.getElementsByTagName("table").Length & " tables found"
Voici le troisième article d'une série consacrée à faire entrer des données du web dans Excel : la requête HTTP en VBA couvre la requête, VBA JSON la réponse structurée, et celui-ci les pages écrites pour des personnes plutôt que pour du code. L'idée de la série : une requête web vous remet du texte, pas des données. Entre le serveur et vos cellules se trouvent trois traductions qui vous appartiennent : des octets au texte, du texte à la structure, de la structure à la grille. Le scraping en est la version où la structure ne vous a jamais été destinée.
Ce que vous allez apprendre
- Le modèle mental : le HTML envoyé par le serveur
- Le test des dix secondes : afficher le code source
- Quand les données ne sont pas dans le source : trouver le JSON
- Pourquoi ni Internet Explorer ni Selenium
- Lire un tableau HTML avec htmlfile
- Les nombres extraits sont du texte
- Texte illisible à cause d'un meta charset
- Power Query et scraping courtois
Le modèle mental : le HTML envoyé par le serveur
Un navigateur fait deux choses avec une page. Il télécharge le HTML, puis exécute le JavaScript de la page, qui va souvent chercher d'autres données et construit à l'écran tableaux, prix et listes. Ce que vous voyez est le résultat de ces deux étapes. Ce que VBA télécharge avec une requête HTTP n'est que la première : le HTML tel que le serveur l'a envoyé.
C'est pourquoi la plainte la plus fréquente en scraping est « mon code ne trouve aucun tableau, mais je vois le tableau ». Les deux affirmations sont vraies. Le tableau existe dans la page vivante du navigateur, pas dans le HTML envoyé par le serveur. Aucun sélecteur, aucune attente, aucune nouvelle tentative n'y change rien, car les données n'ont jamais été dans ce que vous avez téléchargé.
Le test des dix secondes : afficher le code source
Avant d'écrire la moindre ligne de code, ouvrez la page dans un navigateur et appuyez sur Ctrl+U (Afficher le code source de la page). Vous voyez alors le HTML tel que le serveur l'a envoyé, exactement ce que VBA recevra. Recherchez-y (Ctrl+F) une valeur visible sur la page, comme un prix ou un nom.
- Trouvée : les données sont dans le HTML du serveur. Extrayez-les avec
XMLHTTPethtmlfile, comme ci-dessous. - Introuvable : c'est le JavaScript qui les charge. Passez à la section suivante.
N'utilisez pas Inspecter (F12, Éléments) pour ce test. Inspecter montre la page vivante après exécution du JavaScript : les données y apparaissent donc dans les deux cas.
Quand les données ne sont pas dans le source : trouver le JSON
Une page qui construit son tableau en JavaScript doit bien prendre ses données quelque part, presque toujours dans une requête JSON vers le même site. Trouvez-la :
- Ouvrez les outils de développement du navigateur (F12) et allez dans l'onglet Réseau.
- Filtrez sur Fetch/XHR et rechargez la page.
- Cliquez sur les requêtes et regardez leur Réponse. L'une d'elles contient vos données en JSON.
- Copiez son URL et appelez-la depuis VBA comme le montre la requête HTTP en VBA, puis analysez-la avec VBA JSON.
Cette voie vaut mieux que le scraping, même quand le scraping fonctionnerait. Le JSON a des noms de champs au lieu de positions dans un tableau, des nombres sans symbole monétaire, et il change moins souvent que le design de la page. Vérifiez les conditions d'utilisation du site avant de construire dessus ; un point d'accès non documenté peut aussi changer sans préavis.
Pourquoi ni Internet Explorer ni Selenium
Les anciens tutoriels pilotent un navigateur depuis VBA avec CreateObject("InternetExplorer.Application").
Internet Explorer a été retiré en juin 2022 ; il n'est plus pris en charge, et les sites modernes y
fonctionnent de moins en moins. Ne démarrez aucun nouveau développement dessus, et prévoyez de remplacer les
macros qui en dépendent.
Selenium Basic, le remplaçant habituel en VBA, n'a pas connu de nouvelle version depuis 2016 et exige un pilote de navigateur correspondant à la version installée de Chrome ou d'Edge ; chaque mise à jour du navigateur peut casser la macro sur le poste de l'utilisateur. Il peut encore être le bon outil pour une page qui ne fonctionne qu'avec JavaScript et n'offre aucune requête de données appelable, mais considérez-le comme un dernier recours, pas comme un choix par défaut.
Lire un tableau HTML avec htmlfile
Pour des données présentes dans le HTML du serveur, vous n'avez besoin d'aucun navigateur. Téléchargez la page
et chargez-la dans un objet htmlfile, qui vous donne un document que vous pouvez parcourir comme une page
web :
Sub ScrapeFirstTable(ByVal url As String, ByVal target As Range)
Dim http As Object, doc As Object, tbl As Object
Dim out() As Variant, r As Long, c As Long, nCols As Long
Set http = CreateObject("MSXML2.XMLHTTP.6.0")
http.Open "GET", url, False
http.setRequestHeader "User-Agent", "Mozilla/5.0"
http.send
If http.Status <> 200 Then Err.Raise vbObjectError + 514, , "HTTP " & http.Status
Set doc = CreateObject("htmlfile")
doc.body.innerHTML = http.responseText
If doc.getElementsByTagName("table").Length = 0 Then Err.Raise vbObjectError + 515, , "No table"
Set tbl = doc.getElementsByTagName("table")(0)
nCols = 0
For r = 0 To tbl.Rows.Length - 1
If tbl.Rows(r).Cells.Length > nCols Then nCols = tbl.Rows(r).Cells.Length
Next r
ReDim out(1 To tbl.Rows.Length, 1 To nCols)
For r = 0 To tbl.Rows.Length - 1
For c = 0 To tbl.Rows(r).Cells.Length - 1
out(r + 1, c + 1) = Trim$(tbl.Rows(r).Cells(c).innerText)
Next c
Next r
target.Resize(UBound(out, 1), nCols).Value = out
End Sub
Trois détails comptent. Les collections du document HTML (Rows, Cells, getElementsByTagName) commencent
à 0, contrairement à la plupart des collections d'Excel. Les lignes peuvent avoir des nombres de cellules
différents : dimensionnez donc le tableau d'après la ligne la plus large. Et le tableau entier est écrit dans
la feuille en une seule étape.
Pour trouver un élément précis, appuyez-vous sur getElementById et getElementsByTagName. Selon la version
de Windows et d'Office, un document htmlfile en liaison tardive peut tourner dans un ancien mode de
compatibilité où des méthodes plus récentes comme querySelector et getElementsByClassName sont absentes :
un code bâti sur elles fonctionne sur une machine et pas sur une autre. Pour filtrer par classe, parcourez les
balises et testez .className.
Sélectionner « le premier tableau » est le point le plus faible de tout scraper. Une refonte du site ajoute un
tableau au-dessus du vôtre, et la macro lit en silence le mauvais. Si le tableau a un id, utilisez-le ;
sinon, vérifiez le texte d'une cellule d'en-tête avant de faire confiance au tableau.
Les nombres extraits sont du texte
Tout ce que vous prenez sur une page avec innerText est une chaîne, mise en forme pour les lecteurs de ce
site : 1 234,56 € sur un site français, 1.234,56 € sur un site allemand, $1,234.56 sur un site
américain. Écrite telle quelle dans une cellule, elle ne s'additionne pas. Convertie avec CDbl ou Val, elle
donne un nombre faux ou une erreur, selon les paramètres régionaux de l'utilisateur.
Convertissez d'après le format du site, pas celui de l'utilisateur. Retirez le symbole monétaire et le
séparateur de milliers, transformez le séparateur décimal en point, puis utilisez Val :
Function ParseScraped(ByVal s As String, ByVal thousandsSep As String, ByVal decimalSep As String) As Variant
s = Replace(s, ChrW(160), "") ' espace insecable
s = Replace(s, ChrW(8239), "") ' espace fine insecable
s = Replace(s, " ", "")
s = Replace(s, ChrW(8364), ""): s = Replace(s, "$", "") ' symbole euro
If thousandsSep <> "" Then s = Replace(s, thousandsSep, "")
s = Replace(s, decimalSep, ".")
If s Like "*[!0-9.-]*" Or s = "" Then ParseScraped = CVErr(xlErrValue) Else ParseScraped = Val(s)
End Function
v = ParseScraped(cellText, ".", ",") ' "1.234,56" d'un site allemand -> 1234.56
Les deux espaces insécables sont le piège caché. Les sites français et d'autres sites européens s'en servent
souvent pour séparer les milliers ; elles ressemblent exactement à une espace, et Trim ne les supprime pas.
Voir VBA Trim pour le même caractère dans des données collées.
Texte illisible à cause d'un meta charset
responseText décode la page avec le jeu de caractères indiqué dans l'en-tête HTTP du serveur. Beaucoup de
sites anciens ne déclarent leur encodage qu'à l'intérieur du HTML, avec une balise <meta charset>, et
XMLHTTP ne lit pas cette balise. La page s'affiche correctement dans le navigateur et arrive dans VBA avec
é au lieu de é, ou avec des petits carrés au lieu du texte japonais.
Si le source contient une balise <meta charset="windows-1252"> ou <meta charset="shift_jis"> et que le
texte est illisible, décodez http.responseBody avec ce jeu de caractères, à l'aide de la fonction
ADODB.Stream de la requête HTTP en VBA, et passez le résultat à
doc.body.innerHTML.
Power Query et scraping courtois
Pour un tableau HTML statique que vous voulez actualiser, Excel possède déjà un scraper : Données > À partir du web (Power Query) liste les tableaux d'une page, charge celui que vous choisissez et l'actualise d'un clic, sans VBA. Il a la même limite, puisqu'il lit lui aussi le HTML du serveur, mais quand il fonctionne, c'est moins de code à maintenir. Utilisez VBA quand il vous faut de la logique : une liste d'URL, une connexion avec identifiants, ou la combinaison de plusieurs pages.
Et extrayez avec courtoisie. Une requête par page, une pause entre les pages (voir VBA Wait), pas de nouveau téléchargement de ce que vous avez déjà, et un coup d'œil préalable aux conditions d'utilisation du site et à son robots.txt. Une macro qui envoie cent requêtes par seconde fait bloquer l'adresse IP de votre entreprise, et plus aucune macro ne fonctionne pour personne.
Le parti pris : le scraping est un contrat que personne n'a signé
Une API est une promesse : le fournisseur la documente et s'efforce de ne pas la casser. Une page web ne promet rien. Le designer peut ajouter un tableau, renommer une classe ou déplacer les prix dans du JavaScript dès demain, et votre macro casse sans erreur, ou pire, lit la mauvaise colonne.
Choisissez donc la source la plus stable disponible : d'abord une API officielle, puis la requête JSON derrière la page, puis Power Query sur un tableau statique, puis XMLHTTP avec htmlfile, et l'automatisation d'un navigateur en dernier. Quel que soit votre choix, faites vérifier au scraper ce qu'il a trouvé (un texte d'en-tête, un nombre de lignes) avant d'écrire, pour qu'une refonte produise une erreur plutôt que des nombres faux.
Comment ExcelMaster aide
Les scrapers cassent en silence : la mise en page change, les nombres reviennent formatés pour un autre pays, le texte arrive illisible.
ExcelMaster vérifie ce que le serveur renvoie réellement avant d'écrire le code, cherche la requête de données derrière les pages JavaScript, et convertit les nombres extraits d'après le format du site pour qu'ils arrivent dans votre feuille comme de vrais nombres.
Questions fréquentes
Comment extraire les données d'un site web dans Excel avec VBA ?
Téléchargez la page avec MSXML2.XMLHTTP.6.0, chargez responseText dans CreateObject("htmlfile"),
trouvez le tableau avec getElementsByTagName("table"), lisez l'innerText de chaque cellule dans un tableau
VBA et écrivez ce tableau dans la feuille.
Pourquoi mon scraper VBA ne trouve-t-il pas des données que je vois sur la page ?
La page construit ces données en JavaScript après son chargement : elles ne figurent donc pas dans le HTML que VBA télécharge. Trouvez la requête JSON dans l'onglet Réseau du navigateur et appelez-la directement.
Peut-on encore utiliser Internet Explorer pour le web scraping en VBA ?
Ce n'est pas recommandé. Internet Explorer a été retiré en juin 2022 et n'est plus pris en charge. Utilisez
XMLHTTP avec htmlfile pour les pages statiques, et la requête JSON de la page pour les pages dynamiques.
Pourquoi les nombres extraits ne sont-ils pas des nombres dans Excel ?
innerText renvoie toujours du texte, mis en forme selon le pays du site. Retirez les symboles monétaires et
les séparateurs de milliers, y compris les espaces insécables, remplacez le séparateur décimal par un point et
convertissez avec Val.
Power Query est-il meilleur que VBA pour le web scraping ?
Pour un tableau statique que vous voulez actualiser, oui : Données > À partir du web ne demande aucun code. Utilisez VBA quand vous devez parcourir de nombreuses pages, vous connecter, ou appliquer de la logique entre les requêtes.
Testé dans
Testé dans : Excel 365 (Windows 11), VBA 7.1 — vérifié le 05/10/2026.
Guides connexes : Requête HTTP en VBA · VBA JSON · VBA Trim · VBA Wait · Tableaux 2D en VBA · VBA Replace · VBA Like · VBA CreateObject
