TL;DR — Ein Scraping-Makro erhält das HTML, das der Server gesendet hat, nicht die Seite, die Sie sehen. Ihr Browser führt JavaScript aus, nachdem die Seite angekommen ist, und baut oft erst dann die Tabelle, die Sie haben wollen; in dem, was VBA herunterlädt, taucht sie deshalb nie auf. Prüfen Sie zuerst: Öffnen Sie Seitenquelltext anzeigen (Strg+U) und suchen Sie nach einem Wert, den Sie brauchen. Steht er dort, laden Sie die Seite mit
XMLHTTPherunter und lesen sie mit einemhtmlfile-Dokument. Steht er dort nicht, lädt die Seite ihre Daten über eine JSON-Anfrage, und diese Anfrage direkt aufzurufen ist einfacher und stabiler als jedes Scraping. Die Automatisierung von Internet Explorer ist keine Option mehr.
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"
Dies ist der dritte Artikel einer Reihe darüber, Daten aus dem Web nach Excel zu holen: VBA HTTP Request behandelt die Anfrage, VBA JSON die strukturierte Antwort und dieser Artikel Seiten, die für Menschen statt für Code geschrieben wurden. Die Idee der Reihe: Eine Web-Anfrage liefert Ihnen Text, keine Daten. Zwischen dem Server und Ihren Zellen liegen drei Übersetzungen, für die Sie verantwortlich sind: Bytes zu Text, Text zu Struktur, Struktur zu Raster. Scraping ist die Variante, bei der die Struktur nie für Sie gedacht war.
Was Sie lernen
- Das mentale Modell: das HTML, das der Server gesendet hat
- Der Zehn-Sekunden-Test: Seitenquelltext anzeigen
- Wenn die Daten nicht im Quelltext stehen: das JSON finden
- Warum nicht Internet Explorer oder Selenium
- Eine HTML-Tabelle mit htmlfile lesen
- Ausgelesene Zahlen sind Text
- Verstümmelter Text durch ein meta charset
- Power Query und höfliches Scraping
Das mentale Modell: das HTML, das der Server gesendet hat
Ein Browser macht mit einer Seite zwei Dinge. Er lädt das HTML herunter, und dann führt er das JavaScript der Seite aus, das oft weitere Daten abruft und Tabellen, Preise und Listen auf dem Bildschirm aufbaut. Was Sie sehen, ist das Ergebnis beider Schritte. Was VBA mit einer HTTP-Anfrage herunterlädt, ist nur der erste Schritt: das HTML, so wie der Server es gesendet hat.
Deshalb lautet die häufigste Scraping-Beschwerde: „Mein Code findet keine Tabelle, aber ich sehe die Tabelle doch.“ Beide Aussagen stimmen. Die Tabelle existiert in der lebendigen Seite des Browsers, nicht im HTML, das der Server gesendet hat. Kein Selektor, kein Warten und kein erneuter Versuch ändert daran etwas, denn die Daten waren nie in dem, was Sie heruntergeladen haben.
Der Zehn-Sekunden-Test: Seitenquelltext anzeigen
Bevor Sie Code schreiben, öffnen Sie die Seite in einem Browser und drücken Strg+U (Seitenquelltext anzeigen). Das zeigt das HTML so, wie der Server es gesendet hat, also genau das, was VBA erhalten wird. Durchsuchen Sie es (Strg+F) nach einem Wert, den Sie auf der Seite sehen, etwa einem Preis oder einem Namen.
- Gefunden: Die Daten stehen im HTML des Servers. Lesen Sie sie mit
XMLHTTPundhtmlfileaus, siehe unten. - Nicht gefunden: JavaScript lädt sie. Weiter mit dem nächsten Abschnitt.
Verwenden Sie für diesen Test nicht Untersuchen (F12, Elemente). Untersuchen zeigt die lebendige Seite, nachdem JavaScript gelaufen ist, und zeigt die Daten deshalb in beiden Fällen.
Wenn die Daten nicht im Quelltext stehen: das JSON finden
Eine Seite, die ihre Tabelle mit JavaScript aufbaut, muss die Daten irgendwoher bekommen, fast immer über eine JSON-Anfrage an dieselbe Website. So finden Sie sie:
- Öffnen Sie die Entwicklertools des Browsers (F12) und wechseln Sie zum Tab Netzwerk.
- Filtern Sie nach Fetch/XHR und laden Sie die Seite neu.
- Klicken Sie die Anfragen an und sehen Sie sich jeweils die Antwort an. Eine davon enthält Ihre Daten als JSON.
- Kopieren Sie deren URL und rufen Sie sie aus VBA auf, wie in VBA HTTP Request gezeigt, und parsen Sie sie dann mit VBA JSON.
Dieser Weg ist besser als Scraping, selbst wenn Scraping funktionieren würde. Das JSON hat Feldnamen statt Tabellenpositionen, Zahlen ohne Währungssymbole, und es ändert sich seltener als das Seitendesign. Prüfen Sie die Nutzungsbedingungen der Website, bevor Sie darauf aufbauen; ein undokumentierter Endpunkt kann sich außerdem ohne Vorankündigung ändern.
Warum nicht Internet Explorer oder Selenium
Ältere Tutorials steuern aus VBA einen Browser mit CreateObject("InternetExplorer.Application"). Internet
Explorer wurde im Juni 2022 eingestellt; er wird nicht mehr unterstützt, und moderne Websites funktionieren darin
immer öfter nicht. Beginnen Sie darauf keine neue Arbeit, und planen Sie, Makros zu ersetzen, die davon abhängen.
Selenium Basic, der übliche Ersatz für VBA, hat seit 2016 kein Release mehr bekommen und braucht einen Browsertreiber, der zur installierten Chrome- oder Edge-Version passt; jedes Browser-Update kann das Makro auf dem Rechner des Benutzers kaputtmachen. Für eine Seite, die nur mit JavaScript funktioniert und keine Datenanfrage hat, die Sie aufrufen können, kann es trotzdem das richtige Werkzeug sein, aber betrachten Sie es als letzten Ausweg, nicht als Standard.
Eine HTML-Tabelle mit htmlfile lesen
Für Daten, die im HTML des Servers stehen, brauchen Sie keinen Browser. Laden Sie die Seite herunter und in ein
htmlfile-Objekt, das Ihnen ein Dokument liefert, das Sie wie eine Webseite durchsuchen können:
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
Drei Details sind wichtig. Die Auflistungen aus dem HTML-Dokument (Rows, Cells, getElementsByTagName)
beginnen bei 0, anders als das meiste in Excel. Zeilen können unterschiedlich viele Zellen haben, also
bemessen Sie das Array nach der breitesten Zeile. Und die ganze Tabelle wird in einem Schritt ins Blatt
geschrieben.
Um ein bestimmtes Element zu finden, verlassen Sie sich auf getElementById und getElementsByTagName. Je nach
Windows- und Office-Build kann ein spät gebundenes htmlfile-Dokument in einem alten Kompatibilitätsmodus laufen,
in dem neuere Methoden wie querySelector und getElementsByClassName fehlen; Code, der darauf aufbaut,
funktioniert dann auf dem einen Rechner und auf dem anderen nicht. Um nach Klasse zu filtern, durchlaufen Sie die
Tags und prüfen .className.
„Die erste Tabelle“ auszuwählen ist die schwächste Stelle jedes Scrapers. Bei einem Redesign kommt über Ihrer
Tabelle eine weitere hinzu, und das Makro liest stillschweigend die falsche. Hat die Tabelle eine id, verwenden
Sie sie; andernfalls prüfen Sie den Text einer Kopfzelle, bevor Sie der Tabelle vertrauen.
Ausgelesene Zahlen sind Text
Alles, was Sie mit innerText von einer Seite holen, ist ein String, formatiert für die Leute, die diese Website
lesen: 1.234,56 € auf einer deutschen Seite, 1 234,56 € auf einer französischen, $1,234.56 auf einer
amerikanischen. Als Text in eine Zelle geschrieben, lässt es sich nicht summieren. Mit CDbl oder Val
umgewandelt, ergibt es je nach den Regionaleinstellungen des Benutzers eine falsche Zahl oder einen Fehler.
Wandeln Sie nach dem Format der Website um, nicht nach dem des Benutzers. Entfernen Sie die Währung und das
Tausendertrennzeichen, machen Sie dann das Dezimaltrennzeichen zu einem Punkt und verwenden Sie Val:
Function ParseScraped(ByVal s As String, ByVal thousandsSep As String, ByVal decimalSep As String) As Variant
s = Replace(s, ChrW(160), "") ' geschuetztes Leerzeichen
s = Replace(s, ChrW(8239), "") ' schmales geschuetztes Leerzeichen
s = Replace(s, " ", "")
s = Replace(s, ChrW(8364), ""): s = Replace(s, "$", "") ' Eurozeichen
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" von einer deutschen Seite -> 1234.56
Die beiden geschützten Leerzeichen sind die versteckte Falle. Französische und andere europäische Websites
trennen Tausender oft damit, sie sehen genau wie ein Leerzeichen aus, und Trim entfernt sie nicht. Dasselbe
Zeichen in eingefügten Daten behandelt VBA Trim.
Verstümmelter Text durch ein meta charset
responseText dekodiert die Seite mit dem Zeichensatz aus dem HTTP-Header des Servers. Viele ältere Websites
geben ihre Kodierung nur innerhalb des HTML an, mit einem <meta charset>-Tag, und XMLHTTP liest dieses Tag
nicht. Die Seite sieht im Browser gut aus und kommt in VBA mit é statt é an oder mit Kästchen statt
japanischem Text.
Enthält der Quelltext ein Tag <meta charset="windows-1252"> oder <meta charset="shift_jis"> und ist der Text
verstümmelt, dekodieren Sie http.responseBody mit diesem Zeichensatz, mit der ADODB.Stream-Funktion aus
VBA HTTP Request, und übergeben das Ergebnis an doc.body.innerHTML.
Power Query und höfliches Scraping
Für eine statische HTML-Tabelle, die Sie aktualisieren wollen, hat Excel bereits einen Scraper eingebaut: Daten > Aus dem Web (Power Query) listet die Tabellen einer Seite auf, lädt die gewählte und aktualisiert sie per Klick, ohne VBA. Es hat dieselbe Grenze, denn es liest ebenfalls das HTML des Servers, aber wenn es funktioniert, müssen Sie weniger Code pflegen. Nehmen Sie VBA, wenn Sie Logik brauchen: eine Liste von URLs, eine Anmeldung oder das Zusammenführen von Seiten.
Und scrapen Sie höflich. Eine Anfrage pro Seite, eine Pause zwischen den Seiten (siehe VBA Wait), nichts erneut herunterladen, was Sie schon haben, und vorher ein Blick in die Nutzungsbedingungen und die robots.txt der Website. Ein Makro, das hundert Anfragen pro Sekunde abfeuert, sorgt dafür, dass die IP-Adresse Ihres Büros gesperrt wird, und dann funktioniert niemandes Makro mehr.
Die Abwägung: Scraping ist ein Vertrag, den niemand unterschrieben hat
Eine API ist ein Versprechen: Der Anbieter dokumentiert sie und bemüht sich, sie nicht zu brechen. Eine Webseite verspricht nichts. Der Designer kann morgen eine Tabelle hinzufügen, eine Klasse umbenennen oder die Preise in JavaScript verlagern, und Ihr Makro bricht ohne Fehlermeldung, oder schlimmer, es liest die falsche Spalte.
Wählen Sie also die stabilste verfügbare Quelle: zuerst eine offizielle API, dann die JSON-Anfrage hinter der Seite, dann Power Query auf einer statischen Tabelle, dann XMLHTTP mit htmlfile und die Browser-Automatisierung zuletzt. Was auch immer Sie wählen: Lassen Sie den Scraper prüfen, was er gefunden hat (einen Kopfzeilentext, eine Zeilenanzahl), bevor er schreibt, damit ein Redesign einen Fehler erzeugt statt falscher Zahlen.
Wie ExcelMaster hilft
Scraper gehen leise kaputt: Das Layout ändert sich, die Zahlen kommen im Format eines anderen Landes zurück, der Text kommt verstümmelt an.
ExcelMaster prüft, was der Server tatsächlich zurückgibt, bevor es den Code schreibt, sucht bei JavaScript-Seiten nach der Datenanfrage dahinter und wandelt ausgelesene Zahlen nach dem Format der Website um, damit sie als echte Zahlen in Ihrem Blatt ankommen.
Häufig gestellte Fragen
Wie lese ich mit VBA eine Website in Excel aus?
Laden Sie die Seite mit MSXML2.XMLHTTP.6.0 herunter, laden Sie responseText in
CreateObject("htmlfile"), finden Sie die Tabelle mit getElementsByTagName("table"), lesen Sie das
innerText jeder Zelle in ein Array und schreiben Sie das Array ins Blatt.
Warum findet mein VBA-Scraper Daten nicht, die ich auf der Seite sehe?
Die Seite baut diese Daten nach dem Laden mit JavaScript auf, also stehen sie nicht in dem HTML, das VBA herunterlädt. Suchen Sie die JSON-Anfrage im Tab Netzwerk des Browsers und rufen Sie sie direkt auf.
Kann ich für Web Scraping in VBA noch Internet Explorer verwenden?
Das ist nicht zu empfehlen. Internet Explorer wurde im Juni 2022 eingestellt und wird nicht mehr unterstützt.
Verwenden Sie XMLHTTP mit htmlfile für statische Seiten und die JSON-Anfrage der Seite für dynamische.
Warum sind ausgelesene Zahlen in Excel keine Zahlen?
innerText liefert immer Text, formatiert für das Land der Website. Entfernen Sie Währungssymbole und
Tausendertrennzeichen, einschließlich geschützter Leerzeichen, ändern Sie das Dezimaltrennzeichen in einen Punkt
und wandeln Sie mit Val um.
Ist Power Query für Web Scraping besser als VBA?
Für eine statische Tabelle, die Sie aktualisieren wollen, ja: Daten > Aus dem Web braucht keinen Code. Nehmen Sie VBA, wenn Sie viele Seiten durchlaufen, sich anmelden oder zwischen den Anfragen Logik anwenden müssen.
Getestet in
Getestet in: Excel 365 (Windows 11), VBA 7.1 — zuletzt geprüft am 05.10.2026.
Verwandte Anleitungen: VBA HTTP Request · VBA JSON · VBA Trim · VBA Wait · VBA 2D-Array · VBA Replace · VBA Like · VBA CreateObject
