Skip to content
T
Tools.Town
Free Online Tools for Everyone
Developer Tools

URL Query Strings Explained: Encoding, Building & Parsing

A practical guide to URL query strings — what they are, how percent-encoding works, the difference between RFC-3986 and form encoding, and how to build or parse them correctly.

25 June 2026 4 min read By Tools.Town Team Fact Checked

Key Takeaways

  • A space is not allowed literally in a URL, so it gets percent-encoded as %20 (the hexadecimal code point for a space)
  • The query string starts at ? and ends before # (if any) — it is sent to the server
  • Yes — it is valid per the URL spec

What is a query string?

Every URL you type or click can have four main parts: the scheme (https://), the host (example.com), the path (/search), and the query string — the ?key=value&key2=value2 part that appears after the path. The query string is how web pages and APIs receive parameters: the search term you type, the page number you want, the sort order you select, and the tracking codes a marketing team added all live there.

You can build and decode query strings instantly with the Query String Builder. This guide explains the rules that make them work.

Why does encoding matter?

A query string is a flat sequence of characters inside a URL. Problem: URLs have a very small set of characters that are safe to use literally — the unreserved set A–Z a–z 0–9 - _ . ~. Everything else — spaces, ampersands, equals signs, Unicode characters, emoji — must be encoded before it goes into a URL, or it will be misinterpreted.

Consider this URL:

https://example.com/search?q=hello world&tag=C# programming

The space in hello world makes the URL ambiguous; many parsers will treat it as the end of the URL. The # in C# will be interpreted as a fragment delimiter. The correct encoded version is:

https://example.com/search?q=hello%20world&tag=C%23%20programming

Now the URL is unambiguous, regardless of which character set or parser reads it.

How percent-encoding works

Percent-encoding (also called URL encoding) replaces each unsafe character with % followed by its two-digit uppercase hexadecimal code point in UTF-8. The process is:

  1. Take the character (e.g. a space).
  2. Find its UTF-8 byte value (space = 0x20).
  3. Write %20.

For multi-byte Unicode characters the same rule applies to each byte. The letter é is encoded as two UTF-8 bytes: 0xC3 and 0xA9, so it becomes %C3%A9.

The only characters that are never encoded are the unreserved characters: uppercase and lowercase ASCII letters, digits, and the four symbols -, _, ., ~. Everything else should be encoded to be safe.

RFC-3986 vs form encoding — what’s the difference?

There are two common encoding styles, and they differ only in how they treat spaces:

RFC-3986 (the URI standard) encodes a space as %20. This is correct for query strings in URLs you craft manually, in API requests, and in any modern HTTP client. It is what the Query String Builder uses by default.

application/x-www-form-urlencoded (HTML form encoding) encodes a space as +. This is the encoding browsers use when submitting an HTML form with method="GET". Many servers accept + as a space in query strings because of the dominance of form submissions. However, a literal + in your original data must itself be encoded as %2B to distinguish it from a space, which adds complexity.

For new code, prefer RFC-3986 (%20 spaces). Use form encoding only when interoperating with systems that explicitly expect it.

Anatomy of a query string

?page=2&q=hello+world&sort=asc&filter%5Bcolor%5D=red
 │      │             │         │
 │      │             │         └─ filter[color] (brackets encoded as %5B%5D)
 │      │             └─────────── sort=asc
 │      └───────────────────────── q=hello world (+ encoded space)
 └──────────────────────────────── ? delimiter starts the query

Each key=value pair is separated by &. The ? separates the path from the query. There is no trailing delimiter required.

Common encoding pitfalls

Encoding the whole URL instead of just the value. A common mistake is to run the entire URL through an encoder, which encodes the ?, &, and = delimiters. These must stay literal; only the individual key and value strings should be encoded.

Double-encoding. If your HTTP library already encodes values, calling your own encoding on top produces %2520 (the % in %20 encoded again as %25). The result decodes to %20 instead of a space. Use the parser mode of the Query String Builder to check for double-encoding — you will see %25 in the raw column.

Forgetting non-ASCII characters. API consumers sometimes test with ASCII-only data and only discover the issue with a Japanese product name or an accented surname. Always test with Unicode values before shipping.

Using the wrong separator. While & is by far the most common separator, some older systems use ; (permitted by older HTML specs) or ,. Modern code should always use &.

Parsing a query string

Parsing is the reverse operation: take the raw key=value&key2=value2 string and decode it into structured data. The steps are:

  1. Strip the leading ? if present.
  2. Strip any fragment (#...) if present.
  3. Split on & to get individual segments.
  4. For each segment, split on the first = to separate key from value.
  5. Decode each key and value using decodeURIComponent (replacing + with space first if you expect form-encoded input).

The Query String Builder’s Parse mode does all of this and shows you both the raw encoded value and the decoded result, which makes it easy to spot encoding issues in URLs you paste from browser DevTools or server logs.

Duplicate keys and arrays

The URL specification does not define what happens when the same key appears more than once — ?id=1&id=2&id=3 is syntactically valid. What happens on the server side depends entirely on the framework:

  • PHP ($_GET['id']) gives you the last value: 3.
  • Node.js querystring gives you an array: ['1','2','3'].
  • Python urllib.parse.parse_qs gives you a list: ['1','2','3'].
  • Bracket notation (?id[]=1&id[]=2) is another convention used by PHP and some JavaScript frameworks to signal array intent.

The tool warns you when it detects duplicates so you can decide whether the repetition is intentional or a bug.

Building query strings in code

Most languages have a built-in or standard library function. Avoid string concatenation — it is easy to forget to encode a value:

JavaScript (browser/Node.js):

const params = new URLSearchParams({ q: 'hello world', page: '2' });
console.log(params.toString()); // q=hello+world&page=2

Note: URLSearchParams uses form encoding (+ for spaces). For RFC-3986 use encodeURIComponent manually.

Python:

from urllib.parse import urlencode
urlencode({'q': 'hello world', 'page': 2})  # q=hello+world&page=2

Go:

params := url.Values{"q": {"hello world"}, "page": {"2"}}
params.Encode()  // q=hello+world&page=2

The Query String Builder is the fastest way to verify the output of any of these — paste the URL into Parse mode and check every value decoded correctly.

Security note: never trust query string values

Query strings are user-controlled. Any value in a query string could be crafted maliciously. Always validate and sanitise query string inputs on the server — they should never be inserted into SQL queries without parameterisation, rendered directly into HTML without escaping (XSS), or used to construct file paths without strict validation. The same escaping mindset applies when you render those values back into a page; our HTML entity encoder guide covers how to neutralise characters like <, >, and & so user input can’t break out of its context.

Summary

A query string is the ?key=value section of a URL that passes parameters to a page or API. Characters outside the safe ASCII set must be percent-encoded — spaces become %20 (RFC-3986) or + (form encoding). The Query String Builder handles encoding automatically in Build mode and decodes any URL in Parse mode, so you can verify your parameters are being transmitted exactly as intended.

Advertisement

Try Query String Builder — Free

Apply what you just learned with our free tool. No sign-up required.

Try Query String Builder

Frequently Asked Questions

Why does my URL have %20 in it?
A space is not allowed literally in a URL, so it gets percent-encoded as %20 (the hexadecimal code point for a space). Some HTML forms encode spaces as + instead — both are valid, but they belong in different contexts.
What is the difference between a query string and a URL fragment?
The query string starts at ? and ends before # (if any) — it is sent to the server. The fragment starts at # and never leaves the browser — it is used for in-page navigation or client-side routing.
Can a query string have duplicate keys?
Yes — it is valid per the URL spec. Many server frameworks parse duplicate keys into an array. Others take only the first value or only the last. Check your framework's behaviour and use the Query String Builder's duplicate-key warning to stay aware.

Was this guide helpful?

Your feedback helps us improve our content.

Get the best Developer Tools tips & guides in your inbox

Join 25,000+ users who get our weekly developer tools insights.