downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

get_meta_tags> <base64_encode
[edit] Last updated: Fri, 22 Jul 2011

view this page in

get_headers

(PHP 5)

get_headersFetches all the headers sent by the server in response to a HTTP request

Description

array get_headers ( string $url [, int $format = 0 ] )

get_headers() returns an array with the headers sent by the server in response to a HTTP request.

Parameters

url

The target URL.

format

If the optional format parameter is set to non-zero, get_headers() parses the response and sets the array's keys.

Return Values

Returns an indexed or associative array with the headers, or FALSE on failure.

Changelog

Version Description
5.1.3 This function now uses the default stream context, which can be set/changed with the stream_context_get_default() function.

Examples

Example #1 get_headers() example

<?php
$url 
'http://www.example.com';

print_r(get_headers($url));

print_r(get_headers($url1));
?>

The above example will output something similar to:

Array
(
    [0] => HTTP/1.1 200 OK
    [1] => Date: Sat, 29 May 2004 12:28:13 GMT
    [2] => Server: Apache/1.3.27 (Unix)  (Red-Hat/Linux)
    [3] => Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
    [4] => ETag: "3f80f-1b6-3e1cb03b"
    [5] => Accept-Ranges: bytes
    [6] => Content-Length: 438
    [7] => Connection: close
    [8] => Content-Type: text/html
)

Array
(
    [0] => HTTP/1.1 200 OK
    [Date] => Sat, 29 May 2004 12:28:14 GMT
    [Server] => Apache/1.3.27 (Unix)  (Red-Hat/Linux)
    [Last-Modified] => Wed, 08 Jan 2003 23:11:55 GMT
    [ETag] => "3f80f-1b6-3e1cb03b"
    [Accept-Ranges] => bytes
    [Content-Length] => 438
    [Connection] => close
    [Content-Type] => text/html
)



get_meta_tags> <base64_encode
[edit] Last updated: Fri, 22 Jul 2011
 
add a note add a note User Contributed Notes get_headers
damolp at hotmail dot com 04-Jul-2011 12:43
I found that this function is the slowest in obtaining the headers of a page probably because it uses a GET request rather then a HEAD request. Over 10,000,000 trials of obtaining the headers of a page from a server i found the following (results in seconds).

cURL: Mean: 0.584127946. Sigma: 0.050581736.
fsocketopen: Mean: 0.622114251. Sigma: 0.263170424.
get_headers: Mean: 0.90375551. Sigma: 0.273823419.

cURL was the fastest with fsocketopens being the second fastest. I noticed as well that fsocketopen had some outliers where as cURL did not.
Lukas Najduk 11-Jan-2011 11:36
Unfortunately there is still no useful output format to handle redirects.

This function will bring all non-broken headers into a usable format. Too bad it has to call the get_headers() funtion 2 times, but i dont see any other possibility right now.

<?php
function page_get_headers($crawl_uri) {
   
// get the array values where to split the second get headers return
   
$headers = get_headers($crawl_uri, 1);
    if (empty(
$headers)) {
        return array();
    }
   
$splitmarks = array();
    foreach (
$headers as $key=>$h) {
        if (
is_numeric($key)) {
           
array_push($splitmarks, $h);
        }
    }

   
// get the "real" headers
   
$headers_final = array();
   
$i = 0;
   
$headers = get_headers($crawl_uri);
    foreach (
$headers as $head) {
       
// if the value is one of the splitmarks, start the next header
       
if (array_key_exists($i, $splitmarks) && $head === $splitmarks[$i]) {
           
$i++;
        }  
        else {
           
// get the headers name
           
$tmp = explode(": ", $head, 2);
           
// check if the header is already existing, if yes, parse the similar header to an array
           
if (!empty($headers_final[$i-1][$tmp[0]])) {
                if (
is_array($headers_final[$i-1][$tmp[0]])) {
                   
array_push($headers_final[$i-1][$tmp[0]], $tmp[1]);
                }
                else {
                   
$headers_final[$i-1][$tmp[0]] = array($headers_final[$i-1][$tmp[0]], $tmp[1]);
                }
            }
            else {
               
$headers_final[$i-1][$tmp[0]] = $tmp[1];  
            }  
        }
    }
    return
$headers_final;
}
?>
Weboide 26-Sep-2010 01:13
Note that get_headers **WILL follow redirections** (HTTP redirections). New headers will be appended to the array if $format=0. If $format=1 each redundant header will be an array of multiple values, one for each redirection.

For example:

<?php
$url
= 'http://google.com';
var_dump(get_headers($url,0));
array(
18) {
  [
0]=>  string(30) "HTTP/1.0 301 Moved Permanently"
 
[1]=>  string(32) "Location: http://www.google.com/"
 
[2]=>  string(38) "Content-Type: text/html; charset=UTF-8"
 
[3]=>  string(35) "Date: Sun, 26 Sep 2010 00:59:50 GMT"
 
[4]=>  string(38) "Expires: Tue, 26 Oct 2010 00:59:50 GMT"
 
[5]=>  string(38) "Cache-Control: public, max-age=2592000"
....
 
string(15) "HTTP/1.0 200 OK"
 
[10]=>  string(35) "Date: Sun, 26 Sep 2010 00:59:51 GMT"
 
[11]=>  string(11) "Expires: -1"
 
[12]=>  string(33) "Cache-Control: private, max-age=0"
.....
}

/*===========================*/

var_dump(get_headers($url,1));
array(
11) {
  [
0]=>
 
string(30) "HTTP/1.0 301 Moved Permanently"
 
["Location"]=>  string(22) "http://www.google.com/"
 
["Content-Type"]=>  array(2) {
    [
0]=>    string(24) "text/html; charset=UTF-8"
   
[1]=>    string(29) "text/html; charset=ISO-8859-1"
 
}
  [
"Date"]=>  array(2) {
    [
0]=>    string(29) "Sun, 26 Sep 2010 01:03:39 GMT"
   
[1]=>    string(29) "Sun, 26 Sep 2010 01:03:39 GMT"
 
}
  [
"Expires"]=>  array(2) {
    [
0]=>    string(29) "Tue, 26 Oct 2010 01:03:39 GMT"
   
[1]=>    string(2) "-1"
 
}
  [
"Cache-Control"]=>  array(2) {
    [
0]=>    string(23) "public, max-age=2592000"
   
[1]=>    string(18) "private, max-age=0"
 
}
.....
}
bretticus 10-Sep-2010 05:41
If anyone is curious, as I was, this function does not send a HEAD verb. Instead it sends a GET. Which in my case is not ideal because I need a quick way to get a HTTP status (200, 404, etc.) The problem with GET is that, for cases such as mine, I do not want all the overhead with the data that comes back.
nick at innovaweb dot co dot uk 03-May-2010 12:28
Seems like there are some people who are looking for only the 3-digit HTTP response code  - here is a quick and nasty solution:

<?php
function get_http_response_code($theURL) {
   
$headers = get_headers($theURL);
    return
substr($headers[0], 9, 3);
}
?>

How easy is that? Echo the function containing the URL you want to check the response code for, and voilĂ . Custom redirects, alternative for blocked is_file() or flie_exists() functions (like I seem to have on my servers) hence the cheap workaround. But hey - it works!

Pudding
php at hm2k dot org 28-Jan-2010 06:20
<?php
/**
 * Fetches all the real headers sent by the server in response to a HTTP request without redirects
 *
 * @link      http://php.net/function.get_headers
 * @link      http://bugs.php.net/bug.php?id=50719
 */

function get_real_headers($url,$format=0,$follow_redirect=0) {
  if (!
$follow_redirect) {
   
//set new default options
   
$opts = array('http' =>
        array(
'max_redirects'=>1,'ignore_errors'=>1)
    );
   
stream_context_get_default($opts);
  }
 
//get headers
   
$headers=get_headers($url,$format);
   
//restore default options
 
if (isset($opts)) {
   
$opts = array('http' =>
        array(
'max_redirects'=>20,'ignore_errors'=>0)
    );
   
stream_context_get_default($opts);
  }
 
//return
   
return $headers;
}
?>
gabe at vtunnel dot com 22-Apr-2009 08:23
In some cases, you don't want get_headers to follow redirects. For example, some of my servers can access a particular website, which sends a redirect header. The site it is redirected to, however, has me firewalled. I need to take the 302 redirected url, and do something to it to give me a new url that I *can* connect to.

The following will give you output similar to get_headers, except it has a timeout, and it doesn't follow redirects:

<?php
function get_headers_curl($url)
{
   
$ch = curl_init();

   
curl_setopt($ch, CURLOPT_URL,            $url);
   
curl_setopt($ch, CURLOPT_HEADER,         true);
   
curl_setopt($ch, CURLOPT_NOBODY,         true);
   
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
   
curl_setopt($ch, CURLOPT_TIMEOUT,        15);

   
$r = curl_exec($ch);
   
$r = split("\n", $r);
    return
$r;
}

If
you do want to follow redirects, you can do something like this:

$go = 1;
$i = 1;

while (
$go && $i < 6)
{
   
$headers = get_headers_curl($url);
   
$go = getNextLocation($headers);
    if (
$go)
    {
       
$url = modifyUrl($go);
    }
   
$i++;
}

function
getNextLocation($headers)
{
   
$array = $headers;
   
$count = count($array);

    for (
$i=0; $i < $count; $i++)
    {
        if (
strpos($array[$i], "ocation:"))
        {
               
$url = substr($array[$i], 10);
        }
    }
    if (
$url)
    {
        return
$url;
    }
    else
    {
        return
0;
    }
}
?>
Anonymous 06-Oct-2008 09:00
Regarding Radon8472's code immediately below; since the response code always appears in the same place (just after the HTTP protocol and version), that's the only place where the response code needs to be looked for. The code could be simplified by parsing the first line separately from the remaining headers.

Incidentally, 305 and 307 responses should also result in redirects.
Radon8472 07-Aug-2008 01:07
No, it doesn`t.. It is a bad Idea to searczh for the text "Moved" if you want to find out if its a redirect.

Better is to look for the Responscode 301,302 and 303.

<?php
   
function get_headers($Url, $Format= 0, $Depth= 0) {
    if (
$Depth > 5) return;
   
$Parts = parse_url($Url);
    if (!
array_key_exists('path', $Parts))   $Parts['path'] = '/';
    if (!
array_key_exists('port', $Parts))   $Parts['port'] = 80;
    if (!
array_key_exists('scheme', $Parts)) $Parts['scheme'] = 'http';

   
$Return = array();
   
$fp = fsockopen($Parts['host'], $Parts['port'], $errno, $errstr, 30);
    if (
$fp) {
       
$Out = 'GET '.$Parts['path'].(isset($Parts['query']) ? '?'.@$Parts['query'] : '')." HTTP/1.1\r\n".
              
'Host: '.$Parts['host'].($Parts['port'] != 80 ? ':'.$Parts['port'] : '')."\r\n".
              
'Connection: Close'."\r\n";
       
fwrite($fp, $Out."\r\n");
       
$Redirect = false; $RedirectUrl = '';
        while (!
feof($fp) && $InLine = fgets($fp, 1280)) {
            if (
$InLine == "\r\n") break;
           
$InLine = rtrim($InLine);

            list(
$Key, $Value) = explode(': ', $InLine, 2);
            if (
$Key == $InLine) {
                if (
$Format == 1)
                       
$Return[$Depth] = $InLine;
                else   
$Return[] = $InLine;

                if ((
strpos($InLine, '301') > 0)||(strpos($InLine, '302') > 0)||(strpos($InLine, '303') > 0) ) $Redirect = true;
            } else {
                if (
$Key == 'Location') $RedirectUrl = $Value;
                if (
$Format == 1)
                       
$Return[$Key] = $Value;
                else   
$Return[] = $Key.': '.$Value;
            }
        }
       
fclose($fp);
        if (
$Redirect && !empty($RedirectUrl)) {
           
$NewParts = parse_url($RedirectUrl);
            if (!
array_key_exists('host', $NewParts))   $RedirectUrl = $Parts['host'].$RedirectUrl;
            if (!
array_key_exists('scheme', $NewParts)) $RedirectUrl = $Parts['scheme'].'://'.$RedirectUrl;
           
$RedirectHeaders = get_headers($RedirectUrl, $Format, $Depth+1);
            if (
$RedirectHeaders) $Return = array_merge_recursive($Return, $RedirectHeaders);
        }
        return
$Return;
    }
    return
false;
}

?>
info at marc-gutt dot de 21-Jun-2008 12:04
Should be the same than the original get_headers():

if (!function_exists('get_headers')) {
function get_headers($url, $format=0) {
    $headers = array();
    $url = parse_url($url);
    $host = isset($url['host']) ? $url['host'] : '';
    $port = isset($url['port']) ? $url['port'] : 80;
    $path = (isset($url['path']) ? $url['path'] : '/') . (isset($url['query']) ? '?' . $url['query'] : '');
    $fp = fsockopen($host, $port, $errno, $errstr, 3);
    if ($fp)
    {
        $hdr = "GET $path HTTP/1.1\r\n";
        $hdr .= "Host: $host \r\n";
        $hdr .= "Connection: Close\r\n\r\n";
        fwrite($fp, $hdr);
        while (!feof($fp) && $line = trim(fgets($fp, 1024)))
        {
            if ($line == "\r\n") break;
            list($key, $val) = explode(': ', $line, 2);
            if ($format)
                if ($val) $headers[$key] = $val;
                else $headers[] = $key;
            else $headers[] = $line;
        }
        fclose($fp);
        return $headers;
    }
    return false;
}
}
php dot sirlancelot at spamgourmet dot com 05-Jun-2008 08:59
I tried to replicate the native behavior as much as possible for systems that don't have the get_headers() function. Here it is:
<?php
if (!function_exists('get_headers')) {
function
get_headers($Url, $Format= 0, $Depth= 0) {
    if (
$Depth > 5) return;
   
$Parts = parse_url($Url);
    if (!
array_key_exists('path', $Parts))   $Parts['path'] = '/';
    if (!
array_key_exists('port', $Parts))   $Parts['port'] = 80;
    if (!
array_key_exists('scheme', $Parts)) $Parts['scheme'] = 'http';

   
$Return = array();
   
$fp = fsockopen($Parts['host'], $Parts['port'], $errno, $errstr, 30);
    if (
$fp) {
       
$Out = 'GET '.$Parts['path'].(isset($Parts['query']) ? '?'.@$Parts['query'] : '')." HTTP/1.1\r\n".
              
'Host: '.$Parts['host'].($Parts['port'] != 80 ? ':'.$Parts['port'] : '')."\r\n".
              
'Connection: Close'."\r\n";
       
fwrite($fp, $Out."\r\n");
       
$Redirect = false; $RedirectUrl = '';
        while (!
feof($fp) && $InLine = fgets($fp, 1280)) {
            if (
$InLine == "\r\n") break;
           
$InLine = rtrim($InLine);

            list(
$Key, $Value) = explode(': ', $InLine, 2);
            if (
$Key == $InLine) {
                if (
$Format == 1)
                       
$Return[$Depth] = $InLine;
                else   
$Return[] = $InLine;

                if (
strpos($InLine, 'Moved') > 0) $Redirect = true;
            } else {
                if (
$Key == 'Location') $RedirectUrl = $Value;
                if (
$Format == 1)
                       
$Return[$Key] = $Value;
                else   
$Return[] = $Key.': '.$Value;
            }
        }
       
fclose($fp);
        if (
$Redirect && !empty($RedirectUrl)) {
           
$NewParts = parse_url($RedirectUrl);
            if (!
array_key_exists('host', $NewParts))   $RedirectUrl = $Parts['host'].$RedirectUrl;
            if (!
array_key_exists('scheme', $NewParts)) $RedirectUrl = $Parts['scheme'].'://'.$RedirectUrl;
           
$RedirectHeaders = get_headers($RedirectUrl, $Format, $Depth+1);
            if (
$RedirectHeaders) $Return = array_merge_recursive($Return, $RedirectHeaders);
        }
        return
$Return;
    }
    return
false;
}}
?>
The function will handle up to five redirects.
Enjoy!
frozenfire at thefrozenfire dot com 09-Mar-2008 11:56
In response to dxtrim:

Actually, the Content-Type is not based from the file extension in a sense. Any discrepancies in Content-Type will be the result of a poorly configured web server.
For example:
One can configure Apache to serve a specific Content-Type based on the file extension. So, based on this, a web server with exhaustive configuration could serve any format using the correct Content-Type.
dxtrim at yahoo dot com 17-Jan-2008 09:16
Content-Type returns a value depending only on the extension and not the real MIME TYPE.

So, bad_file.exe renamed to good_file.doc will return application/msword

A file without extension returns a 404.
usagispanksrini at gmail dot com 25-Nov-2007 04:50
These will ALWAYS return 400 BAD REQUEST unless you run a $url = str_replace(' ','%20',$url');  This fixes the problem of it thinking that your false scripts for php_header is asking for multiple files, witout using the GET method.

NOTE: this only applies to ALL the above examples ;D.
eddy at interpc dot fr 15-Nov-2007 11:04
Because we only want to receive the headers and not a part of the file, I think that " while(!feof($fp)) " should be replaced by something like " while (!feof($fp) && strpos($var, "\r\n\r\n") === FALSE) "

Else, testing headers for an image file will get back a useless and time lost part of the image ...
PieterMarchand at telenet dot be 10-Nov-2007 07:11
Hello

just a tiny mod gives a cleaner solution

$key = array_shift(explode(':',$header));

$key = array_shift(explode(': ',$header));

notice the space after the colon.

Can be important if you want to modify this function in order to check if a url is valid. On response code 301 or 302 you need the new location. This new location happens to have a colon in it, the clock also has a few colons in it. Neither of them appear complete. With this tiny mod they do.

greetz,

Pieter
angelo [at] mandato (dot) com 14-Jul-2007 02:25
Be forewarned, none of the get_headers() functions below will replicate the behavior of PHP 5's get_headers() for URLs that use the 'Location:' redirect header or return File Not Found headers.

According to RFC1945, A user agent should never automatically redirect a request more than 5 times, since such redirections usually indicate an infinite loop.  For true compatibility, the functions below should be able to handle up to 5 Location redirects within one function call.  Only the native get_headers() function exhibits this behavior.  None of the functions below handle the 'Location' redirection.

The native PHP >= 5 get_headers() function will not return headers in some instances where the functions below would.  For example, if the server returns a 404 status, get_headers() will throw a PHP warning.  Unfortunately, the 404 error can only be known by looking at the headers.  From first glance, all of the functions below will return 404 headers, which may be a desired effect but does not replicate the behavior of the native get_headers() function.
13-Nov-2006 08:29
I've noticed it.
Some Server will simply return the false reply header if you sent 'HEAD' request instead of 'GET'. The 'GET' request header always receiving the most actual HTTP header instead of 'HEAD' request header. But If you don't mind for a fast but risky method then 'HEAD' request is better for you.

btw ... this is get header with additional information such as User, Pass & Refferer. ...
<?php
   
function get_headers_x($url,$format=0, $user='', $pass='', $referer='') {
        if (!empty(
$user)) {
           
$authentification = base64_encode($user.':'.$pass);
           
$authline = "Authorization: Basic $authentification\r\n";
        }

        if (!empty(
$referer)) {
           
$refererline = "Referer: $referer\r\n";
        }

       
$url_info=parse_url($url);
       
$port = isset($url_info['port']) ? $url_info['port'] : 80;
       
$fp=fsockopen($url_info['host'], $port, $errno, $errstr, 30);
        if(
$fp) {
           
$head = "GET ".@$url_info['path']."?".@$url_info['query']." HTTP/1.0\r\n";
            if (!empty(
$url_info['port'])) {
               
$head .= "Host: ".@$url_info['host'].":".$url_info['port']."\r\n";
            } else {
               
$head .= "Host: ".@$url_info['host']."\r\n";
            }
           
$head .= "Connection: Close\r\n";
           
$head .= "Accept: */*\r\n";
           
$head .= $refererline;
           
$head .= $authline;
           
$head .= "\r\n";

           
fputs($fp, $head);      
            while(!
feof($fp) or ($eoheader==true)) {
                if(
$header=fgets($fp, 1024)) {
                    if (
$header == "\r\n") {
                       
$eoheader = true;
                        break;
                    } else {
                       
$header = trim($header);
                    }

                    if(
$format == 1) {
                   
$key = array_shift(explode(':',$header));
                        if(
$key == $header) {
                           
$headers[] = $header;
                        } else {
                           
$headers[$key]=substr($header,strlen($key)+2);
                        }
                    unset(
$key);
                    } else {
                       
$headers[] = $header;
                    }
                }
            }
            return
$headers;

        } else {
            return
false;
        }
    }
?>

Regards.
Donovan
eis 29-Oct-2006 02:29
denilson at vialink:

if you want just the headers, use HEAD request, not GET.
10-May-2006 11:10
If you want to get headers that current PHP process is going to send back to browser, see headers_list()
rsyring+phppost at gmail dot com 06-Apr-2006 10:08
Once again another update.  The improvements are:

HTTPS support (make sure you have SSL support enabled -- PHP5 is as simple as uncommenting extension=php_openssl.dll in php.ini)

Fixed bug with exploding the header on ':'.  This caused the location header to be broken and just return 'http'.

Set stream timeout in addition to socket timeout.

<?php

function my_get_headers($url ) {

      
$url_info=parse_url($url);
       if (isset(
$url_info['scheme']) && $url_info['scheme'] == 'https') {
          
$port = 443;
           @
$fp=fsockopen('ssl://'.$url_info['host'], $port, $errno, $errstr, 10);
       } else {
          
$port = isset($url_info['port']) ? $url_info['port'] : 80;
           @
$fp=fsockopen($url_info['host'], $port, $errno, $errstr, 10);
       }
       if(
$fp) {
          
stream_set_timeout($fp, 10);
          
$head = "HEAD ".@$url_info['path']."?".@$url_info['query'];
          
$head .= " HTTP/1.0\r\nHost: ".@$url_info['host']."\r\n\r\n";
          
fputs($fp, $head);
           while(!
feof($fp)) {
               if(
$header=trim(fgets($fp, 1024))) {
                       
$sc_pos = strpos( $header, ':' );
                        if(
$sc_pos === false ) {
                          
$headers['status'] = $header;
                        } else {
                           
$label = substr( $header, 0, $sc_pos );
                           
$value = substr( $header, $sc_pos+1 );
                           
$headers[strtolower($label)] = trim($value);
                        }
               }
           }
           return
$headers;
       }
       else {
           return
false;
       }
   }

?>
denilson at vialink dot com dot br 30-Oct-2005 09:15
This is a modified version of code from "stuart at sixletterwords dot com", at 14-Sep-2005 04:52. This version tries to emulate get_headers() function at PHP4. I think it works fairly well, and is simple. It is not the best emulation available, but it works.

Features:
- supports (and requires) full URLs.
- supports changing of default port in URL.
- stops downloading from socket as soon as end-of-headers is detected.

Limitations:
- only gets the root URL (see line with "GET / HTTP/1.1").
- don't support HTTPS (nor the default HTTPS port).

<?php
if(!function_exists('get_headers'))
{
    function
get_headers($url,$format=0)
    {
       
$url=parse_url($url);
       
$end = "\r\n\r\n";
       
$fp = fsockopen($url['host'], (empty($url['port'])?80:$url['port']), $errno, $errstr, 30);
        if (
$fp)
        {
           
$out  = "GET / HTTP/1.1\r\n";
           
$out .= "Host: ".$url['host']."\r\n";
           
$out .= "Connection: Close\r\n\r\n";
           
$var  = '';
           
fwrite($fp, $out);
            while (!
feof($fp))
            {
               
$var.=fgets($fp, 1280);
                if(
strpos($var,$end))
                    break;
            }
           
fclose($fp);

           
$var=preg_replace("/\r\n\r\n.*\$/",'',$var);
           
$var=explode("\r\n",$var);
            if(
$format)
            {
                foreach(
$var as $i)
                {
                    if(
preg_match('/^([a-zA-Z -]+): +(.*)$/',$i,$parts))
                       
$v[$parts[1]]=$parts[2];
                }
                return
$v;
            }
            else
                return
$var;
        }
    }
}
?>
tylerxxdurden at web dot de 24-Sep-2005 06:54
my version
cleans the input URL a little bit
(you should be able to put in almost every shit, and it should still work)
Should work for:
http://test.de
http://test.de/
www.test.de
http://test.de/
http://test.de/test.html
http://test.de/test.html?testme
...

not nice, but seems to work for me

<?
function get_headers2($url,$format=0) {
      
$url_info=parse_url($url);
      
$port = isset($url_info['port']) ? $url_info['port'] : 80;
      
$fp=fsockopen($url_info['host'], $port, $errno, $errstr, 30);
       if(
$fp) {
           if(!
$url_info['path']){
                        
$url_info['path'] = "/";
                     }
                     if(
$url_info['path'] && !$url_info['host']){
                       
$url_info['host'] = $url_info['path'];
                       
$url_info['path'] = "/";
                     }
                     if(
$url_info['host'][(strlen($url_info['host'])-1)] == "/" ){
                       
$url_info['host'][(strlen($url_info['host'])-1)] = "";
                     }
                     if(!
$url_array[scheme]){
                        
$url_array[scheme] = "http"; //we always use http links
                       
}
                    
$head = "HEAD ".@$url_info['path'];
                     if(
$url_info['query'] ){
                        
$head .= "?".@$url_info['query'];
                        }
                       
print_r($url_info);
          
$head .= " HTTP/1.0\r\nHost: ".@$url_info['host']."\r\n\r\n";
           echo
$head;
                    
fputs($fp, $head);
           while(!
feof($fp)) {
               if(
$header=trim(fgets($fp, 1024))) {
                   if(
$format == 1) {
                      
$h2 = explode(':',$header);
                      
// the first element is the http header type, such as HTTP/1.1 200 OK,
                       // it doesn't have a separate name, so we have to check for it.
                      
if($h2[0] == $header) {
                          
$headers['status'] = $header;
                       }
                       else {
                          
$headers[strtolower($h2[0])] = trim($h2[1]);
                       }
                   }
                   else {
                      
$headers[] = $header;
                   }
               }
           }
           return
$headers;
       }
       else {
           return
false;
       }
   }
?>
stuart at sixletterwords dot com 14-Sep-2005 07:52
hey, i came across this afew weeks ago and used the function in an app for recording info about domains that my company owns, and found that the status this returns was wrong most of the time (400 bad request or void for sites that were clearly online). then looking into it i noticed the problem was that it wasn't able to get the correct info about sites with redirections. but thats not the full problem because everything on my server was returning the wrong status too. i searched around on php.net for other info and found that fsockopen's example worked better and only needed some tweeking.

heres the function i put together from it and a small change.

<?
if(!function_exists('get_headers')) {
   function
get_headers($url,$format=0,$httpn=0){
   
$fp = fsockopen($url, 80, $errno, $errstr, 30);
    if (
$fp) {
      
$out = "GET / HTTP/1.1\r\n";
      
$out .= "Host: $url\r\n";
      
$out .= "Connection: Close\r\n\r\n";
      
fwrite($fp, $out);
       while (!
feof($fp)) {
          
$var.=fgets($fp, 1280);
       }

   
$var=explode("<",$var);
   
$var=$var[0];
   
$var=explode("\n",$var);
   
fclose($fp);
    return
$var;
    }
    }
}
?>

this returns an array of the header (only problem being that if the site doesn't have correct html it'll pull in some content too).

hope this'll help someone else.
sey at sey dot prometheus-designs dot net 27-Jul-2005 11:10
The replacement updated get_headers function by aeontech at gmail dot com improperly formats dates when $format = 1.

Replace:
<?
else {
$headers[strtolower($h2[0])] = trim($h2[1]);
}
?>

With:
<?
else {   
$foo = implode( ':', $h2 );
$foo = preg_replace( '/[a-zA-Z- ]*: /', '', $foo );
$headers[strtolower($h2[0])] = trim( $foo );
}
drfickle2 at yahoo dot com 27-Jul-2005 12:01
aeontech, this the below change adds support for SSL connections. Thanks for the code!

        if (isset($url_info['scheme']) && $url_info['scheme'] == 'https') {
            $port = 443;
            $fp=fsockopen('ssl://'.$url_info['host'], $port, $errno, $errstr, 30);
        } else {
           $port = isset($url_info['port']) ? $url_info['port'] : 80;
            $fp=fsockopen($url_info['host'], $port, $errno, $errstr, 30);
        }
15-Jul-2005 08:37
For anyone reading the previous comments, here is code that takes into account all the previous suggestions and includes a bugfix, too.

This code basically provides the "get_headers" function even on systems that are not running PHP 5.0.  It uses strtolower() on the keys, as suggested.  It uses the $h2 array instead of the $key, as suggested.  It removes a line about unsetting the $key -- no reason to unset something which is no longer used.  And I've changed the status header to be named "status" (instead of "0") in the array.  Note that if more than one header is returned without a label, they'll be stuck in "status" -- but I think status is the only header that comes back without a label, so it works for me.  So, first the code, then a sample of the usage:

<?php
if(!function_exists('get_headers')) {
  
/**
   * @return array
    * @param string $url
    * @param int $format
    * @desc Fetches all the headers
    * @author cpurruc fh-landshut de
    * @modified by dotpointer
    * @modified by aeontech
    */
   
function get_headers($url,$format=0) {
       
$url_info=parse_url($url);
       
$port = isset($url_info['port']) ? $url_info['port'] : 80;
       
$fp=fsockopen($url_info['host'], $port, $errno, $errstr, 30);
        if(
$fp) {
           
$head = "HEAD ".@$url_info['path']."?".@$url_info['query'];
           
$head .= " HTTP/1.0\r\nHost: ".@$url_info['host']."\r\n\r\n";
           
fputs($fp, $head);
            while(!
feof($fp)) {
                if(
$header=trim(fgets($fp, 1024))) {
                    if(
$format == 1) {
                       
$h2 = explode(':',$header);
                       
// the first element is the http header type, such as HTTP/1.1 200 OK,
                        // it doesn't have a separate name, so we have to check for it.
                       
if($h2[0] == $header) {
                           
$headers['status'] = $header;
                        }
                        else {
                           
$headers[strtolower($h2[0])] = trim($h2[1]);
                        }
                    }
                    else {
                       
$headers[] = $header;
                    }
                }
            }
            return
$headers;
        }
        else {
            return
false;
        }
    }
}
?>

OK?  Here's the usage:

<?php
$response
= get_headers('http://www.example.com/', 1);
if (!
$response) {
    echo
'Unable to initiate connection.';
}
else {
   
print_r($response);
}
?>
Chortos-2 03-Jun-2005 09:44
aeontech, I'd edit your function a little... How about replacing this:

<?
                       $key
= array_shift(explode(':',$header));
                      
// the first element is the http header type, such as HTTP 200 OK,
                       // it doesn't have a separate name, so we have to check for it.
                      
if($key == $header)
                       {
                          
$headers[] = $header;
                       }
                       else
                       {
                          
$headers[$key]=substr($header,strlen($key)+2);
                       }
?>

with this:

<?
                       $h2
= explode(':',$header);
                      
// the first element is the http header type, such as HTTP/1.1 200 OK,
                       // it doesn't have a separate name, so we have to check for it.
                      
if($h2[0] == $header)
                       {
                          
$headers[] = $header;
                       }
                       else
                       {
                          
$headers[ $h2[0] ] = trim($h2[1]);
                       }
?>

I think it looks a bit nicer :)
david at nothisbit dot futuresbright dot com 05-Apr-2005 11:03
After discovering that some webservers reply with "Content-Type" and others with "Content-type" I modified the function below to use strtolower($key) to make for easy checking against these case differences.
aeontech at gmail dot com 24-Dec-2004 01:20
In response to dotpointer's modification of Jamaz' solution...

Here is a small modification of your function, this adds the emulation of the optional $format parameter.

<?php
if(!function_exists('get_headers')) {
   
   
/**
    * @return array
    * @param string $url
    * @param int $format
    * @desc Fetches all the headers
    * @author cpurruc fh-landshut de
    * @modified by dotpointer
    * @modified by aeontech
    */
   
function get_headers($url,$format=0)
    {
       
$url_info=parse_url($url);
       
$port = isset($url_info['port']) ? $url_info['port'] : 80;
       
$fp=fsockopen($url_info['host'], $port, $errno, $errstr, 30);
       
        if(
$fp)
        {
           
$head = "HEAD ".@$url_info['path']."?".@$url_info['query']." HTTP/1.0\r\nHost: ".@$url_info['host']."\r\n\r\n";      
           
fputs($fp, $head);      
            while(!
feof($fp))
            {
                if(
$header=trim(fgets($fp, 1024)))
                {
                    if(
$format == 1)
                    {
                       
$key = array_shift(explode(':',$header));
                       
// the first element is the http header type, such as HTTP 200 OK,
                        // it doesn't have a separate name, so we have to check for it.
                       
if($key == $header)
                        {
                           
$headers[] = $header;
                        }
                        else
                        {
                           
$headers[$key]=substr($header,strlen($key)+2);
                        }
                        unset(
$key);
                    }
                    else
                    {
                       
$headers[] = $header;
                    }
                }
            }
            return
$headers;
        }
        else
        {
            return
false;
        }
    }
}
?>

 
show source | credits | sitemap | contact | advertising | mirror sites