How can I get the destination URL using cURL?
Solution 1
You can use:
echo curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
Solution 2
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, TRUE); // We'll parse redirect url from header.
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE); // We want to just get redirect url but not to follow it.
$response = curl_exec($ch);
preg_match_all('/^Location:(.*)$/mi', $response, $matches);
curl_close($ch);
echo !empty($matches[1]) ? trim($matches[1][0]) : 'No redirect found';
Solution 3
A bit dated of a response but wanted to show a full working example, some of the solutions out there are pieces:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url); //set url
curl_setopt($ch, CURLOPT_HEADER, true); //get header
curl_setopt($ch, CURLOPT_NOBODY, true); //do not include response body
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //do not show in browser the response
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); //follow any redirects
curl_exec($ch);
$new_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); //extract the url from the header response
curl_close($ch);
This works with any redirects such as 301 or 302, however on 404's it will just return the original url requested (since it wasn't found). This can be used to update or remove links from your site. This was my need anyway.
Solution 4
You have to grab the Location header for the redirected URL.
Solution 5
In response to user437797's comment on Tamik Soziev's answer (I unfortunately do not have the reputation to comment there directly) :
The CURLINFO_EFFECTIVE_URL works fine, but for it to do as op wants you also have to set CURLOPT_FOLLOWLOCATION to TRUE of course. This is because CURLINFO_EFFECTIVE_URL returns exactly what it says, the effective url that ends up getting loaded. If you don't follow redirects then this will be your requested url, if you do follow redirects then it will be the final url that is redirected to.
The nice thing about this approach is that it also works with multiple redirects, whereas when retrieving and parsing the HTTP header yourself you may have to do that multiple times before the final destination url is exposed.
Also note that the max number of redirects that curl follows can be controlled via CURLOPT_MAXREDIRS. By default it is unlimited (-1) but this may get you into trouble if someone (perhaps intentionally) configured and endless redirect loop for some url.
ahmed
Updated on February 19, 2020Comments
-
ahmed about 4 years
How can I get the destination URL using cURL when the HTTP status code is 302?
<?PHP $url = "http://www.ecs.soton.ac.uk/news/"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $html = curl_exec($ch); $status_code = curl_getinfo($ch,CURLINFO_HTTP_CODE); if($status_code=302 or $status_code=301){ $url = ""; // I want to to get the destination url } curl_close($ch); ?>
-
hakre about 12 yearsWhich needs further hassles, like checking if it is relative, resolving it (to the probably previous base URL in an intermediate redirection if there are multiple etc. pp.), it's just more easy to use
CURLINFO_EFFECTIVE_URL
. -
anonymous-one about 12 yearsThis method is a lot cleaner / generally better then parsing out the url from the Location header.
-
Achim Krauß over 11 yearsCURLINFO_EFFECTIVE_URL returns current (requested) page for me. There are no redirect (Location:) url in curl_getinfo results. It seems, to parse headers is the best practice...
-
ladieu about 11 yearsperfect! Thanks for sharing
-
Tomáš Zato over 9 yearsAnd if there's no location header?
-
Raptor about 9 yearsSometimes sites will use meta redirect or
window.location.replace
to redirect the page. In such case, replace the regular expression to capture the result. -
Raptor about 9 years
CURLINFO_EFFECTIVE_URL
is not always working for some cases, especially those without using header redirect. -
Admin over 7 yearsFor those who are getting current (requested) page, use this code after calling curl_exec($ch);
-
spekulatius over 4 yearsNice, much cleaner than parsing it myself. Thanks for sharing!