Skip to content
Carl Victor Fontanos
Carl Victor Fontanos

Carl Victor Fontanos

Software Engineer

I build web applications and share what I learn along the way.

© 2026

Stop Parsing Query Strings by Hand

C
Carlo Fontanos
· 2 min read

Every legacy codebase I open contains a hand-written query string parser, and every single one has at least one bug: it decodes twice, or chokes on = inside a value, or turns ?flag into undefined weirdness. The browser has shipped a correct parser for years.

Reading

const params = new URLSearchParams(location.search);

params.get('page');        // "2" (or null if absent)
params.has('debug');       // true even for a bare ?debug
params.getAll('tag');      // ["css", "php"] for ?tag=css&tag=php

getAll() is the sleeper feature: repeated keys are the standard way to send arrays, and naive parsers always clobber all but the last value.

Building - encoding handled for you

const params = new URLSearchParams({
    q: 'café & bar',
    sort: 'newest',
});
fetch('/search?' + params);   // q=caf%C3%A9+%26+bar&sort=newest

No encodeURIComponent calls, no forgotten ampersands. It also serializes directly as a fetch body for form-encoded POSTs: fetch(url, { method: 'POST', body: params }) sets the right Content-Type automatically.

Editing a URL without string surgery

The URL object exposes searchParams as a live, mutable view:

const url = new URL(location.href);
url.searchParams.set('page', 3);       // replaces existing value
url.searchParams.delete('error');
history.replaceState(null, '', url);   // update address bar, no reload

That three-line pattern (mutate params, replaceState) is the backbone of every filterable listing page I build - the URL stays shareable and the back button keeps working.

Edge cases it gets right

  • + is decoded as a space (matching form encoding), which regex-based parsers almost always miss.
  • Keys are case-sensitive, values are always strings - params.get('page') === "2", so remember to Number() it.
  • It's iterable: for (const [key, value] of params) and Object.fromEntries(params) both work (the latter loses duplicate keys, so only use it when keys are unique).

Works everywhere, including Node. The same instinct applies server-side: PHP people, stop hand-assembling JSON too. The platform already solved these problems - our job is to remember that.

C
Written by Carlo Fontanos

Full-stack web developer sharing practical tutorials and building tools that ship.

Got something on your mind?

My inbox is open - no forms disappearing into the void here.

  • Just say hello Found a tutorial useful? Spotted a mistake? Tell me.
  • Hire me for a project Have something custom in mind? Let's talk scope and timelines.
  • Product support Bought something here? I'll help you get it running.

I usually reply within 1-2 business days.

Message sent!

Your details are only used to reply to you.

Keep reading