rawurldecode
Decodes percent-encoded sequences in a string, leaving plus signs untouched.
rawurldecode(string $string): string- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$string | string | The 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
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.
<?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.
<?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.
<?php
foreach (['100%', '%zz', '%4', 'a%25b', '%2Fetc%2Fpasswd'] as $in) {
printf("%-16s -> %s\n", $in, rawurldecode($in));
}
Discussion