Base64 of “foob” (two padding characters)
- Encoding
- Base64
- Direction
- Encode
- Text
- foob
- Result
- Zm9vYg==
- UTF-8 bytes
- 4
- Result length
- 8 characters
Checked against: RFC 4648 §10 test vectors
Encode or decode Base64, URL-safe Base64, URL percent-encoding, HTML entities, hex bytes and Unicode code points, with UTF-8 and UTF-16 byte counts.
By AdminDrafted with AI writing toolsUpdated Checked examples: 17
17 characters become 21 UTF-8 bytes; as Base64 they take 28 characters, 1.33 per byte.
17 characters → 21 bytes.
First group: 43 61 66 → 010000 110110 000101 100110 → 16, 54, 5, 38 → “Q2Fm”.
Every scheme here starts from the text's UTF-8 bytes. Base64 regroups each 3 bytes into four 6-bit values drawn from a 64-character alphabet (RFC 4648), so the output is 4 × ⌈n ÷ 3⌉ characters. Percent-encoding writes every byte outside A–Z, a–z, 0–9 and - . _ ~ as %XX (RFC 3986), HTML escaping replaces & < > " and ' with character references, and hex writes two digits per byte.
Developers use it to put binary data in JSON or email, build query strings, read JWTs and track down character-set problems. The default, "Café & crème, 5 €", is 17 characters but 21 UTF-8 bytes, because é and è take 2 bytes each and € takes 3, and its Base64 form is 28 characters.
A decoding error names the bad character and its position, and bytes that aren't valid UTF-8 show as U+FFFD (�).
Base64 writes bytes as plain text. It takes the text's UTF-8 bytes three at a time, splits each 24-bit group into four 6-bit values and maps each value to one of 64 characters: A–Z, a–z, 0–9, + and /. So Man becomes TWFu, and every 3 bytes become 4 characters, which makes the output about 33% larger.
Man by hand01001101 01100001 01101110.010011 010110 000101 101110 = 19, 22, 5, 46.+ and /. So 19 = T, 22 = W, 5 = F and 46 = u.When the length is not a multiple of 3, the last group is filled with zero bits and = signs: Ma is TWE= and M is TQ==. RFC 4648 defines the alphabet and the padding rules.
The URL-safe alphabet swaps + and /, which clash with URLs and file names, for - and _, and usually drops the padding. <<???>> is PDw/Pz8+Pg== in standard Base64 and PDw_Pz8-Pg in Base64URL.
Signed JSON Web Tokens use Base64URL for each of their three dot-separated parts. Their headers usually start with eyJ, the encoding of {" followed by a letter: eyJhbGciOiJIUzI1NiJ9 decodes to {"alg":"HS256"}.
RFC 3986 leaves only letters, digits and - . _ ~ as they are. Every other byte becomes % plus two hex digits, and non-ASCII characters are encoded from their UTF-8 bytes, so é becomes %C3%A9.
The query value a b&c=d/é? becomes a%20b%26c%3Dd%2F%C3%A9%3F. The &, = and / are escaped because they belong to the value, so encode each URL component on its own, never a whole URL.
%20 or +. HTML forms (application/x-www-form-urlencoded) write a space as +, so a+b in a form query means a b. In a URL path, + is a literal plus.encodeURIComponent gives the same result except that it leaves ! ' ( ) * unescaped. encodeURI keeps / ? & = # intact and suits whole URLs only.%20 again gives %2520. Decode once, where the value enters your code.HTML escaping replaces the five characters that can break markup: & with &, < with <, > with >, " with " and ' with '. That protects text inside elements and quoted attributes, not inside a <script> block or a URL.
Hex writes each UTF-8 byte as two digits, so é€ is c3 a9 e2 82 ac. Code-point notation names characters instead of bytes: A€😀 is U+0041 U+20AC U+1F600.
A code point takes 1 to 4 bytes in UTF-8 (RFC 3629) and 1 or 2 code units in UTF-16. JavaScript strings count UTF-16 units, so "😀".length is 2.
| Scenario | Code points | UTF-8 bytes | UTF-16 units |
|---|---|---|---|
| Default | 17 | 21 | 17 |
| unicode Unicode | 3 | 8 | 4 |
| Combining marks | 2 | 3 | 2 |
| Emoji sequence | 7 | 25 | 11 |
| Invalid UTF-8 hex | 2 | 2 | 2 |
Default is Café & crème, 5 €, where é and è take 2 bytes each and € takes 3. The second row is A€😀, and the third is an e followed by the combining accent U+0301.
The emoji row is the family 👨👩👧👦: four people joined by three zero-width joiners, drawn as one symbol. The last row decodes the hex bytes c3 28, which are invalid UTF-8 and come out as �(.
btoa on Unicode text. In browsers btoa('é') returns 6Q==, the Latin-1 byte, not the UTF-8 w6k=, and btoa('€') throws. Encode to UTF-8 bytes first, for example with TextEncoder.- and _, and a strict Base64URL decoder rejects + and /.Café & crème, 5 € is 17 characters but 21 UTF-8 bytes, which matters for column limits and Content-Length headers.0x prefixes. Code points can be written U+1F600, \u{1F600}, 0x1F600 or 😀.To fingerprint data instead of encoding it, use the hash calculator.
Checked against: RFC 4648 §10 test vectors
Checked against: Independent calculation
Checked against: the standard alphabet gives PDw/Pz8+Pg==
Checked against: Independent calculation
Base64 carries 6 bits in each output character against 8 bits in each input byte, so every 3 bytes become 4 characters, a ratio of 4 to 3, plus up to 2 = padding characters at the end. 21 bytes become 28 characters, and 1 MB of binary becomes about 1.33 MB. MIME email (RFC 2045) also breaks the output into lines of at most 76 characters, which adds a little more.
Base64URL (RFC 4648 §5) replaces the two characters that clash with URLs and file names, + and /, with - and _, and usually drops the = padding. JSON Web Tokens (RFC 7519) use it for all three of their parts. The text <<???>> is PDw/Pz8+Pg== in standard Base64 and PDw_Pz8-Pg in the URL-safe form, 10 characters instead of 12.
No. Base64 is a reversible encoding with no key, so anyone can decode it in one step; it only makes binary data safe to carry as text. HTTP Basic authentication (RFC 7617), for example, sends user:password in Base64, which is why it is only safe over HTTPS. To protect data, encrypt it first, for example with AES-256, and then Base64-encode the ciphertext if it must travel as text.
Both appear, in different places. RFC 3986, which governs URLs, encodes a space as %20, while HTML form submissions (application/x-www-form-urlencoded) write it as +. So a+b in a form's query string means a b, but in a URL path the + is a literal plus. JavaScript's encodeURIComponent gives %20, and Python's urllib.parse.quote_plus gives +.
One to four. Code points below U+0080 (ASCII) take 1 byte, those up to U+07FF take 2 (é, ñ, Greek, Cyrillic), those up to U+FFFF take 3 (€ and most Chinese characters) and the rest take 4, including emoji such as 😀 (U+1F600). So A€😀 is 3 characters, 8 UTF-8 bytes and 4 UTF-16 code units, because 😀 needs a surrogate pair in UTF-16 (RFC 3629).
This calculator includes 17 worked examples with independently sourced answers. They run in the test suite, and you can run them here too.