Question

How to Get the Full Current URL in PHP

phpurl

Question

I want to get the full current URL in PHP exactly as it appears in the browser's address bar.

I currently use this code:

$actual_link = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];

However, this does not work correctly when I use URL rewriting rules in .htaccess, because the visible URL is not always the real file path on the server.

I need the URL exactly as the user sees it in the browser, including the rewritten path rather than the underlying server file path.

Short Answer

By the end of this page, you will understand how PHP builds the current request URL, why $_SERVER['PHP_SELF'] can be misleading with rewritten routes, and how to reliably get the full browser-visible URL using the correct server variables.

Concept

In PHP, the current URL is usually reconstructed from values in the $_SERVER superglobal. The important detail is that not all server variables represent the same thing.

For example:

  • $_SERVER['PHP_SELF'] often points to the executing script path.
  • $_SERVER['REQUEST_URI'] contains the path and query string that the browser actually requested.
  • $_SERVER['HTTP_HOST'] contains the requested host name.
  • $_SERVER['HTTPS'] helps determine whether the request used http or https.

This matters because URL rewriting tools such as Apache .htaccess rules can map a friendly URL like:

/products/42

to a real server file such as:

/index.php?id=42

If you use PHP_SELF, you may get the script path instead of the URL the user typed or clicked. If you want the browser-visible URL, REQUEST_URI is usually the correct choice.

A common way to build the full URL is:

$url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http')
    . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

This works because:

  • the scheme comes from HTTPS
  • the domain comes from HTTP_HOST
  • the visible path and query come from REQUEST_URI

In real programming, understanding these differences is important for:

  • redirects
  • canonical URLs
  • logging requests
  • debugging routing issues
  • generating links back to the current page

Mental Model

Think of a web request like a package delivery label:

  • HTTP_HOST is the building name.
  • REQUEST_URI is the apartment number and any delivery instructions.
  • PHP_SELF is the internal office room where the package was actually processed.

If you want to know what the visitor asked for, use the delivery label they wrote: REQUEST_URI.

If you want to know which PHP file handled it internally, use something like PHP_SELF.

With URL rewriting, those two can be different.

Take Quiz

Syntax and Examples

The most common beginner-friendly approach is:

<?php
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$url = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

echo $url;

Example

If the browser shows:

https://example.com/blog/php?sort=new

then the variables are commonly like this:

  • $_SERVER['HTTPS'] -> on
  • $_SERVER['HTTP_HOST'] -> example.com
  • $_SERVER['REQUEST_URI'] -> /blog/php?sort=new

So the final result becomes:

https://example.com/blog/php?sort=new

Why PHP_SELF is different

<?php
echo $_SERVER['PHP_SELF'];

This may output something like:

/index.php

That is the script being executed, not necessarily the friendly URL requested by the user.

Safer reusable function

<?php
function getCurrentUrl(): string
{
    $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
    $host = $_SERVER['HTTP_HOST'] ?? 'localhost';
    $uri = $_SERVER['REQUEST_URI'] ?? '/';

    return $scheme . '://' . $host . $uri;
}

echo getCurrentUrl();

This version adds fallback values so your code is less fragile.

Step by Step Execution

Consider this code:

<?php
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'];
$uri = $_SERVER['REQUEST_URI'];
$currentUrl = $scheme . '://' . $host . $uri;

echo $currentUrl;

Assume the browser requested:

https://shop.example.com/products/15?page=2

Step-by-step

  1. PHP checks $_SERVER['HTTPS'].

    • It is set and not equal to 'off'.
    • So $scheme becomes 'https'.
  2. PHP reads $_SERVER['HTTP_HOST'].

    • $host becomes 'shop.example.com'.
  3. PHP reads $_SERVER['REQUEST_URI'].

    • $uri becomes '/products/15?page=2'.
  4. PHP concatenates the parts:

$currentUrl = 'https' . '://' . 'shop.example.com' . '/products/15?page=2';
  1. Final result:
https://shop.example.com/products/15?page=2

Rewritten URL example

Suppose Apache internally routes this request to:

/index.php?product=15&page=2

Even if that is the real server-side target, REQUEST_URI still reflects the URL requested by the browser:

/products/15?page=2

That is why it is the better choice for this problem.

Real World Use Cases

Getting the full current URL is useful in many real applications:

  • Redirect back after login

    • Store the current page so users return to it after authenticating.
  • Canonical URL generation

    • Build the preferred page URL for SEO.
  • Analytics and logging

    • Save the exact requested URL for debugging or traffic reports.
  • Sharing links

    • Generate a copyable link to the current page.
  • Pagination and filters

    • Preserve the current path and query string when building navigation links.
  • Error reporting

    • Include the exact request URL in logs when something fails.

Example logging use:

<?php
error_log('User visited: ' . getCurrentUrl());
Take Quiz

Real Codebase Usage

In real projects, developers usually do not build URLs inline everywhere. Instead, they wrap the logic in a helper function or service.

Common patterns include:

Guard clauses for missing values

<?php
function getCurrentUrl(): string
{
    if (empty($_SERVER['HTTP_HOST']) || empty($_SERVER['REQUEST_URI'])) {
        return '';
    }

    $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
    return $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
}

Validation before redirects

Developers often use the current URL as a return_url, but validate it first to avoid unsafe redirects.

<?php
$returnUrl = getCurrentUrl();

if ($returnUrl !== '') {
    $_SESSION['return_url'] = $returnUrl;
}

Query string preservation

When building filtered pages, teams often read REQUEST_URI to keep the original query string intact.

Framework abstraction

In modern codebases, frameworks often provide a request object instead of direct $_SERVER access. But underneath, the same idea applies: use the browser-requested URI, not the physical file path.

Error handling and diagnostics

Many applications log the requested URL during exceptions so debugging is easier:

<?php
try {
    // application code
} catch (Throwable $e) {
    error_log('Error on URL: ' . getCurrentUrl());
    throw $e;
}

Common Mistakes

1. Using PHP_SELF for the visible URL

Broken example:

<?php
$url = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];

Why it is a problem:

  • PHP_SELF may point to the executing script.
  • It may not match the rewritten route the user sees.

Use this instead:

<?php
$url = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

2. Hardcoding http

Broken example:

<?php
$url = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

Why it is a problem:

  • It gives the wrong result on HTTPS pages.

Better:

<?php
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$url = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

3. Forgetting the query string

Broken example:

<?php
$url = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];

Why it is a problem:

  • Query parameters like ?page=2 are lost.
  • REQUEST_URI includes them.

4. Assuming all $_SERVER keys always exist

Broken example:

<?php
$url = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

Why it is a problem:

  • In some environments, values may be missing.
  • This can trigger notices.

Safer version:

<?php
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
$uri = $_SERVER['REQUEST_URI'] ?? '/';

5. Trusting the URL for security decisions

Why it is a problem:

  • Request values come from the client and environment.
  • Do not assume they are safe for redirects, HTML output, or access control without validation and escaping.

Comparisons

Variable / ApproachWhat it representsIncludes query string?Good for browser-visible URL?
$_SERVER['PHP_SELF']Executing script pathNoNo
$_SERVER['REQUEST_URI']Requested path from browserYesYes
$_SERVER['SCRIPT_NAME']Script filename pathNoNo
$_SERVER['HTTP_HOST']Host name from requestNoOnly as one part
$_SERVER['QUERY_STRING']Only the query partYes, but only queryNo

PHP_SELF vs REQUEST_URI

  • Use PHP_SELF when you need the script path being executed.
  • Use REQUEST_URI when you need the path the browser requested.

HTTP_HOST vs SERVER_NAME

  • HTTP_HOST usually reflects the host requested by the client.
  • SERVER_NAME may reflect server configuration instead.
  • For reconstructing the current URL, HTTP_HOST is commonly preferred.

Full URL formula

$fullUrl = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

This is usually the closest match to what the browser shows.

Take Quiz

Cheat Sheet

$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$fullUrl = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

Quick rules

  • Use REQUEST_URI for the browser-requested path.
  • Do not use PHP_SELF if URL rewriting is involved.
  • Use HTTPS to detect http vs https.
  • Use HTTP_HOST for the domain part.
  • REQUEST_URI usually includes the query string.

Common variables

  • $_SERVER['HTTP_HOST'] -> host/domain
  • $_SERVER['REQUEST_URI'] -> path + query string
  • $_SERVER['PHP_SELF'] -> executing script path
  • $_SERVER['QUERY_STRING'] -> query only
  • $_SERVER['HTTPS'] -> whether HTTPS is active

Safe helper

function getCurrentUrl(): string
{
    $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
    $host = $_SERVER['HTTP_HOST'] ?? 'localhost';
    $uri = $_SERVER['REQUEST_URI'] ?? '/';

    return $scheme . '://' . $host . $uri;
}

Watch out for

  • rewritten routes
  • missing server keys
  • hardcoded http
  • using request data without validation

FAQ

How do I get the current full URL in PHP?

Use HTTP_HOST, REQUEST_URI, and the request scheme:

$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$url = $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];

Why is $_SERVER['PHP_SELF'] not giving the visible URL?

PHP_SELF usually points to the script being executed on the server, not the rewritten or friendly URL requested by the browser.

Does REQUEST_URI include the query string?

Yes, it usually includes both the path and the query string, such as /products?page=2.

How do I detect HTTPS in PHP?

A common check is:

!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'

Should I use HTTP_HOST or SERVER_NAME?

For reconstructing the requested URL, HTTP_HOST is commonly more appropriate because it reflects the host sent by the client.

Can URL rewriting change what PHP_SELF returns?

Yes. With rewritten routes, the public URL and the internal script path can be different, which is exactly why REQUEST_URI is often the better choice.

Is the current URL safe to output directly in HTML?

Not always. If you print it into a page, escape it first with htmlspecialchars().

Can I use this approach in frameworks?

Yes, but frameworks often provide a request object with methods for getting the current URL, path, and query string more cleanly.

Take Quiz

Mini Project

Description

Build a small PHP page that displays the exact current URL requested by the browser. This demonstrates how to combine scheme, host, and request URI correctly, even when friendly URLs or rewritten routes are used.

Goal

Create a reusable PHP function that prints the full current URL exactly as the user requested it.

Requirements

  1. Create a function that returns the current full URL.
  2. Detect whether the request uses HTTP or HTTPS.
  3. Include the host name and full request URI.
  4. Print the URL on the page.
  5. Handle missing server values with sensible fallbacks.
Take Quiz

Keep learning

Related questions

View more