%21 is an exclamation mark

%21 is an exclamation mark, legal raw in a URL and mostly harmless, apart from two specific places it is not.

Character"!"
NameExclamation Mark
Encoded%21
ReservedYes — it has a special meaning in a URL

Why it breaks things

An exclamation mark is an RFC 3986 sub-delimiter, with no fixed meaning in the generic syntax. A raw ! travels through a browser, a server, or a query value without any trouble — there is no character-level reason to encode it.

One real exception is historical. Google's AJAX crawling scheme, active from around 2009 and deprecated in 2015, used a fragment starting with #! — a hashbang — to tell a crawler a snapshot of the page existed elsewhere, since a fragment is otherwise invisible to a server. Sites built for that scheme still show up occasionally; treat #! as a legacy pattern, not something to imitate today.

The other exception depends on where the URL is typed rather than anything about the web. In an interactive bash session, with history expansion on by default, a bare ! outside quotes tries to recall a previous command — pasting http://example.com/user!123 can produce bash: !123: event not found instead of making the request. This does not happen in a script, where history expansion is off, which is why the same line works fine saved in a file and fails typed straight into a terminal.

Real examples

Without encoding

https://example.com/#!/products/482

With encoding

https://example.com/%23%21/products/482

The raw form is not broken — it is exactly how Google's now-deprecated AJAX crawling scheme expected a hashbang URL to look. Encoding it removes that historical meaning entirely, which is the point once a site no longer relies on it.

Without encoding

https://example.com/user!123

With encoding

https://example.com/user%21123

Typed straight into an interactive bash session, the unquoted ! triggers history expansion and bash reports 'event not found' instead of running the command. The same URL works fine inside a script, where history expansion is off by default — quoting it avoids the problem either way.

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 an exclamation mark in a normal URL?
    Not for the URL to work. It is an RFC 3986 sub-delimiter with no meaning of its own, and browsers and servers pass a raw ! through without issue.
    What is a hashbang URL and why don't sites use it anymore?
    A URL like example.com/#!/page used a fragment starting with #! so a crawler could ask for a pre-rendered snapshot of an AJAX page, part of a scheme Google introduced around 2009. Google deprecated it in 2015 in favor of crawling JavaScript-rendered pages directly, and modern sites use pushState-based URLs instead.
    Why did my terminal say 'event not found' when I pasted a URL?
    An unquoted ! in an interactive bash session triggers history expansion, which tries to match the text after it against a previous command. If nothing matches, bash reports the error instead of sending the request. Wrapping the URL in single quotes prevents this.
    Does this history expansion problem happen in shell scripts too?
    No. History expansion is off by default in non-interactive shells, including scripts, so a ! in a URL there is left exactly as written. It only causes trouble when typed straight into an interactive terminal session.