Manchmal muss ein Skript nur schnell wissen, ob eine URL erreichbar ist, wohin sie weiterleitet oder welchen Content-Type sie liefert. Für solche Fälle gibt es in PHP die Funktion get_headers(), die allein die Antwort-Header einer Adresse holt und den Body außen vor lässt. Dieses Tutorial zeigt Syntax, Modi und die typischen Stolperfallen von der Statuscode-Extraktion bis zu allow_url_fopen.
Was macht PHP get_headers()?
Wer in PHP schnell prüfen will, ob eine URL erreichbar ist, einen Redirect schickt oder welchen Content-Type sie liefert, greift zu PHP get_headers. Die Funktion sendet einen einzelnen HTTP-Request an die angegebene URL und gibt die Antwort-Header als Array zurück. Der eigentliche Body wird dabei nicht mitübertragen, was die Prüfung sehr schnell macht.

Bevor Syntax, Statuscode-Extraktion und der Vergleich mit cURL folgen, ein kurzer Blick auf die Einsatzfälle, in denen get_headers glänzt.
Typische Einsatzfälle sind Linkchecker, SEO-Tools, einfache Verfügbarkeits-Monitore und Validatoren, die prüfen, ob ein verlinktes PDF noch online liegt. Im Vergleich zu curl_exec ist get_headers besonders kurz aufgeschrieben, kommt aber mit ein paar Einschränkungen, die in diesem Tutorial Schritt für Schritt erklärt werden.
Syntax und Modi (numerisch vs. assoziativ)
Die Signatur von PHP get_headers ist kompakt: ein URL-String, ein optionaler Modus und ein optionaler Stream-Context. Der Modus entscheidet, ob das Ergebnis als numerisch indiziertes Array oder als assoziatives Array zurückkommt.
<?php
get_headers(string $url, int $associative = 0, ?resource $context = null): array|false
Im Modus 0 ist das Array eine schlichte Liste der Header-Zeilen, beginnend mit der Status-Zeile. Im Modus 1 sind die Header über ihren Namen ansprechbar.
<?php
$headers = get_headers('https://php.net/');
print_r($headers);
/* numerisch: $headers[0] enthaelt die Status-Zeile */
$assoc = get_headers('https://php.net/', 1);
echo $assoc['Content-Type'] ?? 'unbekannt';
/* assoziativ: ueber Header-Name greifbar */
Im Alltag ist Modus 1 für Auswertungen praktischer, Modus 0 ist hilfreich, wenn alle Status-Zeilen einer Redirect-Kette einzeln sichtbar bleiben sollen.
Statuscode aus der ersten Header-Zeile lesen
Der HTTP-Statuscode steht in der ersten Header-Zeile, etwa als HTTP/1.1 200 OK oder HTTP/2 301. Da PHP get_headers den Code nicht als Integer liefert, muss er über einen Regex aus der Zeile extrahiert werden.
<?php
$headers = get_headers('https://example.com/');
$statusLine = $headers[0] ?? '';
if (preg_match('#HTTP/\d+\.\d+\s+(\d{3})#', $statusLine, $m)) {
$code = (int) $m[1];
echo 'Statuscode: ' . $code;
}
Mit dieser Prüfung lassen sich klassische Fälle wie 200 (OK), 301 oder 302 (Redirect), 404 (nicht gefunden) und 500 (Server-Fehler) klar unterscheiden. Hilfreich ist das Tutorial zu HTTP-Header in PHP, wenn das Verständnis der Header-Konzepte vertieft werden soll.
Redirects über den Location-Header erkennen
Folgt PHP get_headers automatisch einem Redirect, dann erscheinen die Header beider Antworten im Ergebnis-Array. Im numerischen Modus ist das gut sichtbar, weil mehrere Status-Zeilen vorhanden sind. Im assoziativen Modus wird überschrieben, sodass die letzten Werte gelten und der Location-Header zwischendurch verloren gehen kann. Hier hilft Modus 0.
<?php
$headers = get_headers('http://google.com/');
foreach ($headers as $line) {
if (stripos($line, 'HTTP/') === 0 || stripos($line, 'Location:') === 0) {
echo $line . "\n";
}
}
/* zeigt Status und Ziel-URL der Redirect-Kette */
Wer nur die finale Adresse braucht, kann mit der Location-Auswertung im numerischen Modus arbeiten. Mehr Komfort für komplexe Redirect-Ketten bietet allerdings curl mit CURLOPT_FOLLOWLOCATION und CURLINFO_EFFECTIVE_URL, dazu später mehr.
Timeout und Methodenwechsel via stream_context
Standardmäßig sendet PHP get_headers einen HEAD-Request mit dem in default_socket_timeout festgelegten Timeout (oft 60 Sekunden). Beides lässt sich über einen Stream-Context anpassen, der als dritter Parameter übergeben wird.
<?php
$ctx = stream_context_create([
'http' => [
'method' => 'HEAD',
'timeout' => 3.0,
'header' => "User-Agent: SpaceLinkCheck/1.0\r\n",
],
]);
$headers = @get_headers('https://example.com/', 1, $ctx);
if ($headers === false) {
echo 'URL nicht erreichbar';
}
Manche Server antworten auf HEAD-Requests mit Status 405 (Method Not Allowed). In diesem Fall hilft es, die Methode auf GET umzustellen, auch wenn dann der Body mit über die Leitung geht.
<?php
$ctx = stream_context_create([
'http' => [
'method' => 'GET',
'timeout' => 3.0,
],
]);
$headers = get_headers('https://example.com/', 1, $ctx);
print_r($headers);
Stolperfalle allow_url_fopen
PHP get_headers nutzt intern die HTTP-Stream-Wrapper. Die Funktion arbeitet nur, wenn die Konfiguration allow_url_fopen aktiv ist. Auf Shared-Hostings ist diese Option oft deaktiviert, sodass die Funktion stumm false zurückliefert.
<?php
if (ini_get('allow_url_fopen') !== '1') {
/* Fallback auf curl bauen */
echo 'allow_url_fopen ist deaktiviert';
} else {
$headers = get_headers('https://example.com/');
}
Wer an die Konfiguration nicht herankommt, sollte einen Fallback über curl_init und curl_exec bauen. cURL ist auf den meisten Servern ohnehin verfügbar und liefert mehr Kontrolle.
get_headers vs. curl_exec mit CURLOPT_NOBODY
Sobald eine Linkprüfung produktiv eingesetzt wird, lohnt sich der Vergleich mit curl. Die Option CURLOPT_NOBODY = true macht aus einem GET einen HEAD-Request, CURLOPT_RETURNTRANSFER hält das Ergebnis im Speicher und curl_getinfo liefert den Statuscode bequem als Integer.
<?php
$ch = curl_init('https://example.com/');
curl_setopt_array($ch, [
CURLOPT_NOBODY => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true,
CURLOPT_TIMEOUT => 3,
CURLOPT_FOLLOWLOCATION => true,
]);
$response = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo 'Statuscode: ' . $code;
Diese Variante ist robuster, wenn viele URLs hintereinander geprüft werden sollen. Mit curl_multi_init lassen sich sogar Dutzende Prüfungen parallel ausführen, was PHP get_headers von Haus aus nicht kann. Für eine kleine Linkprüfung im Skript-Alltag bleibt PHP get_headers aber die kürzere Lösung.
Der typische Ablauf einer Header-Abfrage mit anschließender Statuscode-Auswertung lässt sich als Flussdiagramm gut überblicken.
flowchart TD
A[URL] --> B[HEAD-Request]
B --> C{Server antwortet?}
C -->|Ja| D[Header-Array]
C -->|Nein| E[false oder Timeout]
D --> F{Statuscode 3xx?}
F -->|Ja| G[Location-Header lesen]
F -->|Nein| H[Antwort verwenden]
Fazit
PHP get_headers ist ein angenehm kompaktes Werkzeug für schnelle URL-Prüfungen, Statuscode-Checks und Header-Abfragen. Wer den Unterschied zwischen Modus 0 und Modus 1 kennt, den Statuscode sauber per Regex extrahiert und einen Timeout über stream_context_create setzt, kommt im Alltag selten in eine Sackgasse. Für hohe Lasten oder fehlendes allow_url_fopen ist curl_exec mit CURLOPT_NOBODY die robustere Alternative. In der Summe ist PHP get_headers ideal für kleine Helfer, Cron-Jobs und SEO-Tools, in denen Lesbarkeit wichtiger ist als das letzte Quäntchen Performance.