How To Get Redirect URL In PHP

HTTP redirects usually have the response status 301 or 302 and provide the redirection URL in the “Location” header. I’ve written three complementary PHP functions that you can use to find out where an URL redirects to (based on a helpful thread at WebmasterWorld). You don’t even need CURL for this – fsockopen() will do just fine.

The PHP script

/**
 * get_redirect_url()
 * Gets the address that the provided URL redirects to,
 * or FALSE if there's no redirect. 
 *
 * @param string $url
 * @return string
 */
function get_redirect_url($url){
	$redirect_url = null; 

	$url_parts = @parse_url($url);
	if (!$url_parts) return false;
	if (!isset($url_parts['host'])) return false; //can't process relative URLs
	if (!isset($url_parts['path'])) $url_parts['path'] = '/';
	 
	$sock = fsockopen($url_parts['host'], (isset($url_parts['port']) ? (int)$url_parts['port'] : 80), $errno, $errstr, 30);
	if (!$sock) return false;
	 
	$request = "HEAD " . $url_parts['path'] . (isset($url_parts['query']) ? '?'.$url_parts['query'] : '') . " HTTP/1.1\r\n"; 
	$request .= 'Host: ' . $url_parts['host'] . "\r\n"; 
	$request .= "Connection: Close\r\n\r\n"; 
	fwrite($sock, $request);
	$response = '';
	while(!feof($sock)) $response .= fread($sock, 8192);
	fclose($sock);

	if (preg_match('/^Location: (.+?)$/m', $response, $matches)){
		if ( substr($matches[1], 0, 1) == "/" )
			return $url_parts['scheme'] . "://" . $url_parts['host'] . trim($matches[1]);
		else
			return trim($matches[1]);
 
	} else {
		return false;
	}
	
}

/**
 * get_all_redirects()
 * Follows and collects all redirects, in order, for the given URL. 
 *
 * @param string $url
 * @return array
 */
function get_all_redirects($url){
	$redirects = array();
	while ($newurl = get_redirect_url($url)){
		if (in_array($newurl, $redirects)){
			break;
		}
		$redirects[] = $newurl;
		$url = $newurl;
	}
	return $redirects;
}

/**
 * get_final_url()
 * Gets the address that the URL ultimately leads to. 
 * Returns $url itself if it isn't a redirect.
 *
 * @param string $url
 * @return string
 */
function get_final_url($url){
	$redirects = get_all_redirects($url);
	if (count($redirects)>0){
		return array_pop($redirects);
	} else {
		return $url;
	}
}

Here’s an example that lists all URLs that a given address redirects to (in order) :

$rez = get_all_redirects('http://daerils.gtrends.hop.clickbank.net/');
print_r($rez);

Known Issues

Most likely you won’t ever run into one of these, but here they are anyway :

  • The script doesn’t recognize infinite redirects that don’t form a loop. However, it can handle normal redirection loops – get_all_redirects() exits as soon as it encounters an URL that it has already seen.
  • Relative redirects multiple (e.g. “Location: go.php?asdf”) won’t be fully followed by get_all_redirects().
  • Not an issue per-se, yet something to note : these functions won’t tell you if an URL is valid, just what it redirects to (if anything).

On a related note, check out the Firefox extension Redirect Remover.

Related posts :

58 Responses to “How To Get Redirect URL In PHP”

  1. Sadik says:

    Thanks a million… You saved me the coding :)

  2. Ravishankar says:

    Returning back to comment 26 above my Manish, the URL he mentions consists of (note the secure protocol) https://…..

    So, if the URL contains https://, the above codes does not seem to work. I’m facing the same issue.. any help?

    Ravi.

  3. White Shadow says:

    To check HTTPS URLs, you would need to rewrite the script to use something like curl.

  4. Itzekocke says:

    Thanks,

    that little function helped a lot!

    Itzekocke

  5. Johnny Tsunami says:

    Good stuff! You helped me, too.

  6. Prasenjit Das says:

    This helps me a lot.Many thanks.

  7. Ruth says:

    Hi
    Worked for many sites, but did not work for http://www.oldcastle.com/.
    Can anyone find a solution for this.
    Thanks,
    Ruth.

  8. Hello there, simply become aware of your blog through Google, and located that it’s truly informative. I am going to be careful for brussels. I will be grateful if you continue this in future. A lot of other people will be benefited from your writing. Cheers!

  9. Michel says:

    This script works great!
    Only thing I was wondering is, if it is possible to check the final url with the given redirected url.

    Let me give an example:

    I want example.com/1
    To redirect to example.com/2

    With this script I created that I can manually check if the url is correct. But if I have a lot more redirects to check, I would like to handle that automatically like:

    I redirected it to example.com/2 now when I run this script, what I would like it to do.

    I give an array with the redirect from urls (example.com/1)
    And at the check I want it to check if example.com/1 really does go to example.com/2.

    I’m not really an expert in PHP so I hope you can give an answer.

    Thanks,
    Michel

  10. Christoph says:

    Thanks!

    I’ve need it for my new Facebook App… :)

  11. Alex says:

    THANKS … very thanks

  12. Khoa NĐ says:

    Thanks. It’s amazing.

  13. Andre says:

    It doesn’t work with ampersands in the url.

  14. Lennart says:

    To use with ampersands urlencode the URL first.

  15. romuald says:

    I do a cmd c cmd v run it ! it works !

    BIG THANKS

  16. Rafael says:

    I needed to handle https, and did not have to change much in the function:

    function get_redirect_url($url){
        $redirect_url = null; 
    
        $url_parts = @parse_url($url);
        if (!$url_parts) return false;
        if (!isset($url_parts['host'])) return false; //can't process relative URLs
        if (!isset($url_parts['path'])) $url_parts['path'] = '/';
    	$url_host = $url_parts['host'];
    	if (isset($url_parts['scheme']) && $url_parts['scheme'] == 'https') {
    		$url_host = 'ssl://' . $url_host;
    		$url_default_port = 443;
    	} else {
    		$url_default_port = 80;
    	}
        $sock = fsockopen($url_host, (isset($url_parts['port']) ? (int)$url_parts['port'] : $url_default_port), $errno, $errstr, 30);
        if (!$sock) return false;
    
        $request = "HEAD " . $url_parts['path'] . (isset($url_parts['query']) ? '?'.$url_parts['query'] : '') . " HTTP/1.1\r\n"; 
        $request .= 'Host: ' . $url_parts['host'] . "\r\n"; 
        $request .= "Connection: Close\r\n\r\n"; 
        fwrite($sock, $request);
        $response = '';
        while(!feof($sock)) $response .= fread($sock, 8192);
        fclose($sock);
    
        if (preg_match('/^Location: (.+?)$/m', $response, $matches)){
            if ( substr($matches[1], 0, 1) == "/" )
                return $url_parts['scheme'] . "://" . $url_parts['host'] . trim($matches[1]);
            else
                return trim($matches[1]);
    
        } else {
            return false;
        }
    
    }
    

    I did have curl and openssl enabled, mind you.

Leave a Reply