rawurldecode

Decodes percent-encoded sequences in a string, leaving plus signs untouched.

Signature
rawurldecode(string $string): string
  • Added in PHP 4.0

Parameters

ParameterTypeDescription
$stringstringThe URL-encoded string to be decoded.

Return value

stringThe decoded string, with every %XX sequence replaced by the corresponding byte.

Errors

Does not throw. Malformed escapes such as a trailing % are left as literal text.

rawurldecode() reverses rawurlencode(): every %XX sequence becomes the byte it names, and everything else is passed through unchanged. Critically, a + stays a +, which is what makes it the correct decoder for path segments, where a plus is a literal plus character.

Match the decoder to the encoder

If the data came from an HTML form or a query string, spaces were probably encoded as +, and only urldecode() will restore them. If the data came from a path, a header, or any RFC 3986 producer, use rawurldecode(). Choosing the wrong one either loses spaces or corrupts real plus signs — the sort of bug that only appears when someone types a + in an email address.

Do not double-decode

$_GET, $_POST and $_REQUEST are already decoded by PHP. Decoding them again turns a legitimate %2F that the user typed into a real slash, which is a classic path-traversal opening. The same applies to values from parse_str(). Only decode what you know is still encoded, such as the components returned by parse_url().

Invalid sequences are not errors: '100%' comes back unchanged.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Turn a percent-encoded path segment from parse_url back into a readable filename
  • Decode a value read out of a raw HTTP header
  • Restore the original text of a slug that was encoded for a permalink
  • Read a value from a raw request URI before any framework routing decoded it

Frequently asked questions

What is the difference between rawurldecode and urldecode?

urldecode also converts + into a space; rawurldecode leaves + as a literal plus sign. Use rawurldecode for path segments and headers, urldecode for query strings and form data.

Should I call rawurldecode on $_GET values?

No. PHP already decodes $_GET, $_POST and $_REQUEST, and decoding again can turn a user-supplied %2F into a real slash and open a path-traversal hole.

What happens if the string contains an invalid escape like %zz?

It is left unchanged. rawurldecode never fails or returns false, so you cannot use it to validate encoding.

More examples

Why plus signs matter for emails

rawurlencode turns the literal + into %2B, so both decoders restore it correctly. The danger is the reverse pairing: if urlencode had produced the string, its + characters would represent spaces and rawurldecode would leave them as plus signs.

Example · php
<?php
$email = '[email protected]';
$encoded = rawurlencode($email);

echo $encoded, "\n";
var_dump(rawurldecode($encoded) === $email);

// Decoding the same value with urldecode is still safe here,
// because rawurlencode escaped the real plus as %2B.
var_dump(urldecode($encoded) === $email);

Decoding parse_url output

parse_url deliberately leaves the path encoded. rawurldecode restores it to "/files/Q1 report+draft.pdf", keeping the plus as a literal character, and basename then gives the real filename ready to display or match on disk.

Example · php
<?php
$url = 'https://example.com/files/Q1%20report%2Bdraft.pdf';
$path = parse_url($url, PHP_URL_PATH);

echo $path, "\n";
echo rawurldecode($path), "\n";
echo basename(rawurldecode($path)), "\n";

Malformed escapes are passed through

Incomplete or non-hex escapes like %zz and %4 are left exactly as written rather than raising an error, so decoding never fails loudly. Note the last line: %2F decodes to a real slash, which is why decoding user input a second time is dangerous.

Example · php
<?php
foreach (['100%', '%zz', '%4', 'a%25b', '%2Fetc%2Fpasswd'] as $in) {
    printf("%-16s -> %s\n", $in, rawurldecode($in));
}

Discussion

  • Be the first to comment on this lesson.