%28 is an open parenthesis

%28 is an open parenthesis. It is legal raw in a URL, and most encoders leave it exactly as typed.

Character"("
NameOpen Parenthesis
Encoded%28
ReservedYes — it has a special meaning in a URL

Why it breaks things

An open parenthesis is an RFC 3986 sub-delimiter, the same group as the comma and the exclamation mark — no fixed job in the generic syntax. Browsers and servers pass a raw ( straight through. JavaScript's encodeURIComponent does too, on purpose: verified, encodeURIComponent("(") returns ( unchanged, not %28. encodeURI leaves it alone as well.

That is not universal. Python's urllib.parse.quote, with default settings, encodes the same character to %28 — verified. Its safe list is much shorter than JavaScript's, covering little beyond letters, digits and a slash. Whether a parenthesis survives encoding depends on which function did the encoding, not on any rule about the character itself.

The trouble shows up downstream, once a legal, unencoded value reaches something stricter than a browser. Some web application firewalls flag a raw ( and ) in a query value as suspicious, since that shape also appears in function-call injection attempts, like alert(1). A search for Smith (Accounts) can get blocked at that layer, not because anything is malformed, but because parentheses read as a warning sign to a filter built for a different threat.

Real examples

Without encoding

https://example.com/directory?q=Smith (Accounts)

With encoding

https://example.com/directory?q=Smith%20%28Accounts%29

The raw parentheses are legal here and reach the server unchanged; only the space needs encoding for encodeURIComponent to touch this string at all. Encoding the parentheses anyway is harmless, and can help clear a security filter further down the chain that treats raw ( ) as suspicious.

Without encoding

https://example.com/search?tag=web(dev)

With encoding

https://example.com/search?tag=web%28dev%29

A tag using parentheses as a grouping mark, common in tagging systems. Nothing in the URL standard requires encoding this, and most servers accept it as-is — some API gateways and firewalls are stricter, and reject or flag it purely because of the function-call shape.

Decode something

History

    Nothing yet.

    History stays in this browser. It is never sent to our server.

    Common questions

    Do I need to percent-encode parentheses in a URL?
    Not for the URL itself. RFC 3986 lists ( and ) as sub-delimiters, legal to use unencoded, and browsers and servers pass them straight through. Encoding them anyway can help with stricter infrastructure further down the chain.
    Why doesn't encodeURIComponent touch my parentheses?
    Because JavaScript's built-in encoder treats them as part of its safe set, alongside characters like ! ~ and *, and never escapes them. This is deliberate, not a bug — it matches the set of characters the URL standard treats as always safe to write literally.
    Why did my search get blocked by a security filter when nothing looks wrong?
    Some web application firewalls flag literal parentheses in a query value, because the shape resembles a function call used in injection attempts, such as alert(1). The value can be entirely legal by the URL standard and still trip a rule written for a different threat.
    Does every encoder leave parentheses alone like JavaScript does?
    No. Python's urllib.parse.quote, for example, encodes a parenthesis to %28 by default, because its safe list is much narrower than JavaScript's. Which functions touch a given character varies by language and library, not by one universal rule.