URL Query String Guide — Parsing, Building, and Best Practices
URL query strings pass data in URLs after the ? character. Learn how to parse and build query strings in JavaScript, Python, and Go, handle arrays and nested objects, and...
Use the tool
URL Encoder / Decoder
Percent-encode and decode URLs per RFC 3986.
Query strings are the key=value pairs after the ? in a URL. They’re used for search queries, filters, pagination, and passing data between pages without form submission.
Use the URL Encoder to encode query string values safely.
Query string anatomy
https://example.com/search?q=hello+world&page=2&sort=date&tag=js&tag=css
│ │ └─value──┘ └──┘ └─────┘ └─────────────────┘
│ │ │ │ repeated keys (arrays)
│ key=value page sort
└── base URL └── ? starts query string
& separates pairs
Parse query strings in JavaScript
// Using URLSearchParams (recommended):
const qs = '?q=hello+world&page=2&tag=js&tag=css';
const params = new URLSearchParams(qs);
params.get('q') // 'hello world' (decodes + and %xx)
params.get('page') // '2' (always string)
params.get('tag') // 'js' (only first value!)
params.getAll('tag') // ['js', 'css'] (all values for key)
params.has('sort') // false
// Iterate:
for (const [key, value] of params) {
console.log(key, value);
}
// From current page URL:
const url = new URL(window.location.href);
const query = url.searchParams.get('q');
// From fetch response:
const apiUrl = new URL('https://api.example.com/search');
apiUrl.searchParams.set('q', 'hello & world');
apiUrl.searchParams.set('page', '1');
fetch(apiUrl.toString());
// Fetches: https://api.example.com/search?q=hello+%26+world&page=1
Build query strings in JavaScript
// Build from object:
function buildQueryString(params) {
const qs = new URLSearchParams();
for (const [key, value] of Object.entries(params)) {
if (Array.isArray(value)) {
value.forEach(v => qs.append(key, v));
} else if (value !== undefined && value !== null) {
qs.set(key, value);
}
}
return qs.toString();
}
buildQueryString({ q: 'hello world', page: 1, tags: ['js', 'css'] })
// 'q=hello+world&page=1&tags=js&tags=css'
// Append to existing URL:
function addParams(url, params) {
const u = new URL(url);
Object.entries(params).forEach(([k, v]) => {
if (Array.isArray(v)) v.forEach(item => u.searchParams.append(k, item));
else u.searchParams.set(k, v);
});
return u.toString();
}
Parse query strings in Python
from urllib.parse import parse_qs, parse_qsl, urlencode
# parse_qs — returns dict of lists:
qs = 'q=hello+world&page=2&tag=js&tag=css'
params = parse_qs(qs)
# {'q': ['hello world'], 'page': ['2'], 'tag': ['js', 'css']}
params['q'][0] # 'hello world'
params['tag'] # ['js', 'css']
# parse_qsl — returns ordered list of tuples:
pairs = parse_qsl(qs)
# [('q', 'hello world'), ('page', '2'), ('tag', 'js'), ('tag', 'css')]
# Build query string:
from urllib.parse import urlencode
params = {'q': 'hello & world', 'page': 1, 'sort': 'date'}
urlencode(params)
# 'q=hello+%26+world&page=1&sort=date'
# With lists:
params = {'tag': ['js', 'css', 'html']}
urlencode(params, doseq=True)
# 'tag=js&tag=css&tag=html'
Array conventions in query strings
There’s no standard for arrays — different APIs use different conventions:
// Repeated key (most common):
?tag=js&tag=css&tag=html
// Brackets (PHP/Ruby style):
?tag[]=js&tag[]=css&tag[]=html
// Indexed brackets:
?tag[0]=js&tag[1]=css&tag[2]=html
// Comma-separated (some REST APIs):
?tag=js,css,html
// URLSearchParams uses repeated key:
params.append('tag', 'js');
params.append('tag', 'css');
// → 'tag=js&tag=css'
// qs library (npm) supports multiple styles:
import qs from 'qs';
qs.stringify({ tag: ['js', 'css'] }) // 'tag%5B0%5D=js&tag%5B1%5D=css'
qs.stringify({ tag: ['js', 'css'] }, { arrayFormat: 'repeat' }) // 'tag=js&tag=css'
qs.stringify({ tag: ['js', 'css'] }, { arrayFormat: 'comma' }) // 'tag=js%2Ccss'
REST API query parameter conventions
GET /articles?page=2&per_page=20&sort=created_at&order=desc
GET /users?search=alice&role=admin&active=true
GET /products?min_price=10&max_price=100&category=electronics
GET /events?after=2026-01-01&before=2026-12-31
GET /items?fields=id,name,price (sparse fieldsets)
GET /items?include=author,tags (sideloaded relations)
Related tools
- URL Encoder — encode query string values
- URL Encoding in JavaScript — encodeURIComponent guide
- URL Encoding in Python — urllib.parse guide
Related posts
- URL Encoding: The 7 Bugs That Break Your API — Every API has at least one URL-encoding bug. Here are the seven I see most — wha…
- Percent Encoding and RFC 3986 Explained — Why is `+` sometimes a space and sometimes a literal plus? Why does `%2520` show…
- Double URL Encoding — What It Is, Why It Happens, and How to Prevent It — Double URL encoding happens when an already-encoded URL is encoded again, turnin…
- URL Encoding in Python — urllib.parse, requests, and FastAPI — Python's urllib.parse module provides quote, quote_plus, and urlencode for URL e…
- URL Encoding in JavaScript — encodeURIComponent vs encodeURI — JavaScript has two URL encoding functions: encodeURI for full URLs and encodeURI…
Related tool
URL Encoder / Decoder
Percent-encode and decode URLs per RFC 3986.
Written by Mian Ali Khalid. Part of the Dev Productivity pillar.