How Query Strings Work in URLs

Most URLs you interact with daily contain query strings. Understanding exactly how they're structured — and what can go wrong when they're assembled carelessly — is essential for anyone working with web APIs, tracking links, or redirect flows.

Query string anatomy

A query string begins with ? after the path and contains key-value pairs separated by &:

https://example.com/search?q=json+formatter&page=2&sort=relevance
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                        query string

The fragment (hash) comes after the query string: ?q=test#results. The fragment is never sent to the server — browsers use it for in-page navigation only.

Encoding and special characters

Query strings can safely contain ASCII letters, digits, and -_.. Everything else requires percent-encoding. A space becomes %20 (or + in query strings specifically). An & inside a value becomes %26. An = inside a value becomes %3D.

Forgetting this is a frequent source of broken tracking links:

# Broken — the & inside utm_campaign splits into a new parameter
?utm_campaign=summer&sale&utm_source=email
# Parser sees: utm_campaign=summer, sale=(empty), utm_source=email

# Correct — the & is encoded
?utm_campaign=summer%26sale&utm_source=email
# Parser sees: utm_campaign=summer&sale, utm_source=email

Repeated keys

The same key can appear multiple times: ?color=red&color=blue. Whether this creates an array or uses the last value depends on the server framework. PHP expects color[] for arrays. Express.js and many others return arrays for repeated keys. If you're sending multi-value parameters, check the API documentation for the expected format.

URL structure summary

https://api.example.com:443/v2/users?page=1&limit=20#top
└─┬─┘   └──────┬──────┘└─┬┘└────┬───┘└────────┬─────┘└──┬─┘
scheme        host      port   path         query      fragment
Building URLs safely: always use a URL builder or encoding library rather than string concatenation. Most languages have built-in URL building functions that handle encoding automatically. urllib.parse.urlencode() in Python, new URLSearchParams() in JavaScript, URI.escape() in Ruby. Hand-concatenation is reliable only for the simplest cases.