%3D is an equals sign
%3D is an equals sign.
| Character | "=" |
|---|---|
| Name | Equals Sign |
| Encoded | %3D |
| Reserved | Yes — it has a special meaning in a URL |
Why it breaks things
In a query string, an equals sign separates a parameter's name from its value. A pair like token=abc123 is split at the first = into a key, token, and a value, abc123. Only that first = does the splitting — any = appearing later in the same pair is left alone and becomes part of the value.
This is why Base64 values usually survive unencoded even though they often end in =. Base64 pads its output with one or two = characters when the input length is not a multiple of three bytes — encoding order-4521 produces b3JkZXItNDUyMQ==, with two padding characters at the end. Put into a URL as ref=b3JkZXItNDUyMQ==, a compliant parser like URLSearchParams still reads it back correctly, because it only looks at the first =.
Hand-written parsing code is where this breaks. Code that manually splits a parameter on = and unpacks it into exactly two variables — key, value = pair.split('=') in Python — throws an error the moment a value contains an extra = sign, Base64 padding included. Some token formats avoid this: JSON Web Tokens use a version of Base64 that drops the padding entirely, so a token never carries a stray = into a URL.
Real examples
Without encoding
https://example.com/orders/confirm?ref=b3JkZXItNDUyMQ==
With encoding
https://example.com/orders/confirm?ref=b3JkZXItNDUyMQ%3D%3D
Most real query-string parsers handle the double = at the end correctly, since they only split on the first = in the pair. But code that manually splits a parameter and expects exactly two pieces — a common way to write a quick parser — throws an error the moment it hits the extra = signs from Base64 padding.
Without encoding
https://example.com/dashboard?filter=price=50
With encoding
https://example.com/dashboard?filter=price%3D50
A compliant parser reads this correctly as filter=price=50, because only the first = counts. Encoding the inner = removes the ambiguity for any tool further down the chain that assumes a parameter can only contain one equals sign.
Decode something
Result
Breakdown
| Part | Value | Copy |
|---|
History
Nothing yet.
History stays in this browser. It is never sent to our server.
Common questions
- Why does a Base64 token with == at the end still work in a URL?
- Because a query string parser only looks at the first = in each pair to find where the value starts. Everything after that, including any = from Base64 padding, is kept as part of the value rather than treated as another divider.
- Why did my code crash with 'too many values to unpack' when parsing a URL?
- That happens when code manually splits a parameter on = and expects exactly two pieces, a key and a value. If the value itself contains an =, like Base64 padding does, the split produces more than two pieces and the unpacking fails. The fix is to split only on the first =, which is what URLSearchParams and similar libraries do automatically.
- Why don't JSON Web Tokens have this problem?
- JWTs use a version of Base64 that drops the trailing = padding entirely, precisely so a token never needs encoding to travel safely in a URL.
- Is %3D the same kind of divider as %26?
- They work together. & marks the boundary between one parameter and the next; = marks the boundary between a parameter's name and its value. Only the first instance of each counts — extra & or = signs inside a value are read as literal characters, not new dividers.