When a PHP script needs to know how it was requested, $_SERVER is usually the first place to look. It can tell you the request method, requested URI, script path, server name, client IP address and selected HTTP headers.
The array is useful, but its name can be slightly misleading. Not every value comes from the server. Some values originate from the browser or another HTTP client and can be changed by the requester. Treating the entire array as trusted server data is an easy mistake to make, and PHP has kindly left that trap available for all of us.
$_SERVER is a predefined associative array and one of PHP’s superglobal variables. It is available inside functions and methods without using the global keyword.
Quick answer
Use a key such as $_SERVER['REQUEST_METHOD'] to read a specific value. Because available keys depend on the web server, PHP configuration and execution environment, check optional keys before accessing them.
<?php
$requestMethod = $_SERVER['REQUEST_METHOD'] ?? 'UNKNOWN';
$requestUri = $_SERVER['REQUEST_URI'] ?? '/';
$serverName = $_SERVER['SERVER_NAME'] ?? 'localhost';
echo htmlspecialchars($requestMethod, ENT_QUOTES, 'UTF-8');
echo '<br>';
echo htmlspecialchars($requestUri, ENT_QUOTES, 'UTF-8');
echo '<br>';
echo htmlspecialchars($serverName, ENT_QUOTES, 'UTF-8');
The null coalescing operator prevents an undefined array key warning when a value is unavailable. Escaping the output is also important because values such as the requested URI and HTTP headers may contain client-controlled data. The htmlspecialchars() function converts special characters to HTML entities and is commonly used when displaying external data in HTML output.
The complete list of recognised keys is available in the official PHP $_SERVER documentation. In practice, most applications use only a small group of them.
PHP documents these predefined variables in the PHP superglobals reference.
Inspect the available $_SERVER values
The fastest way to see what your current environment provides is to print the array during local development:
<?php
echo '<pre>';
print_r($_SERVER);
echo '</pre>';
The output varies between Apache, Nginx with PHP-FPM, PHP’s built-in development server and command-line execution. Header-related keys may also change from one request to another.
Do not leave this diagnostic output on a public website. It may expose document paths, server software details, request headers and other information that should not be shown to visitors. For a broader configuration check, use phpinfo() temporarily in a protected development environment.
Common PHP $_SERVER variables
The exact contents of $_SERVER depend on the server and request. The following keys are commonly available in web applications.
| Variable | Typical value | Purpose |
|---|---|---|
REQUEST_METHOD |
GET or POST |
Identifies the HTTP request method. |
REQUEST_URI |
/products.php?id=25 |
Contains the requested path and query string. |
QUERY_STRING |
id=25 |
Contains the raw query-string portion of the URL. |
SCRIPT_NAME |
/products.php |
Provides the path of the executing script relative to the document root. |
SCRIPT_FILENAME |
/var/www/html/products.php |
Provides the absolute filesystem path of the executing script. |
DOCUMENT_ROOT |
/var/www/html |
Contains the server document-root directory. |
SERVER_NAME |
example.com |
Identifies the configured server name. |
SERVER_PORT |
80 or 443 |
Contains the port used for the request. |
HTTPS |
on |
May indicate that the request used HTTPS. |
REMOTE_ADDR |
203.0.113.10 |
Contains the IP address that connected directly to the web server. |
HTTP_HOST |
example.com |
Contains the client-supplied Host header. |
HTTP_USER_AGENT |
Browser identification string | Contains the client-supplied user-agent header. |
HTTP_REFERER |
https://example.com/page |
May contain the URL of the referring page. |
Values beginning with HTTP_ usually represent request headers. They are supplied by the client and must not be treated as trusted values.
Check the HTTP request method
REQUEST_METHOD is commonly used to decide whether a form has been submitted. Comparing the value explicitly keeps the request-handling logic easy to read.
<?php
$requestMethod = $_SERVER['REQUEST_METHOD'] ?? '';
if ($requestMethod === 'POST') {
echo 'The form was submitted.';
}
Request methods are uppercase values such as GET, POST, PUT, PATCH and DELETE. A normal HTML form directly supports only GET and POST, while API clients can send the other methods.
For more details about how these methods work in PHP, see the guide on PHP request methods.
Checking the method tells you how the request was sent. It does not validate the submitted data. Continue to validate each value from $_POST, $_GET or the request body before using it.
Get the requested URL path
REQUEST_URI contains the path requested by the client, including the query string when one is present.
<?php
$requestUri = $_SERVER['REQUEST_URI'] ?? '/';
echo htmlspecialchars($requestUri, ENT_QUOTES, 'UTF-8');
For a request such as https://example.com/products.php?id=25, the value is typically:
/products.php?id=25
To work with only the path, parse the value instead of manually splitting it at the question mark.
<?php
$requestUri = $_SERVER['REQUEST_URI'] ?? '/';
$requestPath = parse_url($requestUri, PHP_URL_PATH);
if (!is_string($requestPath)) {
$requestPath = '/';
}
echo htmlspecialchars($requestPath, ENT_QUOTES, 'UTF-8');
This approach returns /products.php and leaves the query parameters to be handled separately.
Build the current URL carefully
PHP does not provide one $_SERVER key containing the complete current URL. It must be assembled from the scheme, host and request URI.
<?php
$isHttps = isset($_SERVER['HTTPS'])
&& $_SERVER['HTTPS'] !== ''
&& strtolower($_SERVER['HTTPS']) !== 'off';
$scheme = $isHttps ? 'https' : 'http';
$host = $_SERVER['SERVER_NAME'] ?? 'localhost';
$requestUri = $_SERVER['REQUEST_URI'] ?? '/';
$currentUrl = $scheme . '://' . $host . $requestUri;
echo htmlspecialchars($currentUrl, ENT_QUOTES, 'UTF-8');
SERVER_NAME is generally safer than directly using HTTP_HOST because HTTP_HOST comes from the client-supplied Host header. However, the exact behaviour of SERVER_NAME depends on the web server configuration.
For applications that already know their public domain, using a configured base URL is more reliable than reconstructing it from request data.
<?php
$baseUrl = 'https://example.com';
$requestUri = $_SERVER['REQUEST_URI'] ?? '/';
$currentUrl = $baseUrl . $requestUri;
This avoids host-header injection and also works more predictably behind reverse proxies, load balancers and containers.
Detect HTTPS requests
A common check is to inspect $_SERVER['HTTPS']. The key is often set to on for HTTPS requests, but its presence and value depend on the server setup.
<?php
$isHttps = isset($_SERVER['HTTPS'])
&& $_SERVER['HTTPS'] !== ''
&& strtolower($_SERVER['HTTPS']) !== 'off';
if ($isHttps) {
echo 'Secure request';
}
Do not rely only on SERVER_PORT === '443'. HTTPS can run on a different port, and a reverse proxy may connect to PHP over HTTP after terminating TLS itself.
When the application runs behind a trusted proxy, HTTPS information may be supplied through a header such as X-Forwarded-Proto. Do not trust that header from arbitrary clients. Configure the application or framework with a list of trusted proxies before using forwarded headers.
Get the executing script and filesystem path
Several $_SERVER keys look similar but describe different paths.
<?php
$scriptName = $_SERVER['SCRIPT_NAME'] ?? '';
$scriptFilename = $_SERVER['SCRIPT_FILENAME'] ?? '';
$documentRoot = $_SERVER['DOCUMENT_ROOT'] ?? '';
echo htmlspecialchars($scriptName, ENT_QUOTES, 'UTF-8');
echo '<br>';
echo htmlspecialchars($scriptFilename, ENT_QUOTES, 'UTF-8');
echo '<br>';
echo htmlspecialchars($documentRoot, ENT_QUOTES, 'UTF-8');
SCRIPT_NAME is normally a web path such as /admin/report.php. SCRIPT_FILENAME is the absolute filesystem path of the executing script. DOCUMENT_ROOT points to the configured web root.
For including files relative to the current PHP file, prefer __DIR__ instead of building paths from DOCUMENT_ROOT.
<?php
require __DIR__ . '/includes/config.php';
__DIR__ is based on the file’s actual location. It remains reliable when the application is moved to another document root or executed from the command line.
Read request headers from $_SERVER
Many HTTP request headers appear in $_SERVER with an HTTP_ prefix. Header names are converted to uppercase, and hyphens usually become underscores.
For example, the request header User-Agent is commonly available as HTTP_USER_AGENT.
<?php
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown client';
echo htmlspecialchars($userAgent, ENT_QUOTES, 'UTF-8');
Custom headers follow the same general pattern. A header named X-Request-ID may appear as HTTP_X_REQUEST_ID.
<?php
$requestId = $_SERVER['HTTP_X_REQUEST_ID'] ?? '';
if ($requestId !== '') {
echo htmlspecialchars($requestId, ENT_QUOTES, 'UTF-8');
}
Header values are client-controlled unless a trusted server or proxy replaces them. Validate their format before using them in redirects, logs, database queries or security decisions.
Get the client IP address
REMOTE_ADDR contains the IP address that connected directly to the web server.
<?php
$clientIp = $_SERVER['REMOTE_ADDR'] ?? '';
if ($clientIp !== '' && filter_var($clientIp, FILTER_VALIDATE_IP)) {
echo htmlspecialchars($clientIp, ENT_QUOTES, 'UTF-8');
}
This may be the visitor’s address, but not always. When the application is behind a reverse proxy, CDN or load balancer, REMOTE_ADDR may contain the proxy’s IP address instead.
Headers such as X-Forwarded-For are often used to preserve the original client address. However, a client can send this header directly. Do not trust it unless the request came through a proxy that you control and have explicitly configured as trusted.
A forwarded address can also contain a comma-separated chain of IP addresses, so simply reading the first value is not a safe universal solution. Client IP detection should follow the rules of your hosting and proxy setup.
Check the referring page
HTTP_REFERER may contain the URL of the page that linked to the current request.
<?php
$referer = $_SERVER['HTTP_REFERER'] ?? '';
if ($referer !== '') {
echo htmlspecialchars($referer, ENT_QUOTES, 'UTF-8');
}
The key name contains the historical misspelling REFERER, which is also used by the HTTP header.
This value is optional. Browsers, privacy tools and referrer policies may remove or shorten it. A client can also forge it. Use it for non-critical analytics or navigation hints, not for authentication, authorization or CSRF protection.
Avoid undefined array key warnings
Not every $_SERVER key exists in every environment. Direct access can produce an undefined array key warning.
<?php
$userAgent = $_SERVER['HTTP_USER_AGENT'];
Use the null coalescing operator when a sensible default is available.
<?php
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown client';
Use isset() when the code should run only if the key exists.
<?php
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
$acceptLanguage = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
}
For required values, validate the value instead of silently accepting a fallback that could hide a configuration problem.
<?php
$requestMethod = $_SERVER['REQUEST_METHOD'] ?? '';
if ($requestMethod === '') {
throw new RuntimeException('The request method is unavailable.');
}
Do not trust $_SERVER values automatically
The $_SERVER array mixes values from different sources. Some come from the server configuration, while others come from the HTTP request.
Common client-controlled values include:
HTTP_HOSTHTTP_USER_AGENTHTTP_REFERERREQUEST_URI- Most custom
HTTP_*headers
Validate values according to how they will be used. Escape them before rendering HTML, validate URLs before redirects, validate IP addresses before storing them and avoid placing raw request values into response headers.
For example, this redirect is unsafe because the destination comes directly from the request:
<?php
header('Location: ' . $_SERVER['HTTP_REFERER']);
exit;
A safer approach is to redirect only to known application paths.
<?php
$allowedPaths = [
'/account.php',
'/dashboard.php'
];
$redirectPath = '/';
if (isset($_GET['return']) && in_array($_GET['return'], $allowedPaths, true)) {
$redirectPath = $_GET['return'];
}
header('Location: ' . $redirectPath);
exit;
The important rule is simple: being inside $_SERVER does not make a value safe.
Common mistakes when using $_SERVER
$_SERVER is simple to use, but a few mistakes appear frequently in real projects.
Assuming every key exists
A script that works perfectly on one server may show warnings on another because the available keys depend on the environment.
For example, HTTP_USER_AGENT may not exist when a request does not include that header.
<?php
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown';
Using a fallback value keeps the application predictable.
Using HTTP_HOST without validation
HTTP_HOST is useful when you need the requested domain name, but it comes from the HTTP request.
<?php
$host = $_SERVER['HTTP_HOST'] ?? '';
echo $host;
Do not use it directly for security-sensitive operations such as generating password reset links, redirects or access-control decisions.
For applications that need a fixed public domain, store it in configuration instead:
<?php
$baseUrl = 'https://example.com';
Using REMOTE_ADDR as a guaranteed real visitor IP
REMOTE_ADDR gives the address of the direct connection to your server. If your application sits behind Cloudflare, a load balancer or another proxy, it may not be the original visitor address.
Before using forwarded headers such as X-Forwarded-For, understand your hosting architecture and trust only headers added by your own infrastructure.
Displaying raw values in HTML
Some $_SERVER values contain data supplied by the client. Printing them directly can create cross-site scripting risks.
Always escape output that is displayed in HTML:
<?php
$value = $_SERVER['REQUEST_URI'] ?? '/';
echo htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
This is commonly done using PHP’s htmlentities() function when displaying user-controlled text.
Using $_SERVER in form handling
A common use case is detecting whether a page request is the first page load or a form submission.
For example, a registration page can display the form during a GET request and process submitted data during a POST request.
<?php
if (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
$name = $_POST['name'] ?? '';
echo 'Processing registration for: ';
echo htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
exit;
}
?>
<form method="post">
<label>
Name:
<input type="text" name="name">
</label>
<button type="submit">Submit</button>
</form>
The request method check only tells you how the request arrived. It does not make the submitted data safe. Always validate and sanitize user input based on how it will be used. For handling external data safely, see the PHP guide on input filtering.
$_SERVER vs $_REQUEST
Both variables may look similar, but they serve different purposes.
| Variable | Purpose |
|---|---|
$_SERVER |
Contains request and server-related information such as headers, paths and request methods. |
$_GET |
Contains values sent through URL query parameters. |
$_POST |
Contains values submitted through POST requests. |
$_REQUEST |
Combines input from multiple sources based on PHP configuration. |
Avoid using $_REQUEST when the source of data matters. Reading from $_GET and $_POST explicitly makes the code easier to understand and maintain.
Useful $_SERVER examples
In day-to-day PHP development, you usually need only a handful of $_SERVER values. The following examples cover some practical cases.
Allow only POST requests
For pages that should process submitted data only, checking the request method prevents accidental execution through a direct URL visit.
<?php
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
http_response_code(405);
exit('Method not allowed');
}
// Process submitted data here
This is useful for form handlers and simple API endpoints.
Get the current script name
SCRIPT_NAME can be useful when creating navigation links or highlighting the current page.
<?php
$currentPage = $_SERVER['SCRIPT_NAME'] ?? '';
echo htmlspecialchars($currentPage, ENT_QUOTES, 'UTF-8');
For more complex routing systems, it is usually better to use the application’s router instead of relying on the physical script name.
Check whether a request is AJAX
Older PHP applications often check the X-Requested-With header to identify AJAX requests.
<?php
$isAjax = isset($_SERVER['HTTP_X_REQUESTED_WITH'])
&& strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
if ($isAjax) {
echo 'AJAX request';
}
This is only a request hint. Any client can send the same header manually, so do not use it as a security check.
Detect the server protocol
SERVER_PROTOCOL contains the HTTP protocol version used for the request.
<?php
$protocol = $_SERVER['SERVER_PROTOCOL'] ?? '';
echo htmlspecialchars($protocol, ENT_QUOTES, 'UTF-8');
A typical value is:
HTTP/1.1
Modern applications rarely need to inspect this value directly, but it can be useful when debugging server behaviour.
Frequently asked questions
Is $_SERVER available in all PHP scripts?
$_SERVER is available in web requests and command-line scripts, but the available values differ. A browser request contains HTTP-related information, while a CLI execution may not contain values such as HTTP_HOST or REMOTE_ADDR.
How can I print all $_SERVER variables?
Use print_r() during local development:
<?php
echo '<pre>';
print_r($_SERVER);
echo '</pre>';
Avoid displaying this output on production servers because it can reveal internal information.
What is the difference between SERVER_NAME and HTTP_HOST?
SERVER_NAME comes from the server configuration, while HTTP_HOST comes from the request header sent by the client.
HTTP_HOST is useful when you need the domain requested by the visitor, but it should be validated before being used in security-sensitive operations.
Can I change $_SERVER values?
Yes. Since $_SERVER is an array, PHP code can modify its values during execution.
<?php
$_SERVER['APP_MODE'] = 'development';
echo $_SERVER['APP_MODE'];
However, changing values does not modify the actual server configuration. It only changes the array inside the current PHP execution.
Why is HTTP_REFERER sometimes empty?
The HTTP_REFERER value depends on the browser, privacy settings and referrer policies. It is optional and should never be required for critical application logic.
Conclusion
The PHP $_SERVER variable is a practical way to access request and server information. It helps with handling forms, detecting request methods, reading URLs, debugging environments and understanding incoming HTTP requests.
The important thing to remember is that not every value inside $_SERVER is trustworthy. Treat request headers and client-provided values as external input, validate them when needed and escape them before displaying them.
Used carefully, $_SERVER remains one of the simplest and most useful tools for understanding what is happening during a PHP request.
Magnificent website. A lot of helpful info.
And naturally, thank you for your effort!.
Welcome, Berita. Keep reading and sharing.
one of the best article I have ever found.. thank you for sharing your information..
Welcome Mohit
What is the length of the strings passed by these superglobal variables? I want to store the results in a table but need to have an idea of the maximum length returned for each so as to define the field value (varchar length).
There is no fixed maximum length for all `$_SERVER` values. Some values come from the server configuration, while others come from HTTP request headers sent by the client.
For storing common values in a database, these sizes are usually practical:
– `REMOTE_ADDR` (IP address): `VARCHAR(45)` is enough for IPv4 and IPv6.
– `REQUEST_METHOD`: `VARCHAR(10)` is more than enough (`GET`, `POST`, `PATCH`, `DELETE`, etc.).
– `SERVER_NAME` / `HTTP_HOST`: `VARCHAR(255)` is commonly used for host names.
– `REQUEST_URI`: use `VARCHAR(2048)` or `TEXT` if you need to support long URLs.
– `HTTP_USER_AGENT`: `VARCHAR(255)` is common, but user-agent strings can be much longer. Use `TEXT` if you need to store them completely.
– `HTTP_REFERER`: `VARCHAR(2048)` is a practical choice, or `TEXT` for full storage.
If you are storing request logs, I would generally use `TEXT` for fields like user agent, referrer and URI rather than trying to enforce a strict limit. For fixed-size values like IP addresses and request methods, a `VARCHAR` column with an appropriate length works well.
Also remember that `$_SERVER` values are not all trusted server data. Many values are supplied by the client, so validate them before storing or using them.