%5E is a caret
%5E is a caret, excluded from RFC 3986's allowed characters, though many browsers leave a raw one alone in a path or query.
| Character | "^" |
|---|---|
| Name | Caret |
| Encoded | %5E |
| Reserved | No |
Why it breaks things
A caret is not a sub-delimiter and not part of the unreserved set either — RFC 3986 excludes it outright, in the same small group as the backtick and the curly braces, characters an older URI specification named as ones gateways were known to mangle. Strictly, a URL should never contain a raw ^ at all.
Browsers are more forgiving than the spec suggests. Verified with a standards-compliant URL parser: a raw ^ in a path or query string is left exactly as typed, with no automatic percent-encoding — https://example.com/pkg/^1.2.3 and ?version=^1.2.3 both come through unchanged. The one place it is encoded automatically is the userinfo section before an @, where a stray ^ does get escaped.
JavaScript disagrees with that leniency: encodeURIComponent("^") and encodeURI("^") both return %5E, verified — the encoders treat it as unsafe even where a browser's own address bar would not. Its common home is a semver version range, like ^1.2.3 in a package URL, and because the character sits outside every officially allowed set, some HTTP clients and API gateways are stricter than a browser and reject a raw one outright.
Real examples
Without encoding
https://registry.example.com/packages/left-pad/^1.2.3
With encoding
https://registry.example.com/packages/left-pad/%5E1.2.3
Most browsers accept the raw caret here and send it through unchanged — verified, it is not in the WHATWG path percent-encode set. It is still outside RFC 3986's allowed characters, so some non-browser HTTP clients and API gateways reject or mishandle it. Encoding it removes that risk entirely.
Without encoding
https://example.com/search?range=^100
With encoding
https://example.com/search?range=%5E100
A raw caret in a query value is read literally by most servers and is not touched by a typical browser. JavaScript's own encodeURIComponent disagrees and escapes it to %5E by default, which is a useful signal that the character is not considered safe even though your browser tolerated it.
Decode something
Result
Breakdown
| Part | Value | Copy |
|---|
History
Nothing yet.
History stays in this browser. It is never sent to our server.
Common questions
- Is a caret allowed raw in a URL?
- Not officially. RFC 3986 excludes it from both the reserved and unreserved sets, so a strictly valid URL should percent-encode it. In practice, many browsers leave a raw caret alone in a path or query string and send it through unchanged.
- Why does encodeURIComponent encode my caret if browsers don't?
- Because JavaScript's encoder and a browser's own URL parser follow different rules. encodeURIComponent treats ^ as unsafe and always escapes it to %5E. A browser navigating to a typed or clicked URL applies a narrower set of automatic encodings that does not include the caret in a path or query.
- Why does ^1.2.3 show up in package URLs?
- It is semver range syntax, meaning "compatible with 1.2.3, allowing minor and patch updates." When that string ends up in a URL, whether it survives unencoded depends on which tool is handling the request, since the caret sits outside every character set RFC 3986 officially allows.
- Where does a browser actually encode a caret automatically?
- Only in the userinfo section, the optional username and password before an @ in the authority part of a URL. Elsewhere — the path, the query string, the fragment — a raw caret is typically left as typed.