Full URL in PHP: How to Get It Quickly and Without Errors

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Get the full URL in PHP: How Not to Reinvent the Wheel and Lose Performance

\n\n

Every PHP developer sooner or later faces the task: "How do I get the full URL of the current page?" It seems simple enough — take $_SERVER['REQUEST_URI'], add the domain, and you're done. But the devil, as always, is in the details. The question "Get the full URL in PHP" on Stack Overflow has gathered thousands of views and dozens of answers. And for good reason.

\n\n

In this article, we'll break down how to get the full URL in PHP correctly, quickly, and without bugs. You'll learn the difference between HTTP_HOST and SERVER_NAME, how to correctly determine the protocol (HTTPS or HTTP), and why you shouldn't blindly copy code from the internet. Let's go!

\n\n

Why the Simple Way Isn't Always the Best

\n\n

The most obvious option looks like this:

\n\n
<?php\n$fullUrl = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];\n?>
\n\n

This code works, but only if you have:

\n
    \n
  • Definitely HTTP (not HTTPS)
  • \n
  • No port other than 80 or 443
  • \n
  • The server correctly passes the Host header
  • \n
\n\n

In the real world, these conditions are not always met. If the site runs over HTTPS, you'll get a URL with http://, which will cause a mixed content error in the browser. If the port is non-standard (e.g., 8080), it will be lost. And if an attacker spoofs the Host header, you could get a URL pointing to a different domain.

\n\n

Components of a Full URL: A Breakdown

\n\n

Before writing a universal solution, let's recall what a full URL consists of:

\n\n
scheme://host:port/path?query#fragment
\n\n

In PHP, we have access to the following elements from the superglobal array $_SERVER:

\n
    \n
  • scheme — protocol (HTTP or HTTPS). There is no direct key, but it can be determined via $_SERVER['HTTPS'] or $_SERVER['REQUEST_SCHEME'] (available since PHP 7.4).
  • \n
  • host — domain. There are two candidates: HTTP_HOST (from the Host header) and SERVER_NAME (from the server configuration).
  • \n
  • port — port. $_SERVER['SERVER_PORT']. If the port is standard (80 for HTTP, 443 for HTTPS), it can be omitted.
  • \n
  • path — path. $_SERVER['REQUEST_URI'] contains the path and query string.
  • \n
  • query — query string. Can be obtained separately via $_SERVER['QUERY_STRING'].
  • \n
  • fragment — anchor. It is not sent to the server, so it cannot be obtained.
  • \n
\n\n

The Correct Solution: The getFullUrl() Function

\n\n

Here is a reliable and performant way to get the full URL in PHP:

\n\n
<?php\nfunction getFullUrl(): string {\n    // Determine the protocol\n    $scheme = 'http';\n    if (\n        (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] === 'on' || $_SERVER['HTTPS'] === '1'))\n        || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https')\n    ) {\n        $scheme = 'https';\n    }\n\n    // Host: prefer HTTP_HOST, but check for emptiness\n    $host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'localhost';\n\n    // Port: add only if non-standard\n    $port = (int) ($_SERVER['SERVER_PORT'] ?? 80);\n    $portStr = '';\n    if (\n        ($scheme === 'http' && $port !== 80) ||\n        ($scheme === 'https' && $port !== 443)\n    ) {\n        $portStr = ':' . $port;\n    }\n\n    // URI\n    $uri = $_SERVER['REQUEST_URI'] ?? '/';\n\n    return $scheme . '://' . $host . $portStr . $uri;\n}\n?>
\n\n

This function accounts for:

\n
    \n
  • HTTPS protocol (including through proxy servers with the X-Forwarded-Proto header).
  • \n
  • Non-standard ports.
  • \

Blogs

Book Recommendations