Öffnen Sie eine moderne Webseite, beobachten Sie die Netzwerkaktivität, und Sie werden oft sehen, dass die gewünschten Daten als JSON eintreffen, bevor die Seite sie darstellt. Die Preise, Angebote oder Ergebnisse, die ein Scraper mühsam aus HTML extrahieren müsste, liegen bereits in einer sauberen, strukturierten Antwort vor, die sich die Seite selbst geholt hat.
Aus dieser Antwort statt aus der gerenderten Seite zu sammeln, kann kleiner, stabiler und deutlich leichter zu parsen sein. Doch es ist nicht so einfach wie das Kopieren einer URL, und zwei Dinge überraschen die meisten Teams: wie wenig vom JSON einer Seite tatsächlich die Daten sind, und wie oft der Daten-Endpunkt außerhalb der aufrufenden Seite den Dienst verweigert. Dieser Leitfaden zeigt, wie man den richtigen Endpunkt findet, was wir auf echten Seiten gemessen haben, und wie man von dort sammelt, ohne dabei zu weit zu gehen.
Die wichtigsten Erkenntnisse
- Das meiste JSON, das eine Seite lädt, sind keine Daten. Auf der Flugsuche-Seite einer Fluggesellschaft kamen die Tarife in einer einzigen 44,9 KB großen Antwort, etwa 8% des JSON der Seite und etwa 1,2% ihrer gesamten Übertragung von 3,6 MB.
- Manche Seiten haben überhaupt keine Daten-API. Auf der Vorhersageseite eines nationalen Wetterdienstes gehörte jede JSON-Antwort zum Cookie-Consent-Tool, und die Vorhersage steckte im HTML.
- Finden Sie den Endpunkt, indem Sie Antwortkörper nach einem auf der Seite sichtbaren Wert durchsuchen, nicht indem Sie anhand von URLs raten.
- Seiten-APIs sind oft an die Sitzung der Seite gebunden. Der Tarif-Endpunkt der Fluggesellschaft funktionierte innerhalb der Seite und lieferte bei direktem Aufruf einen HTTP 409.
- Verwenden Sie nur öffentliche Endpunkte, die die Seite für anonyme Besucher aufruft, in dem Tempo, in dem eine Person browsen würde, und bevorzugen Sie wo immer möglich eine offizielle API.
Was wir gemessen haben
Wir haben am 30. September 2026 zwei öffentliche Seiten in einem echten Browser geladen und jede Antwort aufgezeichnet.
| Flugsuche einer Fluggesellschaft | Wettervorhersage | |
|---|---|---|
| Anfragen | 61 | 46 |
| Gesamt übertragen | 3,62 MB | 2,57 MB |
| JSON-Antworten | 15, 534 KB | 3, 1,04 MB |
| JSON-Antworten mit den Daten | 1, 44,9 KB | 0 |
| Wo die Daten lagen | Ein Tarif-Endpunkt | Das server-gerenderte HTML |
Auf der Seite der Fluggesellschaft waren die größten JSON-Antworten überhaupt keine Tarife. Ein Feature-Flag-Dienst eines Drittanbieters lieferte viermal dieselbe 97 KB große Antwort, und ein Übersetzungsbündel fügte weitere 92 KB hinzu. Die Tarife kamen in einer einzigen Antwort von der eigenen Buchungs-API der Fluggesellschaft.
Auf der Wetterseite stammten alle drei JSON-Antworten vom Consent-Management-Tool, eine davon eine 860 KB große Anbieterliste, während die Vorhersage selbst server-seitig ins HTML gerendert wurde. „Aus dem JSON sammeln” hätte hier nichts Brauchbares eingebracht.
Den Endpunkt finden, der die Daten trägt
Die verlässliche Methode ist Suchen, nicht Raten. Wählen Sie einen auf der Seite sichtbaren Wert, etwa einen Preis, einen Produktnamen oder eine Kennung, laden Sie die Seite in einem echten Browser und finden Sie heraus, welche JSON-Antwort diesen Wert enthält.
Von Hand geschieht dies über die Entwicklertools des Browsers: Öffnen Sie den Network-Tab, filtern Sie auf Fetch/XHR, laden Sie neu und durchsuchen Sie die Antwortkörper nach dem Wert. Automatisiert ist es ein kurzes Skript:
import { chromium } from 'playwright';
// Load a page once and report which JSON responses contain a value you can see on it.
export async function findEndpoint(url, needle, waitMs = 20000) {
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();
const hits = [];
page.on('response', async (response) => {
const type = response.request().resourceType();
const contentType = response.headers()['content-type'] || '';
if (!['xhr', 'fetch'].includes(type) || !contentType.includes('json')) return;
try {
const body = await response.text();
if (body.includes(needle)) {
hits.push({
method: response.request().method(),
status: response.status(),
bytes: Buffer.byteLength(body),
url: response.url(),
});
}
} catch {
// Some responses (redirects, aborted requests) have no readable body.
}
});
// Analytics beacons keep many pages from ever going network-idle,
// so wait for the DOM, then until a match appears or the time runs out.
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 90000 });
for (let waited = 0; waited < waitMs && hits.length === 0; waited += 500) {
await page.waitForTimeout(500);
}
await page.waitForTimeout(1000);
await browser.close();
return hits;
}
Bei der Flugseite der Fluggesellschaft und einem darauf sichtbaren Tarif lieferte das Skript genau eine Übereinstimmung von 61 Anfragen: die Verfügbarkeitsantwort der Buchungs-API. Beachten Sie die Wartestrategie. Unsere erste Version wartete darauf, dass die Seite in den Netzwerk-Leerlauf übergeht, was nie geschah, weil Analytics-Beacons ständig feuerten; sie lief nach 90 Sekunden in ein Timeout. Auf das DOM und dann auf eine Übereinstimmung zu warten, ist verlässlicher.
Kann man ihn direkt aufrufen?
Oft nicht. Als wir denselben Verfügbarkeits-Endpunkt der Fluggesellschaft direkt anfragten, ohne die Seite, lieferte er für Anfragen aus sechs verschiedenen Ländern gleichermaßen HTTP 409, während die Seite selbst ihn problemlos lud. Seiten-APIs hängen häufig von Dingen ab, die die Seite zuvor einrichtet: Sitzungs-Cookies, in das HTML eingebettete Token, Anfrage-Header oder eine Abfolge vorheriger Aufrufe.
Damit bleiben zwei Ansätze:
- Die Seite den Aufruf machen lassen. Laden Sie die Seite in einem Browser und lesen Sie die JSON-Antwort bei ihrem Eintreffen, wie es das obige Skript tut. Sie erhalten die sauberen Daten, ohne die Sitzung nachzubauen, auf Kosten des Betriebs eines Browsers.
- Nur einfache, öffentliche Endpunkte nachbilden. Manche Endpunkte benötigen nichts außer einer URL. Dieselbe Fluggesellschaft veröffentlicht auch einen öffentlichen Tarif-Endpunkt, der einfache Anfragen beantwortet, den wir in einem separaten Test darüber verwendet haben, ob sich Preise nach Ausreiseland unterscheiden. Wo ein Endpunkt so einfach funktioniert, ist er mit Abstand die günstigste Option.
Was man nicht tun sollte, ist die Sitzung zu umgehen: Token abgreifen, Header fälschen oder authentifizierte Aufrufe wiederholen, um an Daten zu gelangen, die die Seite anonymen Besuchern nicht zur Verfügung gestellt hat. Dort hört Sammeln auf, Beobachtung zu sein.
Warum sich JSON lohnt, wenn es vorhanden ist
Wenn die Daten tatsächlich als JSON eintreffen, sind die Vorteile real:
- Größe. Die Tarifantwort war 44,9 KB gegenüber 3,6 MB für die gesamte Seite. Bei bandbreitenabgerechnetem Sammeln macht dieser Unterschied den Großteil der Rechnung aus, wie Kosten pro sauberem Datensatz zeigt.
- Struktur. Felder kommen benannt und typisiert an, ohne Selektoren zu schreiben oder zu pflegen.
- Vollständigkeit. Antworten tragen oft mehr, als die Seite anzeigt, etwa Kennungen, alle Tarifklassen oder Bestandsmarkierungen.
Die Kompromisse sind ebenso real. Undokumentierte Endpunkte ändern sich ohne Vorwarnung, und eine Antwort, die ihre Form ändert, bricht Ihren Parser lautlos, was genau das Problem ist, für das die Überwachung von Schema Drift existiert. Eine Versionsnummer im Pfad, wie das v4 in der Buchungs-API der Fluggesellschaft, ist ein schwaches Signal für Stabilität, kein Versprechen.
Wo sich das unter den Alternativen einordnet
| Quelle | Stabilität | Aufwand | Verwenden wenn |
|---|---|---|---|
| Offizielle, dokumentierte API | Höchste | Geringste | Immer zuerst prüfen |
| JSON-LD oder eingebetteter Seitenzustand | Hoch | Gering | Die Seite veröffentlicht es, siehe HTML-Parsing überspringen |
| Die eigenen JSON-Endpunkte der Seite | Mittel | Mittel | Daten laden nach der Seite, und der Endpunkt ist öffentlich |
| Gerendertes HTML und Selektoren | Niedrigste | Höchste | Nichts anderes trägt die Daten |
| Ein Modell, das die Seite liest | Unterschiedlich | Gering pro Seite, hoch pro Seitenaufruf | Viele Vorlagen, wie in LLM-Extraktion vs. Selektoren |
Verantwortungsvoll sammeln
Die Endpunkte, die eine Seite aufruft, sind Teil der Website, und die Regeln der Website gelten weiterhin. Verwenden Sie nur Endpunkte, die die Seite für anonyme Besucher aufruft, halten Sie das Tempo so, wie es eine browsende Person tun würde, respektieren Sie robots.txt und die Nutzungsbedingungen der Website, und lassen Sie alles hinter einem Login oder Token in Ruhe, sofern Sie keine Erlaubnis haben. Wo eine Website eine offizielle API anbietet, nutzen Sie diese; sie ist stabiler, und es ist das, was die Website zu unterstützen zugesagt hat. Die weiter gefassten Prinzipien finden sich in robots.txt, KI-Opt-outs und Reservierungssignale.
Fazit
Die Daten hinter einer modernen Seite kommen oft als JSON an, und wenn das der Fall ist, ist das Sammeln dort kleiner, sauberer und leichter zu pflegen als das Parsen von HTML. Doch es zu finden erfordert eine Suche, kein Raten: Auf den von uns gemessenen Seiten war das nützliche JSON eine Antwort unter vielen, und auf einer Seite existierte es überhaupt nicht.
Durchsuchen Sie Antwortkörper nach einem sichtbaren Wert, prüfen Sie, ob der Endpunkt eigenständig funktioniert, lassen Sie die Seite den Aufruf machen, wenn das nicht der Fall ist, und bleiben Sie innerhalb dessen, was die Website jedem anonymen Besucher anbietet.
Quellen und Verweise
- Seiten geladen und gemessen von Shifter am 30. September 2026, mit dem obigen Code.
- Playwright, Dokumentation zu Network-Events.