Question

urlencode vs rawurlencode in PHP: URL Encoding Explained

phpurlencodeurl-encoding

Question

When building a URL in PHP from a variable, both urlencode() and rawurlencode() can encode a string. What is the exact difference between these functions, and which one should be preferred in different parts of a URL?

Short Answer

You will learn why URL encoding is necessary, how PHP's urlencode() and rawurlencode() handle spaces and special characters differently, and how to choose the correct function for URL path segments and query-string values.

Concept

URLs have special characters with structural meanings. For example, / separates path segments, ? begins a query string, & separates query parameters, and # begins a fragment. If one of these characters appears inside user-provided data, it must be encoded so it is treated as data rather than URL structure.

PHP offers two closely related encoding functions:

  • urlencode() uses the application/x-www-form-urlencoded convention used by HTML forms and traditional query strings. A space becomes +.
  • rawurlencode() follows RFC 3986 percent encoding. A space becomes %20.
$text = 'red shoes & bags';

echo urlencode($text);    // red+shoes+%26+bags
echo rawurlencode($text); // red%20shoes%20%26%20bags

Both functions encode & as %26, preventing it from accidentally creating another query parameter. Their important visible difference is how they represent spaces.

A practical rule is:

  • Use rawurlencode() for an individual URL path segment.
  • Use http_build_query() for query strings. When choosing manually, use urlencode() for form-style query values or rawurlencode() for RFC 3986-style query values, depending on the convention your API requires.

Do not encode an entire URL at once. Encode only the data inserted into a specific URL component.

Mental Model

Think of a URL as a shipping label with separate fields:

  • The path is the street address.
  • The query string is a set of labelled notes.
  • Your variable is the text written inside one field.

If the text itself contains a separator such as /, &, or ?, it can be mistaken for part of the label's format. Encoding replaces those reserved characters with safe representations.

rawurlencode() uses %20 to write a space. urlencode() follows the older form convention of writing a space as +. Both protect the contents; the correct choice depends on which URL field and protocol convention you are working with.

Take Quiz

Syntax and Examples

Encode one value before inserting it into a URL.

$value = 'C++ & PHP';

$formStyle = urlencode($value);
$rfc3986Style = rawurlencode($value);

echo $formStyle;    // C%2B%2B+%26+PHP
echo $rfc3986Style; // C%2B%2B%20%26%20PHP

For a path segment, use rawurlencode():

$username = 'Ada Lovelace/Team A';
$url = 'https://example.com/users/' . rawurlencode($username);

echo $url;
// https://example.com/users/Ada%20Lovelace%2FTeam%20A

Encoding / as %2F is important here. Without encoding, it would create an unintended extra path segment.

For a query string, let http_build_query() build it instead of concatenating values manually:

$params = [
    'q' => 'C++ & PHP',
    'page' => 1,
];

$url = 'https://example.com/search?' . http_build_query($params);

echo $url;
// https://example.com/search?q=C%2B%2B+%26+PHP&page=1

To generate an RFC 3986 query string with %20 instead of +, pass PHP_QUERY_RFC3986:

$query = http_build_query($params, '', '&', PHP_QUERY_RFC3986);

echo $query;
// q=C%2B%2B%20%26%20PHP&page=1

Step by Step Execution

Consider this path-building example:

$category = 'science fiction/fantasy';
$url = 'https://example.com/books/' . rawurlencode($category);

echo $url;

Step by step:

  1. $category contains the text science fiction/fantasy.
  2. The space must not remain a literal space in a URL, so rawurlencode() changes it to %20.
  3. The slash is data in the category name, not a path separator, so it becomes %2F.
  4. rawurlencode($category) produces science%20fiction%2Ffantasy.
  5. PHP concatenates that encoded value after /books/.
  6. The final URL is:
https://example.com/books/science%20fiction%2Ffantasy

Now compare a query value:

$term = 'science fiction';
$url = 'https://example.com/search?q=' . urlencode($term);

echo $url;
// https://example.com/search?q=science+fiction

Here the space becomes +, which is the standard form-style query-string representation used by urlencode().

Real World Use Cases

  • Profile URLs: Encode a username before placing it in /users/{username}. Names may contain spaces, @, or /.
  • Search pages: Build URLs such as /search?q=wireless+headphones from a search input.
  • API requests: Encode query parameters such as filters, redirect destinations, and pagination tokens.
  • File download links: Encode a file name when it is used as one path segment, especially when it contains spaces or #.
  • OAuth redirect parameters: A callback URL placed inside another URL's query parameter must be encoded as the parameter value.
  • Server-side integrations: Generate safe links for emails, reports, and redirects from database values.
Take Quiz

Real Codebase Usage

In production PHP applications, developers usually avoid manually joining many query parameters. http_build_query() handles separators and encoding consistently.

$filters = [
    'status' => 'in progress',
    'owner' => 'sam@example.com',
];

$redirectUrl = '/tasks?' . http_build_query($filters, '', '&', PHP_QUERY_RFC3986);

For routes, encode each dynamic segment individually:

function userProfileUrl(string $username): string
{
    return '/users/' . rawurlencode($username);
}

This is safer than encoding the entire route because the route's real slashes must remain slashes.

A common validation pattern is to reject invalid application data first, then encode it for URL transport:

function productUrl(string $slug): string
{
    if ($slug === '') {
        throw new InvalidArgumentException('Product slug is required.');
    }

    return '/products/' . rawurlencode($slug);
}

Encoding is not validation and is not HTML escaping. If the URL will later be printed in HTML, use htmlspecialchars() at the HTML output boundary as well.

Common Mistakes

Encoding the whole URL

Broken example:

$url = 'https://example.com/search?q=red shoes';
echo rawurlencode($url);

This encodes :, /, ?, and =, destroying the URL structure.

https%3A%2F%2Fexample.com%2Fsearch%3Fq%3Dred%20shoes

Instead, keep structural characters and encode only the value:

$url = 'https://example.com/search?q=' . rawurlencode('red shoes');

Forgetting to encode query values

Broken example:

$term = 'books & music';
$url = '/search?q=' . $term;

The & can be interpreted as a new query parameter. Use http_build_query() or encode the value.

$url = '/search?' . http_build_query(['q' => $term]);

Using urlencode() for a path segment

$name = 'Team Alpha';
echo '/groups/' . urlencode($name);
// /groups/Team+Alpha

+ is associated with form-style query strings, not general path encoding. Prefer:

echo '/groups/' . rawurlencode($name);
// /groups/Team%20Alpha

Double encoding

$value = rawurlencode('hello world'); // hello%20world
echo rawurlencode($value);            // hello%2520world

The % is encoded as %25. Keep raw values in variables where possible and encode exactly once when constructing the URL.

Confusing URL encoding with HTML escaping

rawurlencode() makes data safe for a URL component. It does not make a URL safe to insert into HTML. When outputting a URL in an HTML attribute, escape it for HTML too:

$url = '/search?q=' . rawurlencode($term);
echo '<a href="' . htmlspecialchars($url, ENT_QUOTES, 'UTF-8') . '">Search</a>';

Comparisons

SituationRecommended approachWhy
One path segment, such as /users/{name}rawurlencode($name)Uses RFC 3986 percent encoding; spaces become %20.
Several query parametershttp_build_query($params)Builds key=value&key=value safely.
Query string requiring RFC 3986 spaceshttp_build_query($params, '', '&', PHP_QUERY_RFC3986)Produces %20 instead of +.
Form-style query value encoded manuallyurlencode($value)Uses application/x-www-form-urlencoded; spaces become +.
Complete URLDo not encode it as one stringEncode each inserted component separately.
FunctionSpace outputTypical use
urlencode()+Form-style query-string values
rawurlencode()%20URL path segments and RFC 3986 components
http_build_query()+ by defaultConstructing a complete query string
http_build_query(..., PHP_QUERY_RFC3986)%20RFC 3986 query strings
Take Quiz

Cheat Sheet

// Form-style encoding: spaces become +
urlencode('a b');       // a+b

// RFC 3986 encoding: spaces become %20
rawurlencode('a b');    // a%20b

// Dynamic path segment
$url = '/posts/' . rawurlencode($slug);

// Query string, default form-style encoding
$url = '/search?' . http_build_query(['q' => $term]);

// Query string, RFC 3986 encoding
$url = '/search?' . http_build_query(
    ['q' => $term],
    '',
    '&',
    PHP_QUERY_RFC3986
);
  • Encode data, not an entire URL.
  • Encode every dynamic path segment separately.
  • Use rawurlencode() for path segments.
  • Prefer http_build_query() over manually assembling query strings.
  • + represents a space in form-style query parsing; %20 is the standard percent-encoded space.
  • Avoid encoding a value twice.
  • URL encoding is different from HTML escaping.

FAQ

What is the main difference between urlencode() and rawurlencode() in PHP?

The key difference is spaces: urlencode() converts spaces to +, while rawurlencode() converts them to %20. They also follow different encoding conventions: form encoding and RFC 3986 encoding respectively.

Which function should I use for a URL path in PHP?

Use rawurlencode() for each dynamic path segment. It safely encodes spaces as %20 and prevents data such as / from changing the route structure.

Should I use urlencode() or rawurlencode() for query parameters?

Prefer http_build_query() for complete query strings. Its default output is form-style encoding; use PHP_QUERY_RFC3986 when an API requires RFC 3986 encoding.

Is %20 better than + in URLs?

Neither is universally better. %20 is the RFC 3986 percent-encoded form and is appropriate for path segments. + is conventional in application/x-www-form-urlencoded query strings.

Can I use rawurlencode() on a complete URL?

No. It will encode structural characters such as :, /, ?, and =, so the result is no longer a usable URL. Encode only variable components.

Does urlencode() protect against XSS?

No. URL encoding protects URL structure. Use htmlspecialchars() when inserting a URL into HTML, and use parameterized queries for database values.

Why does % become %25 after encoding?

% is itself a reserved character in percent encoding. If you encode an already encoded value, %20 becomes %2520; this is double encoding.

Take Quiz

Mini Project

Description

Build a small PHP URL generator for a product page. The product category is placed in the path, while search and sorting options are placed in the query string. This demonstrates encoding each URL component correctly rather than encoding the complete URL.

Goal

Generate a valid product URL even when category names and search terms contain spaces, slashes, ampersands, or plus signs.

Requirements

Create a category path segment from a variable containing special characters. Build query parameters for a search term, sort order, and page number. Use RFC 3986 encoding for the generated query string. Do not encode the base URL or its structural slashes. Print the final URL.

Take Quiz

Keep learning

Related questions

View more