API-Endpunkt testen: DNS, TLS, Header & CORS
Kernaussage
„Die API ist down“ ist fast nie ein einzelnes Problem. Testen Sie in sechs Schichten (DNS, Port 443, TLS, HTTP-Status, CORS, Payload) und halten Sie bei der ersten fehlschlagenden an. Typische Ursachen sind ein DNS-Eintrag, der sich nie verbreitet hat, ein über Nacht abgelaufenes Zertifikat oder ein fehlender Access-Control-Allow-Origin-Header, der Browser-Aufrufe bricht, während curl problemlos funktioniert.
Jetzt prüfen

Jetzt lesen
- Warum „Die API ist down“ nie ein einzelnes Problem ist
- Einen echten Endpunkt wählen, den Sie beliebig oft aufrufen dürfen
- Schicht 1: Wird der Hostname aufgelöst?
- Schicht 2: Ist Port 443 offen?
- Schicht 3: Ist das TLS-Zertifikat gültig?
- Schicht 4: Die Antwort-Header lesen
- So sieht eine gesunde JSON-Antwort aus
- Schicht 5: Der Header, der nur Browser-Aufrufe bricht
- Die Preflight-Falle: Funktioniert, bis Sie einen Header hinzufügen
- Schicht 6: Hat die Payload die erwartete Form?
- Symptom → Schicht → Tool
- Häufig gestellte Fragen
Warum „Die API ist down“ nie ein einzelnes Problem ist
Wenn ein API-Aufruf fehlschlägt, wird der Fehler, den Ihr Client anzeigt, meist mehrere Schichten über dem erzeugt, was tatsächlich kaputt ist. Ein Browser, der Failed to fetch meldet, kann nicht sagen, ob der Hostname nicht aufgelöst wurde, die TCP-Verbindung abgelehnt wurde, der TLS-Handshake zurückgewiesen wurde oder der Server ein völlig gesundes 200 geliefert hat, das der Browser wegen eines fehlenden CORS-Headers verworfen hat. Alle vier erzeugen dieselbe Meldung.
Hören Sie auf zu raten und gehen Sie den Stack der Reihe nach durch. Jede Schicht ergibt nur Sinn, wenn die darunterliegende erfolgreich war. Die erste fehlschlagende Schicht ist also Ihr eigentlicher Fehler, alles danach ist Rauschen.
Es lohnt sich, sechs Schichten zu prüfen, und zusammen dauert das etwa zwei Minuten:
- DNS: Wird der Hostname überhaupt zu einer IP aufgelöst?
- Port 443: Lauscht dort etwas, oder wird die Verbindung abgelehnt oder gefiltert?
- TLS: Ist das Zertifikat gültig, nicht abgelaufen und mit vollständiger Kette ausgeliefert?
- HTTP-Status: Was liefert der Server tatsächlich: 200, 401, 429, 503?
- CORS: Trägt die Antwort die Header, die ein Browser braucht, um Ihnen den Body zu übergeben?
- Payload: Hat das JSON die Form, die Ihr Code erwartet?
Status und Header eines Endpunkts jetzt prüfen
Einen echten Endpunkt wählen, den Sie beliebig oft aufrufen dürfen
Zum Üben brauchen Sie einen Live-Endpunkt, der echte Daten liefert, keinen API-Key verlangt und Sie nicht per Rate Limit ausbremst, wenn Sie dieselbe Anfrage zwanzigmal senden. Das schließt die meisten naheliegenden Kandidaten aus: Fast jede gängige öffentliche API verlangt inzwischen eine Registrierung und ein Token, sodass eine fehlgeschlagene Anfrage immer auch an Ihren Zugangsdaten liegen könnte statt an der getesteten Schicht.
Die Beispiele unten verwenden die kostenlose Gebetszeiten-API von Waqt Azan (مواقيت الصلاة), einem arabischen Gebetszeiten-Dienst mit mehr als 60.000 Orten in über 100 Ländern. Als Lehr-Endpunkt eignet sie sich aus drei Gründen: Es gibt weder Key noch Auth-Header, sie liefert strukturiertes JSON statt HTML, und sie setzt eine großzügige CORS-Richtlinie. Die curl-Befehle laufen also genau wie geschrieben, und das fetch()-Beispiel funktioniert in der Konsole einer Seite ohne strikte Content-Security-Policy.
Der Endpunkt nimmt Länder- und Städte-Slug direkt im Pfad:
# Prayer times for a city — no API key, no headers required
curl -s https://waqtazan.com/api/v1/timings/saudi-arabia/riyadh
# The same data as a subscribable calendar feed
curl -s https://waqtazan.com/api/v1/ical/saudi-arabia/riyadh.icsSetzen Sie einen beliebigen Host ein, den Sie tatsächlich debuggen: Die sechs Schichten sind identisch, ob Sie eine öffentliche API, Ihren eigenen Staging-Server oder einen Webhook-Empfänger eines Drittanbieters testen.
Schicht 1: Wird der Hostname aufgelöst?
DNS ist ein häufiger Übeltäter. Ein Eintrag wurde geändert und hat sich nicht verbreitet, ein Wildcard wurde entfernt, oder die API liegt auf einer Subdomain, die nie angelegt wurde.
Lösen Sie den Hostnamen vor allem anderen auf. Liefert dieser Schritt nichts, hilft kein noch so häufiger Neustart Ihrer App: Ihr Client kommt gar nicht so weit, einen Socket zu öffnen.
dig +short waqtazan.com A
nslookup waqtazan.com
# Compare what different resolvers see — catches mid-propagation records
dig +short waqtazan.com A @1.1.1.1
dig +short waqtazan.com A @8.8.8.8Wenn zwei öffentliche Resolver kurz nach einer Änderung des Eintrags voneinander abweichen, verbreitet er sich noch, und die API wirkt je nach Resolver des jeweiligen Clients zeitweise kaputt (ein CDN mit Geo-Routing kann jedem Resolver dauerhaft eine andere Adresse geben, vergleichen Sie also mit dem Eintrag, den Sie gesetzt haben). Mit einer DNS-Abfrage sehen Sie alle Einträge, und die Verbreitung bei globalen Resolvern prüfen Sie direkt nach einer Änderung im DNS-Propagation-Checker.
Eine leere Antwort entspricht direkt ERR_NAME_NOT_RESOLVED in Chrome und getaddrinfo ENOTFOUND in Node. Alle Lösungen finden Sie in ERR_NAME_NOT_RESOLVED.
Eines brauchen Sie nicht zu beachten: Viele APIs liegen hinter einem CDN, sodass der A-Eintrag auf einen CDN-Edge statt auf den Ursprungsserver zeigt. Das ist normal. Wichtig ist, dass Sie überhaupt eine Antwort bekommen, nicht welche IP es ist.
Schicht 2: Ist Port 443 offen?
Der Hostname wird aufgelöst, also hat etwas eine Adresse. Jetzt klären Sie, ob dort etwas lauscht. Hier trennen Sie drei sehr unterschiedliche Fehler, die Clients gern identisch melden:
- Offen (Open): Der TCP-Handshake wird abgeschlossen. Weiter zur nächsten Schicht.
- Abgelehnt (Refused): Der Host hat sofort mit RST geantwortet. Er ist da, aber nichts ist an den Port gebunden, meist ist der Dienst abgestürzt oder nur an localhost gebunden.
- Gefiltert (Filtered): Die Verbindung hängt bis zum Timeout. Eine Firewall oder Security Group verwirft Pakete stillschweigend, weshalb Ihre Anfrage über eine Minute hängt, bevor sie fehlschlägt (unter macOS 75 Sekunden).
# Time-boxed TCP check: -w limits the connect on Linux; on macOS use -G 5 instead
nc -vz -w 5 waqtazan.com 443
# Or with curl: --connect-timeout caps the connect; 000 means no response came back
curl -s -o /dev/null -w '%{http_code}\n' --connect-timeout 5 https://waqtazan.com/Eine abgelehnte und eine gefilterte Verbindung brauchen völlig unterschiedliche Lösungen, daher lohnt es sich zu wissen, welche Sie haben. Der Port-Checker unterscheidet beide und testet von außerhalb Ihres Netzwerks, was wichtig ist: Ein Port, der über Ihr Büro-VPN offen ist, kann aus dem öffentlichen Internet per Firewall gesperrt sein.
Wenn curl als Statuscode 000 ausgibt, kam keine HTTP-Antwort zurück. Meist ist die Anfrage in den Schichten 1–3 gescheitert (keine DNS-Antwort, abgelehnter oder gefilterter Port, fehlgeschlagener TLS-Handshake), aber auch ein Server, der die Verbindung annimmt und dann schließt oder nie antwortet, ergibt 000. Mit -v sehen Sie den letzten funktionierenden Schritt. ERR_CONNECTION_REFUSED behandelt den Fall der Ablehnung ausführlich.
Schicht 3: Ist das TLS-Zertifikat gültig?
Port 443 ist offen, aber ein offener Port bedeutet noch keinen funktionierenden HTTPS-Endpunkt. Zertifikate sind ein klassischer Über-Nacht-Ausfall, weil sie planmäßig ablaufen und die Erneuerungsautomatik still fehlschlägt.
Das Zertifikat muss drei Bedingungen gleichzeitig erfüllen: Es ist nicht abgelaufen, sein Name passt zum angefragten Hostnamen, und der Server sendet die vollständige Zwischenzertifikat-Kette. Die dritte ist die heimtückische: Eine unvollständige Kette funktioniert in Browsern oft, weil Chrome ein fehlendes Zwischenzertifikat selbst nachlädt und Firefox sie vorlädt, während Node, Python, Java und OpenSSL-Builds von curl scheitern (das mit macOS ausgelieferte curl nutzt die Apple-Prüfung und kann bestehen). Das ist der Ursprung des klassischen Fehlerberichts „Im Browser läuft es, in Produktion nicht“.
# Expiry dates and subject
echo | openssl s_client -connect waqtazan.com:443 -servername waqtazan.com 2>/dev/null \
| openssl x509 -noout -subject -dates
# Full chain as presented by the server
openssl s_client -connect waqtazan.com:443 -servername waqtazan.com -showcerts < /dev/nullZählen Sie die Zertifikate in der -showcerts-Ausgabe. Ein einzelnes Zertifikat bedeutet meist ein fehlendes Zwischenzertifikat. Der SSL-Zertifikat-Checker meldet Ablauf, Kettenvollständigkeit und Hostnamen-Übereinstimmung in einem Durchgang, und was eine SSL-Zertifikatskette ist erklärt, warum das Zwischenzertifikat so wichtig ist.
Lassen Sie -servername stehen: OpenSSL 1.1.1 und neuer setzen SNI aus dem -connect-Hostnamen, das mit macOS ausgelieferte LibreSSL-openssl aber nicht, und bei einer Verbindung zu einer IP-Adresse keine Version. Ohne SNI liefert ein Shared Host sein Standardzertifikat oder bricht, wie Cloudflare, den Handshake ab, und Sie jagen eine Namensabweichung, die es gar nicht gibt.
Schicht 4: Die Antwort-Header lesen
TLS ist in Ordnung, Sie haben also endlich ein echtes HTTP-Gespräch. Lesen Sie jetzt, was der Server tatsächlich gesagt hat, statt was Ihr Client daraus zusammengefasst hat. Gedruckt werden nur die Header: Der Body wird trotzdem heruntergeladen und verworfen, es ist also dasselbe GET, das Ihr Client sendet.
curl -s -D - -o /dev/null https://waqtazan.com/api/v1/timings/egypt/cairoLesen Sie zuerst die Statuszeile, dann content-type, dann alles andere. Diese beiden Felder verraten Ihnen, ob die Anfrage erfolgreich war und ob der Body JSON ist, bevor Sie sonst etwas lesen.
So sieht eine gesunde JSON-Antwort aus
Der obige Befehl gegen den Test-Endpunkt lieferte am 27. Oktober 2026 unter anderem diese Header:
| Header | Wert | Was er Ihnen sagt |
|---|---|---|
HTTP/2 | 200 | Die Anfrage war erfolgreich, und der Server spricht HTTP/2 |
content-type | application/json | Sie bekommen JSON, keine HTML-Fehlerseite |
content-length | 567 | Eine echte Payload, kein leerer Body |
access-control-allow-origin | * | Browser dürfen diese Antwort lesen |
server | cloudflare | Vor dem Ursprungsserver sitzt ein CDN |
alt-svc | h3=":443" | HTTP/3 wird für Folgeanfragen angeboten |
Schicht 5: Der Header, der nur Browser-Aufrufe bricht
In dieser Schicht verschwinden Stunden, denn hier sind curl und Browser tatsächlich verschiedener Meinung. CORS wird vom Browser durchgesetzt, nicht vom Server. Fehlt Access-Control-Allow-Origin, liefert der Server trotzdem ein vollständiges, korrektes 200, nur der Browser weigert sich, den Body an Ihr JavaScript zu übergeben.
Das Symptom lautet also: curl funktioniert einwandfrei, Postman funktioniert einwandfrei, und die Browser-Konsole meldet, die Anfrage sei durch die CORS-Richtlinie blockiert worden. Am Server ist nichts falsch. In der Antwort fehlt nur ein Header.
Der Test-Endpunkt liefert access-control-allow-origin: *, weshalb ein einfaches fetch() von jedem Origin aus funktioniert:
// Run it in the console of a tab on a site without a strict CSP, such as example.com
// (this page's own CSP blocks it). It works there because ACAO is set to *
const r = await fetch('https://waqtazan.com/api/v1/timings/egypt/cairo')
console.log(await r.json())Die Preflight-Falle: Funktioniert, bis Sie einen Header hinzufügen
Es gibt eine zweite Falle, und dieser Endpunkt zeigt sie schön. Eine einfache Anfrage (ein schlichtes GET ohne eigene Header) gelingt. Sobald Sie aber einen eigenen Header hinzufügen oder mit Content-Type: application/json per POST senden, schickt der Browser zuerst einen OPTIONS-Preflight, und dessen Antwort muss eigene CORS-Header tragen (MDN).
Testen Sie den Preflight separat, denn er ist eine andere Antwort aus einem anderen Codepfad:
curl -s -D - -o /dev/null -X OPTIONS \
-H 'Origin: https://example.com' \
-H 'Access-Control-Request-Method: GET' \
https://waqtazan.com/api/v1/timings/egypt/cairoStand 27. Oktober 2026 liefert dieser Preflight ein 200 mit content-type: text/html und überhaupt keinen access-control-allow-origin-Header, sodass eine Browser-Anfrage mit Preflight blockiert würde, obwohl das einfache GET einwandfrei funktioniert.
Genau das ist die Falle: Ihre Integration läuft in der Entwicklung, Sie fügen einen Authorization- oder X-Request-Id-Header hinzu, und sie bricht ohne jede Änderung am Server. Wenn Sie nur öffentliche Daten brauchen, halten Sie die Anfrage einfach, dann funktioniert sie weiter.
Schicht 6: Hat die Payload die erwartete Form?
Die letzte Schicht ist die, die Ihr Code wirklich interessiert. Ein 200 mit gültigem JSON kann Sie trotzdem brechen, wenn ein Feld umbenannt wurde, ein Typ von Zahl zu String wechselte oder ein Zeitstempel in einem Format ankommt, das Sie nicht parsen.
Sehen Sie sich die echte Antwort an, bevor Sie den Parser schreiben. Dieser Endpunkt liefert sowohl formatierte Anzeigezeiten als auch ISO-Zeitstempel, ein Muster, das man übernehmen sollte: Die lokalisierten Strings sind für Menschen, die ISO-Werte für Code:
{
"city": { "slug": "riyadh", "name_ar": "الرياض", "name_en": "Riyadh" },
"country": "saudi-arabia",
"date": "2026-10-26",
"times": { "fajr": "4:38 ص", "dhuhr": "11:37 ص", "maghrib": "5:17 م" },
"timesISO": { "fajr": "2026-10-26T01:38:00.000Z", "dhuhr": "2026-10-26T08:37:00.000Z" },
"method": "umm_al_qura"
}Parsen Sie immer das maschinenlesbare Feld. Hier ist das timesISO, nie times: Die Anzeige-Strings sind lokalisiert und ändern ihr Format, sobald sich die Locale ändert.
Leiten Sie die Antwort durch jq, um die Struktur schnell zu prüfen: curl -s <url> | jq keys listet die Felder der obersten Ebene auf, und jq '.times' geht ins Detail, ohne dass Sie durch den rohen Body scrollen müssen.
Symptom → Schicht → Tool
Damit springen Sie direkt zur relevanten Schicht, statt jedes Mal alle sechs zu durchlaufen:
| Was Sie sehen | Fehlerhafte Schicht | Prüfen mit |
|---|---|---|
ERR_NAME_NOT_RESOLVED, ENOTFOUND | 1 — DNS | DNS-Abfrage |
ECONNREFUSED, instant failure | 2 — Port | Port-Checker |
| Anfrage hängt, dann Timeout | 2 — Gefilterter Port | Port-Checker |
CERT_HAS_EXPIRED, UNABLE_TO_VERIFY_LEAF_SIGNATURE | 3 — TLS | SSL-Checker |
| Läuft im Browser, scheitert in curl oder Node | 3 — Unvollständige Kette | SSL-Checker |
401, 429, 503 | 4 — HTTP-Status | HTTP-Header-Checker |
| Läuft in curl, im Browser blockiert | 5 — CORS | HTTP-Header-Checker |
Unexpected token '<', "<!DOCTYPE "... is not valid JSON | 4 — HTML-Fehlerseite | HTTP-Header-Checker |
| Felder fehlen oder haben den falschen Typ | 6 — Payload | curl … | jq |
Die Latenz liegt etwas außerhalb dieser Leiter. Wenn alle Schichten bestehen, die Antworten aber langsam sind, messen Sie die Round-Trip-Zeit zum Host mit ping und prüfen mit einem DNS-Geschwindigkeitstest, ob die Namensauflösung selbst der Engpass ist.
Die echten Antwort-Header jedes Endpunkts prüfen
Sehen Sie den genauen Statuscode, den content-type und die CORS-Header, die eine API zurückgibt. Die Anfrage läuft serverseitig, sodass weder Browser-Cache noch Erweiterungen das Ergebnis verfälschen. Kostenlos, ohne Anmeldung.
Quellen
Häufig gestellte Fragen
Wie teste ich einen API-Endpunkt ohne Postman?
Warum funktioniert meine API in curl, schlägt aber im Browser fehl?
Was bedeutet der Statuscode 000 bei curl?
Woran erkenne ich, ob eine API für alle oder nur für mich nicht erreichbar ist?
Warum liefert eine API 200, aber mein JSON-Parser wirft einen Fehler?
Was ist ein CORS-Preflight, und wann tritt er auf?
Sollte ich das DNS der API mit meinem eigenen oder einem öffentlichen Resolver testen?
Bedeutet ein offener Port 443, dass der HTTPS-Endpunkt funktioniert?
Verwandte Artikel
Verwandte Tools
HTTP-Header-Checker
HTTP-Antwort-Header und Sicherheits-Header-Bewertung analysieren
DNS-Abfrage
Alle DNS-Einträge direkt von den Nameservern der Domain, neben dem Cache von Google und Cloudflare
Port-Checker
Port-Konnektivität und Service-Verfügbarkeit testen
SSL-Zertifikat-Check
Gültigkeit und Sicherheitsdetails des SSL-Zertifikats überprüfen
Ping Test
Ping, Jitter und Paketverlust messen, den Ping zu 34 Cloud-Regionen sehen und jede Website oder IP aus 11 Städten anpingen



