---
title: "Web Scraping vs. API: Welche Methode sollten Sie nutzen?"
description: "Eine API liefert, was ein Anbieter freigibt, in festem Format; Web Scraping liest die Seite selbst. Wir vergleichen beide und holen dieselben Daten zweimal."
url: https://proxynet.io/de/blog/web-scraping-vs-api
date: 2026-09-29
author: "Acar Diveroli"
category: "Vergleich, Web Scraping"
lang: de
---

# Web Scraping vs. API: Welche Methode sollten Sie nutzen?

Sie brauchen jeden Morgen dieselbe Liste: offene Issues aus einem GitHub-Repository, Preise von der Kategorieseite eines Shops, Zitate von einer Website. GitHub dokumentiert für seine Issues eine API, also kann ein Skript sie abfragen und bekommt JSON zurück. Der Shop bietet vielleicht nur seine Seiten an; dann muss das Skript das HTML herunterladen und die Preise daraus herauslesen. Das ist der ganze Unterschied zwischen einer API und Web Scraping, und in den meisten Projekten entscheidet nicht der Geschmack, sondern das, was die Gegenseite anbietet.

Dieser Beitrag erklärt, was eine API und was Scraping ist, vergleicht beide in zehn Punkten und sammelt dann dieselben 100 Datensätze in Python auf beiden Wegen: einmal aus HTML-Seiten und einmal aus dem JSON-Endpunkt, den die Seite der Website selbst aufruft. Danach geht es um versteckte JSON-Endpunkte, Scraping-API-Dienste, Rate Limits, IP-Whitelists, die Kosten beider Wege und die Frage, wann man sie kombiniert. Jedes Codebeispiel lief am 29. September 2026 mit Python 3.13, Requests 2.34.2 und beautifulsoup4 4.15.0.

> **Hinweis: Kurzantwort**
>
> Nutzen Sie eine offizielle API, wenn es eine gibt und sie die Felder liefert, die Sie brauchen: Die Daten kommen strukturiert in einem versionierten Format, und die Limits sind schriftlich festgehalten. Scrapen Sie, wenn es keine API gibt, wenn die API Felder auslässt, die die Seite zeigt, oder wenn ihr Kontingent oder Preis nicht zur Aufgabe passt. Dazwischen liegt der JSON-Endpunkt, den die Seiten einer Website selbst aufrufen. Er ist leichter als HTML, aber niemand hat versprochen, ihn beizubehalten; die Nutzungsbedingungen der Website und ein zurückhaltendes Anfragetempo gelten also weiterhin. Viele Projekte nutzen beides: die API für die Kerndaten und Scraping für das, was die API nicht liefert.

## Was ist eine API?

Eine API (Application Programming Interface, Programmierschnittstelle) ist eine Reihe fester Anfragen, die ein Programm an ein anderes senden kann, zusammen mit den Regeln dafür, was man sendet und was zurückkommt. Im Web bedeutet das meist eine HTTP-Anfrage an eine Adresse wie `https://api.github.com/repos/python/cpython/issues` und eine Antwort in JSON. Eine Webseite ist geschrieben, damit ein Mensch sie liest; eine API-Antwort, damit ein Programm sie parst.

Eine Web-API besteht aus einigen Teilen:

- **Endpunkt (Endpoint):** die Adresse einer einzelnen Operation, etwa „Issues auflisten“ oder „ein Produkt abrufen“.
- **Parameter:** was Sie anfordern, zum Beispiel `state=open` oder `page=2`.
- **Authentifizierung:** ein API-Schlüssel, ein Token oder OAuth, woran der Dienst erkennt, wer anfragt. Viele APIs beantworten auch anonyme Aufrufe, dann mit einem niedrigeren Limit.
- **Antwortformat:** meist JSON, mit Feldnamen, die von Aufruf zu Aufruf gleich bleiben.
- **Limits und Bedingungen:** wie viele Aufrufe Sie pro Stunde machen dürfen und was Sie mit den Daten tun dürfen.
- **Dokumentation:** Viele APIs veröffentlichen eine maschinenlesbare Beschreibung im OpenAPI-Format. Die [OpenAPI Specification](https://spec.openapis.org/oas/latest.html), seit dem 10. September 2026 in Version 3.2.1, beschreibt sich selbst als standardisierte, sprachunabhängige Schnittstellenbeschreibung für HTTP-APIs, damit Menschen und Werkzeuge erkennen können, was ein Dienst bietet, ohne seinen Quellcode zu lesen.

Nicht jede API steht allen offen. Banken, Börsen und viele Business-Dienste vergeben Schlüssel nur an Kontoinhaber, und manche nehmen Aufrufe nur von vorher registrierten IP-Adressen an; darauf kommen wir weiter unten zurück.

## Was ist Web Scraping?

Beim Web Scraping tut ein Programm das, was Ihr Browser tut, und behält danach nur die Daten: Es lädt die Seite herunter, liest das HTML und wählt Werte mit CSS-Selektoren oder XPath aus. Die Website hat keiner Sache zugestimmt. Das Layout der Seite ist der einzige „Vertrag“, und die Website kann es jeden Tag aus eigenen Gründen ändern. [Was ist Web Scraping und wie funktioniert es?](/de/blog/what-is-web-scraping) führt durch die ganze Pipeline, und den Unterschied zwischen dem Verfolgen von Links und dem Extrahieren von Feldern behandelt [Web Scraping vs. Web Crawling](/de/blog/web-scraping-vs-web-crawling).

Die Stärke von Scraping ist die Reichweite: Alles, was ein Besucher ohne Anmeldung sehen kann, ist erreichbar. Der Preis dafür ist, dass jeder Wert in einem Markup wiedergefunden werden muss, das für das Design gebaut wurde, nicht für Daten.

## Wie kommen die beiden Wege an die Daten?

Aus der Ferne sehen die Schritte ähnlich aus. Der Unterschied liegt darin, wer die Form der Antwort bestimmt.

Mit einer API:

1. **Sie lesen die Dokumentation** und finden den Endpunkt, die Parameter und die Limits.
2. **Sie besorgen einen Schlüssel,** falls die API einen verlangt, und speichern ihn in einer Umgebungsvariablen statt im Code.
3. **Sie senden eine Anfrage** mit Parametern, zum Beispiel `?page=2`.
4. **Der Dienst liefert JSON** mit benannten Feldern und meist ein Feld oder einen Header, der auf die nächste Seite verweist.
5. **Sie lesen die Felder über ihren Namen.** Ein Redesign der Website berührt sie nicht.

Mit Scraping:

1. **Sie untersuchen die Seite** und das HTML dahinter, um herauszufinden, wo jeder Wert steht.
2. **Sie prüfen `robots.txt` und die Nutzungsbedingungen der Website** ([robots.txt richtig lesen](/de/blog/robots-txt)).
3. **Sie laden die Seite herunter,** wie ein Browser es täte, oder rendern sie in einem Headless-Browser, wenn JavaScript den Inhalt aufbaut.
4. **Sie parsen das HTML** und wählen jeden Wert mit einem Selektor wie `span.text` aus ([was Data Parsing ist](/de/blog/what-is-data-parsing)).
5. **Sie bereinigen und speichern die Werte** und wiederholen die Arbeit, wenn sich das Layout ändert.

## Web Scraping vs. API: Vergleichstabelle

| | Offizielle API | Eigener JSON-Endpunkt der Website | Web Scraping (HTML) |
|---|---|---|---|
| Datenumfang | Nur die Felder, die der Anbieter freigibt | Was die Seite braucht, um sich darzustellen | Alles, was ein Besucher sehen kann |
| Format | Dokumentiertes JSON oder XML | JSON, undokumentiert | HTML, das Sie parsen |
| Stabilität | Versioniert; Änderungen werden angekündigt | Kann sich mit jedem Frontend-Release ändern | Bricht, wenn sich das Layout ändert |
| Rate Limits | Veröffentlicht, oft in den Response-Headern | Nicht veröffentlicht; Sie bestimmen Ihr Tempo selbst | Nicht veröffentlicht; Sie bestimmen Ihr Tempo selbst |
| Authentifizierung | Schlüssel, Token oder OAuth; manchmal eine IP-Whitelist | Manchmal die Cookies oder Tokens einer Seitensitzung | Bei öffentlichen Seiten meist keine |
| Nutzungsbedingungen | Die API-Bedingungen legen fest, was erlaubt ist | Es gelten die Bedingungen der Website; keine Zusage der Website | Es gelten die Bedingungen der Website und robots.txt |
| Kosten | Kostenloses Kontingent oder bezahlter Tarif | Keine Gebühr; Ihre Zeit und Ihr Datenverkehr | Keine Gebühr; Entwicklung, Wartung, Proxys, Rendering |
| Wartung | Gering; Update, wenn eine Version ausläuft | Mittel; auf umbenannte Felder achten | Hoch; Selektoren versagen nach Redesigns |
| Größe einer Antwort | Klein, nur die Daten | Klein, nur die Daten | Ganze Seiten mit Layout und Markup |
| Per JavaScript erzeugte Inhalte | Kein Problem | Kein Problem | Braucht einen Headless-Browser oder den JSON-Weg |

Die REST-API von GitHub zeigt, was „versioniert“ in der Praxis bedeutet. Eine Anfrage kann ihre Version im Header `X-GitHub-Api-Version` angeben, und wenn eine neue Version erscheint, bleibt die vorherige noch mindestens 24 Monate lang unterstützt ([Versionen der GitHub-REST-API](https://docs.github.com/en/rest/about-the-rest-api/api-versions)). Ein Antwortfeld zu entfernen oder umzubenennen gilt dort als inkompatible Änderung (Breaking Change) und muss auf eine neue Version warten. Anfragen ohne den Header bekommen weiterhin die Version 2022-11-28, die bis zum 10. März 2028 unterstützt wird. Keine Website gibt ein solches Versprechen für ihre CSS-Klassen.

## Dieselben Daten auf beiden Wegen: ein getestetes Python-Beispiel

Die Übungsseite [quotes.toscrape.com](https://quotes.toscrape.com/) ist eine Sandbox für Scraping-Übungen; ihre Fußzeile nennt Zyte. Sie listet 100 Zitate auf zehn HTML-Seiten, `/page/1/` bis `/page/10/`. Ihre Version mit Endlos-Scrollen unter `/scroll` lädt dieselben Zitate von einem JSON-Endpunkt, `/api/quotes?page=N`, und jede Antwort enthält ein Feld `has_next`. Für `/robots.txt` liefert die Website 404, was nach dem robots.txt-Standard bedeutet, dass es keine Crawl-Regeln gibt; das Skript wartet trotzdem eine Sekunde zwischen den Seiten.

Das Skript sammelt alle 100 Zitate über beide Wege mit einer gemeinsamen Session. Jede Anfrage hat ein Timeout, die Session nennt sich im User-Agent beim Namen und wiederholt Anfragen bei `429`- und `5xx`-Antworten:

```python
"""Dieselben Zitate zweimal: aus den HTML-Seiten geparst und vom JSON-Endpunkt gelesen."""
import os
import time

import requests
from bs4 import BeautifulSoup
from requests.adapters import HTTPAdapter
from urllib3.util import Retry

BASE = "https://quotes.toscrape.com"
DELAY = 1.0  # Pause zwischen den Seiten

def make_session():
    retry = Retry(
        total=4,
        backoff_factor=1,  # wartet 0, 2, 4, 8 s zwischen den Versuchen
        status_forcelist=[429, 500, 502, 503, 504],
        allowed_methods=["GET"],
        respect_retry_after_header=True,  # ein Retry-After-Header ersetzt den Backoff
    )
    session = requests.Session()
    session.mount("https://", HTTPAdapter(max_retries=retry))
    session.mount("http://", HTTPAdapter(max_retries=retry))
    session.headers["User-Agent"] = "quotes-compare/1.0 (contact: you@example.com)"
    proxy = os.environ.get("PROXY_URL")  # z. B. http://user:pass@pr.proxynet.io:8000
    if proxy:
        session.proxies = {"http": proxy, "https": proxy}
    return session

def scrape_html(session):
    """Weg 1: jede HTML-Seite herunterladen und die Felder mit CSS-Selektoren herauslesen."""
    quotes, page, size = [], 1, 0
    while True:
        r = session.get(f"{BASE}/page/{page}/", timeout=(5, 20))
        r.raise_for_status()
        size += len(r.content)
        soup = BeautifulSoup(r.content, "lxml")
        for q in soup.select("div.quote"):
            quotes.append({
                "text": q.select_one("span.text").get_text(strip=True),
                "author": q.select_one("small.author").get_text(strip=True),
                "tags": [a.get_text(strip=True) for a in q.select("a.tag")],
            })
        if soup.select_one("li.next > a") is None:  # kein „Next“-Link: letzte Seite
            return quotes, page, size
        page += 1
        time.sleep(DELAY)

def fetch_api(session):
    """Weg 2: den JSON-Endpunkt aufrufen, den die Scroll-Seite der Website selbst nutzt."""
    quotes, page, size = [], 1, 0
    while True:
        r = session.get(f"{BASE}/api/quotes", params={"page": page}, timeout=(5, 20))
        r.raise_for_status()
        size += len(r.content)
        data = r.json()
        for q in data["quotes"]:
            quotes.append({
                "text": q["text"],
                "author": q["author"]["name"],
                "tags": q["tags"],
            })
        if not data["has_next"]:  # die API sagt, wann die Liste endet
            return quotes, page, size
        page += 1
        time.sleep(DELAY)

session = make_session()
results = {}
for name, collect in (("HTML", scrape_html), ("API", fetch_api)):
    quotes, pages, size = collect(session)
    results[name] = quotes
    print(f"{name}: {len(quotes)} quotes from {pages} pages, {size / 1024:.1f} KiB")

print("same data:", results["HTML"] == results["API"])
print(results["API"][0])
```

Die Ausgabe war identisch, ob wir das Skript direkt oder über einen lokalen Test-Proxy in `PROXY_URL` ausgeführt haben:

```text
HTML: 100 quotes from 10 pages, 106.1 KiB
API: 100 quotes from 10 pages, 30.2 KiB
same data: True
{'text': '“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”', 'author': 'Albert Einstein', 'tags': ['change', 'deep-thoughts', 'thinking', 'world']}
```

Die 100 Datensätze der beiden Wege stimmten Feld für Feld überein. Der HTML-Weg lud dafür 106,1 KiB herunter, der JSON-Weg 30,2 KiB, jeweils nach der Dekomprimierung gezählt; die HTML-Seiten tragen zusätzlich das Layout, die Navigation, die Tag-Seitenleiste und das Markup um jeden Wert. Über den Proxy schickte die eine `Session` alle 20 Anfragen durch einen einzigen Proxy-Tunnel.

Die beiden Schleifen erkennen ihr Ende an verschiedenen Stellen. Der HTML-Weg stoppt, wenn die Seite keinen „Next“-Link hat, während die API es ausdrücklich mit `has_next: false` mitteilt. Seiten hochzuzählen, bis ein Fehler kommt, würde auf dieser Website nicht funktionieren: `/page/11/` antwortet mit `200` ohne Zitate, und `/api/quotes?page=11` antwortet mit `200` und einer leeren Liste. Weitere Abbruchbedingungen behandelt [Was ist Paginierung und wie scrapen Sie alle Seiten?](/de/blog/pagination-web-scraping)

Die Wiederholungslogik dient beiden Wegen. Wir haben die Session auf einen lokalen Testserver gerichtet, der zweimal mit `429` und `Retry-After: 2` antwortete: Die Session wartete jedes Mal zwei Sekunden, lieferte die dritte Antwort nach 4,0 Sekunden, und der aufrufende Code sah nie eine 429. Gegen einen Server, der ohne diesen Header dauerhaft mit `503` antwortete, wartete sie 0, 2, 4 und 8 Sekunden und löste nach 14 Sekunden `requests.exceptions.RetryError` mit „too many 503 error responses“ aus. `allowed_methods=["GET"]` ist Absicht: [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-idempotent-methods) sagt, dass ein Client eine Anfrage mit einer nicht idempotenten Methode wie POST nicht automatisch wiederholen sollte.

### Felder, die nur einer der beiden Wege hat

Die beiden Wege liefern nicht genau dieselben Felder. Jeder API-Datensatz enthält den Goodreads-Link des Autors und einen Slug, die die Listenseite nicht zeigt:

```json
{
  "author": {
    "goodreads_link": "/author/show/9810.Albert_Einstein",
    "name": "Albert Einstein",
    "slug": "Albert-Einstein"
  },
  "tags": [
    "change",
    "deep-thoughts",
    "thinking",
    "world"
  ],
  "text": "“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”"
}
```

Die HTML-Listenseite verlinkt dafür jeden Autor auf eine „about“-Seite mit Geburtsdatum und Geburtsort („March 14, 1879“ und „in Ulm, Germany“ bei Einstein). Diese Seite hat kein JSON-Gegenstück: `/api/author/Albert-Einstein` liefert 404. In echten Projekten sieht es ähnlich aus. Die API enthält interne IDs und genaue Lagerbestände, die Seite dagegen die Texte, Badges und Preise, die Besucher tatsächlich sehen.

Auch eine API kann auf eine Weise scheitern, die aus Sicht des Codes seltsam wirkt. `/api/quotes?page=abc` liefert den Status `500` mit einer HTML-Fehlerseite, und der Aufruf von `.json()` auf diesem Body löst `JSONDecodeError: Expecting value: line 1 column 1 (char 0)` aus. Im obigen Skript fängt der Retry-Adapter die 500 zuerst ab und endet mit einem `RetryError`; ohne ihn stoppt `raise_for_status()` den Lauf, bevor `.json()` es tut. Die anderen Ursachen dieses Fehlers stehen in [JSONDecodeError: Expecting Value in Python beheben](/de/blog/jsondecodeerror-expecting-value).

## Versteckte JSON-Endpunkte: der Mittelweg

Viele Seiten, die wie reines HTML aussehen, laden ihre Daten im Hintergrund als JSON, genau wie die Seite `/scroll` oben `/api/quotes` aufruft. Diese Anfragen finden Sie in den Entwicklertools des Browsers: Öffnen Sie den Bereich **Netzwerk**, filtern Sie nach **Fetch/XHR**, laden Sie die Seite neu und suchen Sie nach Antworten, die Ihre Daten enthalten. Das vollständige Vorgehen steht in [Statische und dynamische Seiten beim Web Scraping](/de/blog/static-vs-dynamic-pages), und wie Sie eine kopierte Anfrage in Python umsetzen, zeigt [JSON mit Python Requests per POST senden](/de/blog/python-requests-post-json).

Ein solcher Endpunkt ist oft ein guter Kompromiss: strukturierte Daten zu einem Bruchteil der Seitengröße. Eine öffentliche API ist er trotzdem nicht, deshalb gelten ein paar Regeln:

- **Nur öffentliche Daten.** Funktioniert die Anfrage nur mit dem Session-Cookie Ihres Logins, sind die Daten nicht öffentlich, und ein zeitgesteuertes Skript, das mit Ihrem Cookie läuft, gefährdet Ihr eigenes Konto.
- **Keine Stabilitätszusage.** Feldnamen und Parameter können sich mit jedem Frontend-Release der Website ohne Ankündigung ändern. Prüfen Sie die Form der Antwort bei jedem Lauf und lassen Sie das Skript mit einer deutlichen Fehlermeldung abbrechen, wenn ein Schlüssel fehlt.
- **Gleiche Bedingungen, gleiches Tempo.** Die Nutzungsbedingungen der Website und `robots.txt` gelten für den Endpunkt genauso wie für ihre Seiten. JSON-Anfragen sind klein, deshalb ist es leicht, sie viel schneller zu senden, als ein Mensch es würde; behalten Sie die Pause bei.
- **Bei signierten Parametern aufhören.** Enthält die Anfrage eine Signatur oder ein kurzlebiges Token, das das Skript der Seite erzeugt, ist sie nicht zur Wiederverwendung gedacht. Suchen Sie nach einer offiziellen API oder kontaktieren Sie die Website.
- **Den dokumentierten Weg vorziehen.** Bietet die Website für dieselben Daten eine offizielle API an, nutzen Sie diese.

Die rechtliche Seite beim Sammeln öffentlicher Daten, die von Land zu Land verschieden ist, behandelt [Ist Web Scraping legal?](/de/blog/is-data-web-scraping-legal)

## Was ist eine Scraping-API?

„Scraping-API“ bezeichnet auch eine Art kommerziellen Dienst, und das ist etwas anderes als die eigene API einer Website. Sie schicken dem Dienst eine Ziel-URL; er lädt die Seite für Sie herunter, oft in einem Headless-Browser und über seinen eigenen Proxy-Pool, wiederholt fehlgeschlagene Anfragen und liefert das HTML oder daraus geparste Felder als JSON zurück. Sie rufen ihn wie eine API auf, doch die Daten stammen weiterhin aus dem Scraping der Zielseite.

Solche Dienste passen zu Teams, die Seiten von vielen Websites brauchen, ohne selbst Browser und Proxy-Rotation zu betreiben. Sie berechnen die Anfragen, die Sie über sie senden; verglichen wird also diese Rechnung mit den Kosten eines eigenen Scrapers. Wessen Regeln gelten, ändern sie nicht: Die Nutzungsbedingungen und `robots.txt` der Zielseite binden Sie weiterhin, und eine Scraping-API ist kein Grund, eine vorhandene offizielle API zu übergehen.

## Rate Limits, 429 und API-Schlüssel

Eine offizielle API nennt ihre Limits, oft in jeder Antwort. Die REST-API von GitHub erlaubt ohne Authentifizierung 60 Anfragen pro Stunde, gezählt pro Ursprungs-IP-Adresse, und 5.000 pro Stunde mit einem Personal Access Token ([Rate Limits der GitHub-REST-API](https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api)). Der Endpunkt `/rate_limit` zeigt Ihren Stand, und sein Aufruf zählt nicht gegen das primäre Limit:

```python
import requests

r = requests.get(
    "https://api.github.com/rate_limit",
    headers={"Accept": "application/vnd.github+json"},
    timeout=(5, 20),
)
core = r.json()["resources"]["core"]
print(r.status_code, "limit:", core["limit"], "remaining:", core["remaining"], "reset:", core["reset"])
print({k: v for k, v in r.headers.items() if k.lower().startswith("x-ratelimit")})
```

```text
200 limit: 60 remaining: 58 reset: 1790650244
{'X-RateLimit-Limit': '60', 'X-RateLimit-Remaining': '58', 'X-RateLimit-Used': '2', 'X-RateLimit-Resource': 'core', 'X-RateLimit-Reset': '1790650244'}
```

Der Reset-Wert ist ein Unix-Zeitstempel in UTC, in diesem Lauf 02:50:44 Uhr am 29. September 2026, und von unserer Adresse waren in dieser Stunde bereits zwei Anfragen gestellt worden. Ist das Limit aufgebraucht, antwortet GitHub mit `403` oder `429` und `x-ratelimit-remaining` bei 0, und Sie sollten bis zu der Zeit in `x-ratelimit-reset` warten. Bei seinen sekundären Limits sendet GitHub `retry-after`, wenn es kann, und bittet sonst darum, mindestens eine Minute zu warten.

Hier stößt eine allgemeine Wiederholungslogik an ihre Grenzen. Die Session in unserem Skript wiederholt bei `429`, aber nicht bei `403`, und 14 Sekunden Backoff nützen nichts gegen ein Fenster, das sich einmal pro Stunde zurücksetzt. Lesen Sie bei einer API die Header und warten Sie bis zum Reset.

Der Statuscode selbst stammt aus [RFC 6585](https://www.rfc-editor.org/rfc/rfc6585.html#section-4): `429 Too Many Requests` bedeutet, dass der Client in einem bestimmten Zeitraum zu viele Anfragen gesendet hat; die Antwort sollte den Zustand erklären und kann `Retry-After` enthalten. Der RFC lässt bewusst offen, wie ein Server den Client identifiziert und Anfragen zählt, ein Limit kann also pro IP, pro Schlüssel oder pro Konto gelten. RFC 9110 definiert `Retry-After` entweder als Datum oder als Anzahl von Sekunden, und urllib3 liest beide Formen. Eine Website, die Sie scrapen, veröffentlicht davon selten etwas; Sie bestimmen das Tempo also selbst und werden beim ersten 429 langsamer ([429 Too Many Requests erklärt](/de/blog/http-429-too-many-requests)).

## Warum verlangen manche APIs eine feste IP-Adresse?

Manche APIs prüfen nicht nur, welchen Schlüssel ein Aufruf trägt, sondern auch, woher er kommt. Börsen, Marktplätze, Banken und viele Business-Datendienste lassen Sie eine oder mehrere IP-Adressen für einen Schlüssel registrieren, und ein Aufruf von einer anderen Adresse wird selbst mit dem richtigen Schlüssel abgelehnt. Das scheitert, sobald das Skript irgendwo mit wechselnder Adresse läuft: an einem Heimanschluss, auf einem Laptop unterwegs, in einer Serverless-Funktion ohne feste ausgehende IP. Wie Sie Ihre ausgehende Adresse finden, und vier Wege, das Problem zu lösen, beschreibt [Statische IP für APIs](/de/blog/static-ip-for-api-access); den Fall der Börsen behandelt [Krypto-Börse: API-Schlüssel per IP-Whitelist absichern](/de/blog/crypto-exchange-api-ip-whitelist).

Bei Integrationen, die Zahlungen, Kartendaten oder Gesundheitsdaten übertragen, sollte die registrierte Adresse Ihr eigener Server oder Anschluss sein. Für Testumgebungen und Clients ohne sensible Daten erfüllt auch ein Proxy mit fester Adresse den Zweck: Ein [ISP-Proxy](https://proxynet.io/de/static-isp-residential-proxy) oder ein [Datacenter-Proxy](https://proxynet.io/de/datacenter-proxy) gibt Ihrem Skript eine ausgehende IP, die Sie einmal bei der API registrieren. Diese Produkte mit eigener IP werden standardmäßig mit einer Beschränkung auf eine Zielseite ausgeliefert; Sie nennen also bei der Bestellung den Host der API. Der Zugriff auf alle Websites ist ein kostenpflichtiges Add-on.

Beim Scraping ist der Bedarf umgekehrt: viele Seiten über längere Zeit, manchmal so, wie Besucher in einem anderen Land sie sehen. Dafür ist ein [Rotierender Proxy](https://proxynet.io/de/rotating-proxy) gedacht. Keine der beiden Proxy-Arten ändert die Regeln oben: Ein Proxy ändert die Adresse, nicht die Bedingungen der Website und nicht das Anfragetempo, an das Sie sich halten sollten.

## Was kostet welcher Ansatz?

**Eine offizielle API.** Der Preis steht auf der Preisseite des Anbieters. Manche APIs sind bis zu einem Kontingent kostenlos, manche kosten ab dem ersten Aufruf, und manche gibt es nur mit einem Geschäftsvertrag. Der Entwicklungsaufwand ist gering: Ein Client für eine dokumentierte JSON-API umfasst oft ein paar Dutzend Zeilen, wie oben. Die versteckten Kosten sind zum einen das Kontingent, denn ein Job, der mehr Aufrufe braucht, als der Tarif erlaubt, muss warten oder zahlen, und zum anderen die Kontrolle des Anbieters: Bedingungen, Preise und Zugang können sich ändern, und eine API kann abgeschaltet werden.

**Scraping.** Die Website verlangt keine Gebühr, aber alles andere liegt bei Ihnen: den Parser schreiben, ihn nach Redesigns reparieren, ein Headless-Browser, wenn JavaScript die Seite aufbaut (viel schwerer als eine einfache Anfrage; siehe den Kostenabschnitt in [Statische und dynamische Seiten beim Web Scraping](/de/blog/static-vs-dynamic-pages)), Proxys, wenn Volumen oder Land es verlangen, und ein Monitoring, das bemerkt, wenn ein Selektor still nichts mehr liefert. Auch die Datenmenge summiert sich. In unserem Test lud der HTML-Weg für dieselben Datensätze etwa 3,5-mal so viele Bytes herunter, und wenn Ihr Proxy-Tarif nach Datenverkehr abgerechnet wird, taucht dieses Verhältnis auf der Rechnung auf.

**Ein Scraping-API-Dienst.** Sie zahlen pro Anfrage und betreiben weder Browser noch Proxys. Liefert der Dienst rohes HTML, pflegen Sie das Parsing weiterhin selbst.

## Wann sollten Sie Scraping und API kombinieren?

Beides zusammen zu nutzen ist üblich und folgt meist einem von vier Mustern:

- **Die API für die Liste, die Seiten für die Details.** In unserem Beispiel würden Sie die 100 Zitate vom JSON-Endpunkt holen und jede der 50 Autorenseiten einmal für die Geburtsdaten besuchen.
- **Die API für Ihre eigenen Daten, die Seiten für die öffentliche Ansicht.** Eine Verkäufer-API liefert Ihre Angebote mit IDs und Bestand; die öffentliche Produktseite zeigt die Badges und Bewertungszahlen, die Kunden sehen. Führen Sie beides über die Produkt-ID zusammen.
- **Die API für den Datensatz, die Seite für ein Land.** Eine API liefert vielleicht einen einzigen Listenpreis, während ein Besucher in einem anderen Land auf der Seite eine lokale Währung, Steuern und eine Aktion sieht. Für diesen Vergleich muss die Seite aus diesem Land geladen werden.
- **Die Seite als Kontrolle der API.** Ein kleiner Scraper, der täglich ein paar Seiten stichprobenartig abruft, bestätigt, dass die Antworten der API noch zu dem passen, was Besucher sehen.

## Anwendungsfälle

- **Preis- und Bestandsüberwachung:** Ihre eigenen Angebote über die API der Plattform, die öffentlichen Seiten der Wettbewerber über einen Scraper ([Wettbewerberpreise überwachen](/de/blog/competitor-price-tracking)).
- **Repository-, Issue- und Release-Daten:** die API von GitHub mit Paginierung über den `Link`-Header ([Paginierung bei APIs](/de/blog/pagination-web-scraping)).
- **Börsendaten und Trading-Bots:** ein API-Schlüssel, der an eine registrierte Adresse gebunden ist ([IP-Whitelist für Börsen-APIs](/de/blog/crypto-exchange-api-ip-whitelist)).
- **Einmalig eine Tabelle in eine Tabellenkalkulation übernehmen:** eine Importfunktion oder ein paar Zeilen Python ([Daten von Websites extrahieren](/de/blog/extract-data-from-website)).
- **Die Ergebnisse aufbewahren:** dieselben Datensätze als CSV, JSON oder in SQLite gespeichert ([gescrapte Daten speichern](/de/blog/save-scraped-data-csv-json-sqlite)).
- **Jede Seite vor der Extraktion finden:** ein Crawler, der URLs auf der ganzen Website entdeckt ([Web-Crawler](/de/web-crawler)).
- **Große, geplante Datensammlung:** Warteschlangen, Tempokontrolle und Ausgänge in mehreren Ländern ([Data Scraping](/de/data-scraping)).

## Häufige Fehler

- **Eine Website scrapen, die für dieselben Daten eine API anbietet.** Sie übernehmen die Wartung ohne Not, und womöglich erlauben nur die Bedingungen der API automatisierten Zugriff.
- **Einen versteckten Endpunkt wie eine öffentliche API behandeln.** Er hat keine Version und keine Zusage; prüfen Sie die Form der Antwort bei jedem Lauf.
- **Eine Wiederholungsregel für jeden Fehler.** Kurzer Backoff passt zu einem kurzen `503`; ein stündliches Kontingent braucht `x-ratelimit-reset`, und ein `403` wird von der obigen Konfiguration gar nicht wiederholt.
- **POST-Anfragen automatisch wiederholen.** Eine Bestellung oder Nachricht kann doppelt gesendet werden; beschränken Sie automatische Wiederholungen auf GET.
- **`.json()` auf alles aufrufen, was zurückkommt.** Prüfen Sie zuerst den Statuscode und `Content-Type`; eine Fehlerseite ist HTML.
- **Seitennummern durchlaufen, bis etwas schiefgeht.** Auf der Übungsseite antwortete Seite 11 mit `200` und ohne Inhalt; folgen Sie `has_next` oder dem „Next“-Link.
- **Einen API-Schlüssel im Code aufbewahren.** Lesen Sie ihn aus einer Umgebungsvariablen und halten Sie ihn aus dem Repository heraus.
- **Der Website einen Proxy-Fehler anlasten.** Der Retry-Adapter wiederholt auch eine fehlgeschlagene Proxy-Anmeldung: Mit einem falschen Proxy-Passwort versuchte es unser Skript fünfmal in 14 Sekunden, bevor es `ProxyError` mit `407 Proxy Authentication Required` auslöste. Prüfen Sie zuerst die Zugangsdaten.

## Entscheidungshilfe

| Bedarf | Empfehlung |
|---|---|
| Die Website hat eine offizielle API mit den Feldern, die Sie brauchen | Die API nutzen; vorher Limits und Bedingungen lesen |
| Es gibt eine API, aber ihr fehlen einige Felder | API für die Kerndaten, Scraping für den Rest, über eine ID verknüpft |
| Keine API, und die Daten stehen im HTML | Requests und BeautifulSoup, mit einer Pause zwischen den Seiten |
| Keine API, und JavaScript lädt die Daten | Zuerst nach der JSON-Anfrage suchen; ein Headless-Browser nur, wenn sie sich nicht wiederverwenden lässt |
| Die API nimmt nur Aufrufe von registrierten IPs an | Eine feste ausgehende Adresse: Ihr eigener Server oder, für nicht sensible Clients, ein statischer ISP- oder Datacenter-Proxy |
| Das API-Kontingent ist jede Stunde aufgebraucht | Die Rate-Limit-Header lesen, die Aufrufe verteilen, eine höhere Stufe anfragen |
| Seiten von vielen Websites ohne eigene Infrastruktur | Ein Scraping-API-Dienst, sofern die Bedingungen der Zielseiten die Sammlung erlauben |
| Tausende Seiten pro Tag von Websites, die Sie geprüft haben | Ein eigener Scraper mit einem [Rotierender Proxy](https://proxynet.io/de/rotating-proxy) und einem Anfragebudget pro Website |

## Häufige Fragen

### Was ist der Unterschied zwischen Web Scraping und einer API?

Eine API ist ein Weg, den der Anbieter für Programme gebaut hat: Sie senden eine dokumentierte Anfrage und bekommen strukturierte Daten zurück, unter veröffentlichten Limits und Bedingungen. Web Scraping liest die Seiten, die für Menschen gebaut wurden, und holt die Werte aus dem HTML. Bei der API entscheidet der Anbieter, welche Felder Sie bekommen; Scraping erreicht alles Sichtbare, bricht aber, wenn sich die Seite ändert.

### Ist Web Scraping besser als eine API?

Nicht grundsätzlich. Liefert eine offizielle API die Felder, die Sie brauchen, ist ein Skript darauf schneller geschrieben und läuft auch nach Redesigns der Website weiter. Scraping ist die bessere Wahl, wenn es keine API gibt, wenn die API Daten auslässt, die die Seite zeigt, oder wenn ihr Kontingent oder Preis nicht zur Aufgabe passt.

### Hat jede Website eine API?

Nein. Viele Websites haben gar keine öffentliche API, und bei vielen deckt sie nur einen Teil der Daten ab oder verlangt ein Business-Konto. Manche Websites laden ihre Seiten aus internen JSON-Endpunkten; diese lassen sich für öffentliche Daten vorsichtig nutzen, sind aber keine veröffentlichte API.

### Ist es legal, die versteckte API einer Website zu nutzen?

Das hängt von den Daten ab, von den Nutzungsbedingungen der Website und vom Recht dort, wo Sie und die Website tätig sind. Öffentliche Daten von einem Endpunkt zu lesen, den die Seite selbst aufruft, ist technisch dasselbe wie das Lesen der Seite, und es gelten dieselben Bedingungen. Sich mit dem Konto einer anderen Person anzumelden, Zugriffskontrollen zu umgehen oder personenbezogene Daten zu sammeln, wirft andere Fragen auf. Den Überblick gibt [Ist Web Scraping legal?](/de/blog/is-data-web-scraping-legal)

### Ist eine Scraping-API dasselbe wie die API einer Website?

Nein. Die API einer Website wird von der Website selbst veröffentlicht und liefert deren Daten in einem festen Format. Eine Scraping-API ist ein Dienst eines Drittanbieters, der die Zielseite für Sie herunterlädt und das HTML oder geparste Felder zurückgibt. Die Daten stammen weiterhin von der Seite, und die Bedingungen der Zielseite gelten weiterhin.

### Brauche ich einen Proxy, um eine API aufzurufen?

Meist nicht. Sie brauchen einen, wenn die API nur Aufrufe von registrierten IP-Adressen annimmt und sich Ihre eigene Adresse ändert, oder wenn Sie eine API oder Seite so sehen müssen, wie sie aus einem anderen Land antwortet. Registrieren Sie für Zahlungen und andere sensible Integrationen stattdessen die Adresse Ihres eigenen Servers.

## Fazit

Eine API ist der Weg, den ein Anbieter für Programme gebaut hat, mit versioniertem Format und schriftlich festgelegten Limits. Scraping liest, was der Anbieter für Menschen gebaut hat; es erreicht alles Sichtbare und bricht, wenn sich die Seite ändert. Prüfen Sie zuerst, ob es eine offizielle API gibt, nutzen Sie vorsichtig den eigenen JSON-Endpunkt einer Website, wenn es keine gibt, und scrapen Sie das HTML für den Rest. Wenn eine API eine feste Adresse verlangt oder ein Scraping-Job Volumen über mehrere Länder braucht, vergleichen Sie unsere [Proxy-Tarife](/de/proxy).
