Menu
Try in Playground

JavaScript URLs and Query Strings: URL and URLSearchParams

How to parse, build, and modify URLs in JavaScript with the URL and URLSearchParams APIs — without regex and without edge-case bugs.

Stop Parsing URLs With String Tricks

Before the URL API existed, people sliced URLs with split('?'), regexes, and hope. It mostly worked until a value contained an &, a =, a space, or a non-ASCII character — and then it didn't. The browser and Node both ship a proper parser. Use it.

index.js
Output
Click Run to see the output here.

One call, every part of the URL already split apart and decoded correctly. The constructor throws a TypeError on invalid input, which is usually what you want — a garbage URL should fail loudly rather than silently produce garbage downstream.

Reading Query Parameters

Every URL has a .searchParams property — a URLSearchParams object that knows how to read and write the query string:

index.js
Output
Click Run to see the output here.

A few things worth noticing:

  • Values come back already decoded. ?name=Ada%20Lovelace gives you "Ada Lovelace".
  • Everything is a string. "2" is not 2. Convert with Number() if you need a number.
  • Repeated keys are legal. get returns the first match; getAll returns every match.
  • Missing keys return null, not undefined — so ?? "default" works well with them.

Building a Query String

You can build a query string from scratch with URLSearchParams — no manual escaping, no joining with &:

index.js
Output
Click Run to see the output here.

Or construct it from an object — any iterable of [key, value] pairs works, and a plain object does too:

index.js
Output
Click Run to see the output here.

set vs append: set replaces any existing value for that key. append adds another one. Use append when a key can legitimately repeat (tags, filters); use set for single-valued parameters.

Modifying a URL

Because URL is a live object, changing searchParams updates .search and .href automatically:

index.js
Output
Click Run to see the output here.

This is the idiomatic way to append a query parameter to an existing URL. No "does the URL already have a ?" check, no worrying about whether to prepend & or ?.

You can change other parts of the URL the same way:

index.js
Output
Click Run to see the output here.

Iterating Over Parameters

URLSearchParams is iterable. for...of gives you [key, value] pairs, and there are the usual keys(), values(), and entries() helpers:

index.js
Output
Click Run to see the output here.

Note that repeated keys show up multiple times — you'll see tag = web and then tag = beginner as separate entries. That's faithful to the actual query string.

If you want a plain object for a quick debug print, Object.fromEntries works — but it collapses repeats, keeping only the last value:

index.js
Output
Click Run to see the output here.

Fine for debugging. Wrong if any key can repeat.

Relative URLs Need a Base

new URL("/search?q=js") on its own throws — a relative path isn't a valid URL by itself. Pass a base as the second argument:

index.js
Output
Click Run to see the output here.

The resolution rules are the same ones browsers use for <a href>: a leading / is absolute from the host, no slash is relative to the current path, .. walks up. Very handy when you're assembling API URLs from a configured base.

In the browser, window.location.href is a ready-made base for parsing the current page's URL:

const u = new URL(window.location.href);
const page = u.searchParams.get("page") ?? "1";

Handling Invalid URLs

The URL constructor throws on malformed input. That's useful — but it means you need try/catch when parsing anything the user typed or an external system sent:

index.js
Output
Click Run to see the output here.

Modern environments also expose URL.canParse(input) — a boolean check that avoids the try/catch dance when you just want to validate:

index.js
Output
Click Run to see the output here.

A Small Working Example

Putting it together — read the current filters from a URL, tweak them, and produce a new URL to navigate to:

index.js
Output
Click Run to see the output here.

Passing null deletes the parameter. Any other value sets or overwrites it. That's a pattern you'll end up writing in one form or another any time you build filter UIs, pagination, or deep links.

What to Take Away

  • new URL(string) parses a URL into labelled parts. It throws on garbage.
  • url.searchParams is a URLSearchParams — use get, getAll, set, append, delete, has.
  • Encoding happens for you. Don't reach for encodeURIComponent unless you're building strings by hand.
  • Pass a base URL as the second argument to resolve relative paths.
  • URL.canParse (or try/catch) is your validation tool for untrusted input.

Every time you're tempted to split a URL with .split('?') or pick a query parameter out with a regex, reach for these APIs instead. They're shorter, correct, and already in the runtime.

Frequently Asked Questions

How do I parse a URL in JavaScript?

Pass the string to the URL constructor: const u = new URL('https://example.com/path?x=1'). The resulting object exposes protocol, host, pathname, search, hash, and a searchParams helper. It throws on invalid URLs, so wrap it in try/catch when parsing untrusted input.

How do I get a query string parameter in JavaScript?

Use url.searchParams.get('name'). It returns the decoded value or null if the parameter isn't present. For parameters that can repeat (?tag=a&tag=b), use searchParams.getAll('tag') to get all values as an array.

What's the difference between URL and URLSearchParams?

URL parses and represents a whole URL — protocol, host, path, query, hash. URLSearchParams is just the query-string part, and you can use it standalone to build or parse a=1&b=2 strings. Every URL instance has a .searchParams property that's a URLSearchParams tied to that URL.

Do I need to encode query parameters manually?

No. URLSearchParams encodes keys and values automatically when you call set, append, or read back the string. That handles spaces, &, =, and Unicode correctly. Only reach for encodeURIComponent when you're building a string by hand, which you usually shouldn't.

Learn to code with Coddy

GET STARTED