TL;DR
Use a custom function leveraging PHP's $_SERVER superglobal to build the full URL including protocol detection, host, port handling, and query string.
The problem
Sometimes you need to retrieve the complete URL of the current page in PHP. This might be for canonical URLs, redirects, logging, or sharing functionality. A standard URL has this format:
protocol://username:password@host:port/path?query#fragment
Note that credentials and fragments are typically excluded from PHP URL retrieval for security and technical reasons — the fragment (hash) is never sent to the server.
The solution
Here's a reliable function that handles HTTPS detection, non-standard ports, and the full request URI:
function get_current_url()
{
$url = false;
if (isset($_SERVER['SERVER_ADDR'])) {
// Detect HTTPS
$is_https = isset($_SERVER['HTTPS']) && 'on' == $_SERVER['HTTPS'];
$protocol = 'http' . ($is_https ? 's' : '');
// Get host (prefer HTTP_HOST for virtual hosts)
$host = isset($_SERVER['HTTP_HOST'])
? $_SERVER['HTTP_HOST']
: $_SERVER['SERVER_ADDR'];
// Get port
$port = $_SERVER['SERVER_PORT'];
// Get path and query string
$path_query = $_SERVER['REQUEST_URI'];
// Build the URL
$url = sprintf('%s://%s%s%s',
$protocol,
$host,
$is_https
? (443 != $port ? ':' . $port : '')
: (80 != $port ? ':' . $port : ''),
$path_query
);
}
return $url;
}
Key features
- HTTPS detection: Automatically detects if the request is over HTTPS
- Non-standard ports: Only includes port number when it's not the default (80 for HTTP, 443 for HTTPS)
- Query string included: Uses
REQUEST_URIwhich contains both path and query string - Graceful fallback: Returns
falseif not running as a web request (e.g., CLI)
Usage example
// Get the current URL
$current_url = get_current_url();
if ($current_url) {
echo "Current URL: " . $current_url;
// Output: https://example.com:8443/page?foo=bar
} else {
echo "Not running as web request";
}
Considerations
When using this in production, be aware of a few edge cases:
- Reverse proxies: If you're behind a load balancer or reverse proxy, you may need to check
X-Forwarded-ProtoandX-Forwarded-Hostheaders - Port in HTTP_HOST: Some servers include the port in
HTTP_HOST, which could lead to duplication - Security: Never trust
HTTP_HOSTfor security-critical operations without validation
Need help with PHP development? Let's talk.