%3D is an equals sign

%3D is an equals sign.

Character"="
NameEquals Sign
Encoded%3D
ReservedYes — 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

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.