URL boundaries
URL encoding: encode data, not the whole address
A URL has structure: scheme, host, path, query, and fragment have different escaping rules. Encoding the full string usually destroys that structure.
Content updated: · Maintainer and corrections
Trace a query value through the URL API
Suppose the search text is tea & cake + milk. Set it as a value with url.searchParams.set("q", "tea & cake + milk"). Serialization produces q=tea+%26+cake+%2B+milk. Reading searchParams.get("q") returns the original text: the encoded ampersand stays inside the value, while a literal plus becomes %2B.
Paste the complete result into URL Inspector and compare its query with the original input. URLSearchParams uses form-style query encoding: its + represents a space. decodeURIComponent by itself does not turn + into a space, so it is not a drop-in query parser.
| Case | Interpretation and next step |
|---|---|
| q=a&b | The unescaped & starts another parameter; use searchParams.set to retain it as data. |
| q=%2520 | One parse returns the literal text %20, not a space. Check whether the caller encoded twice. |
| #section | The fragment is not sent as part of the HTTP request target; do not store server-required input there. |
Build from components
Start with a complete HTTP(S) URL, then change one path segment or query value at a time. This keeps separators such as ?, &, =, and / meaningful instead of turning them into data.
Spot double encoding
%20 already represents a space. Encoding it again produces %2520, which changes the value rather than making it safer. Decode only the component you intend to inspect, then encode it once at the boundary.
Parsing is not a security review
A syntactically valid URL can still point to an untrusted host or an unsafe redirect target. Apply an explicit allowlist and server-side validation before fetching, redirecting, or rendering external addresses.
https://example.test/search?q=tea%20set&lang=zh-TWData provenance