Signature
parse_str(string $string, array &$result): voidPurpose
parse_str() reads a string that is formatted like the query part of a URL, such as page=2&sort=name, and fills an array with the pairs it finds. It is useful when a query string reaches your code as plain text, for example from a stored link, a log line or a test fixture, rather than through $_GET.
Signature
Parameters and defaults
$stringis the text to parse. Give it only the query portion, without the leading?. If you have a whole URL, extract the query first, for example withparse_url().$resultis passed by reference. PHP assigns a new array to it that holds the extracted keys and values. It has no default, and it has been mandatory since PHP 8.0.0. Older code that omitted it created variables in the current scope. That style was deprecated in PHP 7.2 and no longer works, so always pass a result variable.
Return value and failure behavior
The function returns void, so the result lives only in the variable you passed. Writing $data = parse_str($q, $data); is a mistake because the assigned value would be null. Malformed input does not throw an exception. PHP extracts what it can. The function is also affected by the max_input_vars directive, whose default is 1000. If a string holds more variables than the limit allows, PHP emits an E_WARNING and leaves out the extra ones.
Every value is already URL-decoded using the same rules as urldecode(). This means + becomes a space and %C3%A3 becomes the matching UTF-8 character.
Example 1: basic pairs and list syntax
A key that ends in [] collects its values into a list, in the order they appear.
parse_str("first=value&arr[]=foo+bar&arr[]=baz", $output);
echo json_encode($output, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;{"first":"value","arr":["foo bar","baz"]}
Notice that foo+bar arrives as foo bar.
Example 2: name mangling and percent decoding
Spaces and dots in parameter names are converted to underscores. This follows the rules for PHP variable names, and it applies even when you use the recommended $result argument. Values are decoded, so non-ASCII text encoded as UTF-8 percent sequences comes back readable.
parse_str("My Value=Something&user.name=Ana&city=S%C3%A3o+Paulo", $output);
echo json_encode($output, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;{"My_Value":"Something","user_name":"Ana","city":"São Paulo"}
If you expected a key named user.name, look for user_name instead.
Example 3: nested keys, duplicates and empty values
Bracket syntax with a name inside builds an associative sub-array. When the same plain key appears twice, the later value replaces the earlier one. A name with no equals sign, or with nothing after it, produces an empty string.
parse_str("a[b]=1&a[c]=2&x=1&x=2&flag&empty=", $output);
echo json_encode($output, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;{"a":{"b":"1","c":"2"},"x":"2","flag":"","empty":""}
All the scalar values are strings, including the digits, because a query string carries no type information.
Edge cases
- Everything is a string. Convert with
(int),filter_var()or similar if you need numbers or booleans. - Repeated keys without brackets overwrite. Use
name[]=if you want to keep every value. - Bracket keys are interpreted. Input controlled by a user can create nested arrays, so validate the shape of the result before you rely on it.
- Too many variables. Anything beyond
max_input_varsis dropped with a warning. - Only the query is parsed. A leading
?or a full URL becomes part of the first key. Strip or extract the query first.
Common mistakes
- Calling the function with a single argument. This is an error in PHP 8, because
$resultis required. - Using the return value. It is always
null. - Searching the result for keys with dots or spaces. They have been changed to underscores.
- Decoding the values a second time with
urldecode(). This can corrupt data that legitimately contains a percent sign or a plus sign after the first decoding. - Trusting types and structure. A parameter you expect to be text may arrive as an array if the client sends
name[]=x.
Related functions
http_build_query()does the reverse and creates a query string from an array.parse_url()splits a URL into scheme, host, path, query and fragment.urldecode()decodes a single encoded string.pathinfo()describes file path parts, which is useful alongside URL handling.
Recap
parse_str() converts a query string into an array stored in the variable you pass by reference. It decodes values, mangles spaces and dots in names into underscores, builds nested arrays from bracket syntax, lets later duplicates win, and returns nothing. Always pass the result argument and validate what comes back.
Tested examples
parse_str("first=value&arr[]=foo+bar&arr[]=baz", $output);
echo json_encode($output, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;{"first":"value","arr":["foo bar","baz"]}
parse_str("My Value=Something&user.name=Ana&city=S%C3%A3o+Paulo", $output);
echo json_encode($output, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;{"My_Value":"Something","user_name":"Ana","city":"São Paulo"}
parse_str("a[b]=1&a[c]=2&x=1&x=2&flag&empty=", $output);
echo json_encode($output, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;{"a":{"b":"1","c":"2"},"x":"2","flag":"","empty":""}