CompoundPage

Base64url Encode

Base64url encode text the way a JSON Web Token does: the URL-safe alphabet with - and _, and no padding. It opens on a JWT header, which comes out as the familiar eyJ prefix.

Base64 to decode, or text to encode. Line breaks, spaces and a data: prefix are skipped when decoding.

Decoding reads either alphabet on its own.

Base64urleyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Length Unpadded: ceil(27 x 4 / 3) = 36. Padded it would be 36.
36 characters
Bytes encoded From 27 characters, all ASCII, so one byte each.
27 bytes of UTF-8
Padding 27 is a multiple of 3, so the last group is full and nothing is added.
none needed
Size increase
33%
Alphabet RFC 4648 section 5. The same as standard Base64 except that values 62 and 63 are written - and _, which need no escaping in a URL or a file name.
URL-safe, - and _
The steps, first 6 of 9 groups
GroupBytes (hex)Six-bit groupsIndexesBase64
17B 22 61011110 110010 001001 10000130, 50, 9, 33eyJh
26C 67 22011011 000110 011100 10001027, 6, 28, 34bGci
33A 22 48001110 100010 001001 00100014, 34, 9, 8OiJI
453 32 35010100 110011 001000 11010120, 51, 8, 53UzI1
536 22 2C001101 100010 001000 10110013, 34, 8, 44NiIs
622 74 79001000 100111 010001 1110018, 39, 17, 57InR5

How the Base64 Decode and Encode works

Base64url is standard Base64 with two characters changed. Values 62 and 63 are + and / in the standard alphabet, and both mean something in a URL: + can be read as a space in a query string and / separates path segments. RFC 4648 section 5 defines the URL- and filename-safe alphabet, which writes them as - and _ instead. Every other character, and every bit of the method, is the same.

The padding usually goes as well. The = sign is also special in a URL (it separates a query key from its value), and padding carries no data: the length of the string already says how many bytes the last group holds. Two leftover characters mean one byte and three mean two. So base64url is normally written without it, and JSON Web Tokens (RFC 7519) require that.

The example is the JWT header {"alg":"HS256","typ":"JWT"}, 27 bytes of ASCII. 27 is a multiple of three, so it encodes to exactly 36 characters with no padding to drop, and it starts eyJ because every JSON object starts with {", which encodes to eyJ. That is why a token is recognizable at a glance. The header holds no + or / either, so for this input the URL-safe and standard alphabets agree. Other text differs wherever the bits make a 62 or a 63.

Decoding base64url needs no setting. The Base64 decoder reads either alphabet and works out the padding from the length, so a JWT segment pasted as is decodes to its JSON. It does refuse a string that mixes the two alphabets, which usually means two values were pasted together.

A JWT's payload is readable by anyone who has the token, since base64url is an encoding and not encryption. The signature proves the token was not changed; it does not keep the claims secret.

Base64 Decode and Encode FAQ

What is the difference between Base64 and Base64url?

Two characters and the padding. Base64url writes values 62 and 63 as - and _ instead of + and /, so the result is safe in URLs and file names, and it usually leaves off the trailing = signs. The decoded bytes are identical.

Why do JWTs start with eyJ?

Because the header is a JSON object, which starts with {" and those two bytes, 7B 22, plus the high bits of the next byte, encode to eyJ. The payload is JSON too, so the second segment usually starts with eyJ as well.

How do I convert base64url back to standard Base64?

Replace - with + and _ with /, then add = until the length is a multiple of four. A decoder that reads base64url directly does not need the padding.

More from the Base64 Decode and Encode

Related calculators

Embed this calculator
<div id="compoundpage-base64-decode"></div>
<script src="https://compoundpage.com/embed/base64-decode.js" async></script>

The same calculation as JSON