Base64 turns 3 bytes into 4 characters
Base64 encoding takes data 3 bytes (24 bits) at a time, splits those bits into four groups of 6, and writes each number from 0 to 63 as one of 64 characters: A-Z, a-z, 0-9, + and /. Three bytes therefore always become four characters, and the result is about 33% longer than the original. Text is first turned into bytes, so 'Hello, café 👋' is 17 bytes (é takes two bytes in UTF-8 and the emoji takes four) and becomes the 24-character SGVsbG8sIGNhZsOpIPCfkYs=, with one = at the end. Base64 is not encryption, so anyone can reverse it.
The tool above lets you edit either box. Edit the text and it encodes; paste a value into the Base64 box and it decodes. Wrapped values such as an Authorization: Basic header, an email subject like =?UTF-8?B?…?=, a data: URL, a PEM certificate or a PowerShell -EncodedCommand are unwrapped for you. Bytes that are not valid UTF-8 are tried as Windows-1252 or UTF-16, or shown as a file such as a PNG or PDF. The decoding route shows the steps the conversion took, and the group rail and magnifier show where 3 bytes turn into 4 characters.
When you need to decode or build Base64 by hand
- Checking an HTTP Basic auth header: RFC 7617 joins the user name, a colon (:) and the password, encodes the result as Base64 and sends it after
Authorization: Basic. For example,admin:1234becomesYWRtaW46MTIzNA==. That also means anyone who sees the header can read the password, so Basic auth belongs on HTTPS only. - An email subject that looks like =?UTF-8?B?…?=: Mail headers are limited to ASCII, so a subject with an emoji or accents is written as an RFC 2047 encoded-word. The text between the first question marks (UTF-8 here) is the character encoding, and B means Base64. Paste the whole header value and the tool decodes it with the encoding it names; a value such as
=?UTF-8?B?WW91ciBvcmRlciBoYXMgc2hpcHBlZCDwn5Om?=reads as 'Your order has shipped 📦'. - Reading config values or a Kubernetes Secret: Values in the data field of a Kubernetes Secret must be Base64 strings; use stringData if you would rather not encode them. Use the tool to see what a stored value is, or to make the Base64 for a new one.
- Putting an image or PDF inside JSON: Base64 is a common way to carry file bytes in a format that only accepts text. If the value in the Base64 box is not text, the tool shows its type and size and lets you save it as a file.
- Looking inside a JWT: Each dot-separated part of a JWT is Base64url (RFC 7515): URL-safe characters with the trailing = removed. The header and payload decode here too, but the signature is not verified.
- Building or checking a PowerShell -EncodedCommand value: The PowerShell documentation says the value must be the Base64 of a UTF-16LE string. The same
Get-DateisR2V0LURhdGU=in UTF-8 butRwBlAHQALQBEAGEAdABlAA==in UTF-16LE. - Working with certificate and key files (PEM): The body between
-----BEGIN CERTIFICATE-----lines is Base64, wrapped at 64 characters per line as RFC 7468 requires. Decoding it gives DER bytes.
How to use it
- Encode: Type or paste text in the text box, or choose a file with 'Add file'. You can also drop or paste a file into the text box. The Base64 appears right away in the Base64 box.
- Decode: Paste a value into the Base64 box. Quotes or a header name around it are fine. The text appears in the text box, or, if the bytes are not text, a file card shows the type and size.
- Choose the shape: In the settings bar pick standard (+ /) or URL-safe (- _), padding with or without =, and one line, 76 or 64 characters per line. The shape of a pasted value is copied into the settings, so if you edit the decoded text it is rebuilt in the same shape.
- Text encoding: The default is auto-detect. If the decoded text looks wrong, choose UTF-8, UTF-16LE, Windows-1252 or another encoding yourself. If the box holds one value per line, turn on 'Each line separately'.
- Check: The decoding route shows the wrapper that was removed, the whitespace that was ignored and the padding that was added. Click a group on the rail to see its bits in the magnifier. If another tool gives a different result, look in 'Same text, different Base64' and click a row to copy that value.
The rule behind 3 bytes becoming 4 characters
Take the three ASCII bytes of 'Man', 4D 61 6E. Joined, they make 24 bits; cut into 6-bit pieces they give four numbers between 0 and 63; look those up in the alphabet below and you get TWFu.
| Step | First byte | Second byte | Third byte |
|---|---|---|---|
| Bytes | 4D | 61 | 6E |
| 8 bits each | 01001101 | 01100001 | 01101110 |
| 6 bits each | 010011 · 010110 · 000101 · 101110 | ||
| Number | 19 · 22 · 5 · 46 | ||
| Character | T · W · F · u | ||
When the data does not divide evenly into 3-byte groups, the missing bits are filled with 0 to finish the last character, and the empty slots are written as =. One leftover byte gives 2 characters and ==; two leftover bytes give 3 characters and =. RFC 4648 says an encoder sets the filler bits to 0 and a decoder may reject any other value.
| Text | Bytes | Base64 | Without = |
|---|---|---|---|
| Man | 3 | TWFu | TWFu |
| Ma | 2 | TWE= | TWE |
| M | 1 | TQ== | TQ |
| 😀 | 4 | 8J+YgA== | 8J+YgA |
| +0 | +1 | +2 | +3 | +4 | +5 | +6 | +7 | |
|---|---|---|---|---|---|---|---|---|
| 0 | A | B | C | D | E | F | G | H |
| 8 | I | J | K | L | M | N | O | P |
| 16 | Q | R | S | T | U | V | W | X |
| 24 | Y | Z | a | b | c | d | e | f |
| 32 | g | h | i | j | k | l | m | n |
| 40 | o | p | q | r | s | t | u | v |
| 48 | w | x | y | z | 0 | 1 | 2 | 3 |
| 56 | 4 | 5 | 6 | 7 | 8 | 9 | + / - | / / _ |
How long is the Base64?
With padding the length is 4 × ⌈n ÷ 3⌉ (n = number of bytes); without padding it is ⌈4n ÷ 3⌉. What counts is the number of bytes, not characters. In UTF-8 a plain English letter is 1 byte, an accented letter such as é is 2 and an emoji is 4, so text with many accents or symbols grows more than plain ASCII. Wrapping every 76 characters with a CRLF line break, as email does, adds 2 characters per line.
| Original | Bytes | With = | Without = | 76-char lines (CRLF) | Growth |
|---|---|---|---|---|---|
| Hello | 5 | 8 | 7 | 8 | 60% |
| Hello, café 👋 | 17 | 24 | 23 | 24 | 41.2% |
| 100 bytes | 100 | 136 | 134 | 138 | 36% |
| 1 KiB | 1,024 | 1,368 | 1,366 | 1,402 | 33.6% |
| 1 MiB | 1,048,576 | 1,398,104 | 1,398,102 | 1,434,896 | 33.3% |
| 5 MiB (file limit) | 5,242,880 | 6,990,508 | 6,990,507 | 7,174,468 | 33.3% |
Standard, URL-safe, MIME and PEM compared
The names differ, but the 3-bytes-to-4-characters calculation is the same. Only three things change: characters 62 and 63, the trailing =, and line wrapping.
| Variant | 62 and 63 | Trailing = | Line wrapping | Typical use | Source |
|---|---|---|---|---|---|
| Standard | + / | Kept | None | General data, data: URLs, Basic auth | RFC 4648 section 4 |
| URL-safe | - _ | Kept or removed | None | Values in URLs and file names | RFC 4648 section 5 |
| JWT (Base64url) | - _ | Removed | None | The three parts of a JWT or JWS | RFC 7515 section 2 |
| MIME (email) | + / | Kept | At most 76 characters per line | Email bodies and attachments | RFC 2045 section 6.8 |
| PEM | + / | Kept | 64 characters per line (except the last) | Certificate and key files | RFC 7468 section 2 |
| GNU base64 command | + / | Kept | 76 by default, one line with -w 0 | Linux command line | coreutils manual |
Decoders also differ in how strict they are. RFC 4648 says to reject characters outside the alphabet, while RFC 2045 for email says to ignore line breaks and characters that are not in the table. The browser's atob() removes only whitespace and throws an error on - or _ (WHATWG forgiving-base64). This tool ignores line breaks and spaces, turns %2B, %2F and %3D from URLs and \n escapes from JSON back into their characters, and accepts both standard and URL-safe characters. Anything else stops it, and it tells you the position.
The same text gives different Base64 in each text encoding
Base64 only writes bytes as characters, so the result depends on which bytes the text was turned into, that is, on the text encoding. Plain ASCII such as Hello has the same bytes in UTF-8 and Windows-1252, so the Base64 is the same too. Accented letters differ between the two, and UTF-16 doubles every character, so no result matches.
| Text | UTF-8 | Windows-1252 | UTF-16LE | UTF-16BE |
|---|---|---|---|---|
| café | Y2Fmw6k= | Y2Fm6Q== | YwBhAGYA6QA= | AGMAYQBmAOk= |
| Résumé | UsOpc3Vtw6k= | UulzdW3p | UgDpAHMAdQBtAOkA | AFIA6QBzAHUAbQDp |
| Hello | SGVsbG8= | SGVsbG8= | SABlAGwAbABvAA== | AEgAZQBsAGwAbw== |
| 日本語 | 5pel5pys6Kqe | not in Windows-1252 (日) | 5WUsZ56K | ZeVnLIqe |
Auto-detect first checks the opening bytes for a file signature such as PNG or JPEG. It then tries, in order, (1) an encoding that is written down or fixed, as in an email subject, a data: URL or PowerShell; (2) a BOM at the start (EF BB BF, FF FE, FE FF); (3) the UTF-16 pattern of a 00 byte after every ASCII character; (4) UTF-8, and keeps the first reading without control characters. If none of these works, it reads the bytes as EUC-KR, Shift_JIS, Windows-1252 and UTF-16 without 00 bytes, and picks the reading best filled with that encoding's own letters (Hangul, kana and kanji, accented Latin letters). On a tie, the page language's encoding wins (Windows-1252 on this page). Bytes alone cannot prove the encoding, so if the result looks odd, choose it yourself in the settings bar.
Wrappers the tool removes from pasted values
A copied value often has a header name or format marker around the Base64. The shapes below are unwrapped and only the Base64 inside is read; when you edit the text, the same wrapper is put back (except for a JWT, which needs its signature). Press the x button on the 'Wrapper kept' chip in the decoding route to drop the wrapper.
| Shape | Example | What happens |
|---|---|---|
| Basic auth | Authorization: Basic cm9i… | Read as UTF-8 first |
| Email subject | =?UTF-8?B?WW91ciBv…?= | Read with the encoding it names; several words are joined; when rebuilt, each word is kept to 75 characters or fewer |
| data: URL | data:image/png;base64,iVBOR… | Type and charset are used; if there is no ;base64, you are told it is not Base64 |
| PEM | -----BEGIN CERTIFICATE----- | Only the body is read, and 64-character lines are kept |
| PowerShell | powershell -EncodedCommand RwBl… | Read as UTF-16LE |
| JWT, Bearer | eyJhbGci….eyJzdWIi….signature | Header and payload are decoded onto separate lines; the signature is skipped |
| Quotes, Python | "SGVsbG8=", b'SGVsbG8=' | Only the quotes are removed |
| %XX in a URL | SGVsbG8%3D | %2B, %2F and %3D are turned back into +, / and = |
| \n inside JSON | MIIB…\nMIIC… | Treated as a line break and ignored |
When it will not decode: causes by error
If the value in the Base64 box cannot be read, the status line says which character it stopped at and shows the characters around it. The text box stays dimmed and shows the last result that was read successfully.
| Status | Example | Cause | Fix |
|---|---|---|---|
| Not a Base64 character | SGVs bG8! | Characters such as !, : or accented letters are mixed in | Remove explanatory text and symbols, leave only the value |
| Wrong length | SGVsb | Only 1 character is left in the last group of 4 | Check for a character lost or added while copying |
| Wrong number of = | SGVsbG8== | This length needs exactly one = | Remove one = |
| Characters after = | SGVsbG8=V29ybGQ= | Two values were joined together | Split them into lines and turn on 'Each line separately' |
| Last bits not 0 (warning) | SGVsbG | The spare bits of the last character are not 0, so the end may be cut off (it decodes to Hell) | Check the end of the original |
| Not valid UTF-8 | UulzdW3p | Bytes in another encoding, here Windows-1252 (Résumé) | Look at the auto-detected result or choose the encoding yourself |
| Looks like a file | iVBORw0KGgo… | Bytes that are not text (this one is a PNG signature) | Save it from the file card |
When the result differs from another tool
If you enter the same text and the Base64 differs, the bytes are almost always different or the shape settings are. The 'Same text, different Base64' list under the tool recalculates the cases below for your current text and shows the first difference.
| Cause | Text | Difference |
|---|---|---|
| Trailing newline added by echo | hello | printf gives aGVsbG8=, echo gives aGVsbG8K |
| Line breaks: LF or CRLF | First line ↵ Second line | LF Rmlyc3QgbGluZQpTZWNvbmQgbGluZQ==, CRLF Rmlyc3QgbGluZQ0KU2Vjb25kIGxpbmU= |
| Text encoding | café | UTF-8 Y2Fmw6k=, Windows-1252 Y2Fm6Q== |
| Standard or URL-safe | 😀 | 8J+YgA==, 8J-YgA== |
| Padding | Hello | SGVsbG8=, SGVsbG8 |
| Line wrapping | A large file | GNU base64 wraps every 76 characters; with -w 0 it stays on one line |
| How forgiving the decoder is | Zm9v-_ | Python b64decode() drops - and _ by default and leaves only b'foo'; this tool reads them as URL-safe characters |
Doing it in code
The browser's btoa() throws InvalidCharacterError for any character that does not fit in one byte, so text with an emoji or most non-Latin letters must be turned into UTF-8 bytes first. The newer Uint8Array.prototype.toBase64() works in Chrome 140, Firefox 133 and Safari 18.2 and later.
// JavaScript: turn text into UTF-8 bytes first (fine for short text)
const bytes = new TextEncoder().encode('café');
const b64 = btoa(String.fromCharCode(...bytes)); // Y2Fmw6k=
const back = new TextDecoder().decode(Uint8Array.from(atob(b64), c => c.charCodeAt(0)));
bytes.toBase64({ alphabet: 'base64url', omitPadding: true }); // newer API
# Python
import base64
base64.b64encode('café'.encode('utf-8')) # b'Y2Fmw6k='
base64.b64decode('SGVsbG8') # no = at the end: binascii.Error: Incorrect padding
base64.b64decode('Zm9v-_', validate=True) # error instead of silently dropping non-alphabet characters
# Command line
printf '%s' 'café' | base64 # echo adds a trailing newline
base64 -w 0 report.pdf # GNU: no wrapping (macOS base64 is one line by default; -b 76 wraps)
Common mistakes
- Treating Base64 as encryption: Anyone can reverse it without a key. Turning a password or token into Base64 does not hide it.
- Using a value made with echo as it is:
echoadds a trailing newline, so the result ends differently, for example inKoro=. Useprintf '%s'orecho -n. - Changing letter case: Base64 treats upper and lower case as different characters. Changing the case to tidy it up gives different data or a value that no longer decodes.
- Putting standard Base64 straight into a URL query: In form-data parsing + becomes a space, and / and = also have meaning inside a URL. Use URL-safe Base64 or percent-encode the value.
- Encoding twice: If the decoded result still looks like Base64, a 'Decode once more' button appears next to the status line.
- Leaving off the data: prefix on an image: In HTML or CSS you need the
data:image/png;base64,prefix. For images, the image to Base64 converter builds the HTML and CSS forms for you.
Limits
- Files up to 5 MB can be added (about 7 million characters of Base64). If the text in a box passes 400,000 characters, only the start and end are shown; copy and save still include all of it.
- Auto-detect is an estimate from the shape of the bytes. A short value can be read in several encodings, so it can be wrong.
- You can build UTF-8, UTF-16LE and BE, EUC-KR (CP949), Shift_JIS and Windows-1252. An encoding named in an email subject that the tool cannot build, such as ISO-2022-JP, is read only; if you edit the decoded text, it is rebuilt in UTF-8.
- The JWT signature is not verified, and Q encoding in an email subject (=?…?Q?…?=) is not decoded.
- A browser text box turns line breaks into LF, so line breaks in the text box are encoded as LF. If you need CRLF, copy the CRLF row from 'Same text, different Base64'.
- The group rail draws the first 480 groups (1,440 bytes). The rest is still converted and copied.
- Everything is converted inside this browser; the value you enter is not sent to a server or kept in the address or in storage.
Sources
Basis: The Base64 format follows RFC 4648, the uses in email, PEM, authentication headers and JWT follow their own RFCs, browser behaviour follows the WHATWG standards and MDN, and command-line and language behaviour follows each manual; all were checked on 21 October 2026. The values in the tables were confirmed with this tool and Python 3.14's base64 module.
- 01RFC 4648 — The Base16, Base32, and Base64 Data Encodings3.1 line breaks, 3.3 rejecting characters outside the alphabet, 3.5 spare bits set to 0, section 4 alphabet, section 5 URL-safe (- _), section 10 test values
- 02RFC 2045 — MIME Part One6.8 lines of at most 76 characters; decoders ignore line breaks and characters not in the table
- 03RFC 2047 — MIME Part Three: Message Header Extensionsencoded-word form =?charset?B?…?=, at most 75 characters per word, B = BASE64
- 04RFC 7468 — Textual Encodings of PKIX StructuresPEM body wrapped at 64 characters per line except the last
- 05RFC 7617 — The 'Basic' HTTP Authentication Schemeuser name + ':' + password as Base64; the charset parameter allows UTF-8 only
- 06RFC 7515 — JSON Web Signature (JWS)Section 2 Base64url: URL-safe characters, trailing = removed, no line breaks
- 07RFC 2397 — The "data" URL schemedata: + media type + optional ;base64 + comma + data
- 08WHATWG Infra — forgiving-base64 decodeRules behind atob(): strip whitespace, allow 1 or 2 trailing =, fail on characters outside + /
- 09WHATWG — Encoding StandardHow TextDecoder reads UTF-8, UTF-16, EUC-KR, Shift_JIS and Windows-1252
- 10MDN — Window.btoa()InvalidCharacterError for characters that do not fit in one byte
- 11MDN — Uint8Array.prototype.toBase64()alphabet (base64, base64url) and omitPadding options; supported versions come from the MDN browser compatibility data
- 12Python 3 — base64 moduleb64decode(validate=False) discards characters outside the alphabet; urlsafe_b64encode
- 13GNU coreutils — base64(1)-w (--wrap) defaults to 76; 0 means no wrapping
- 14Microsoft Learn — about_PwshThe -EncodedCommand value is the Base64 of a UTF-16LE string
- 15Kubernetes — SecretsValues in the data field are Base64; use stringData to avoid encoding
Frequently asked questions
Is Base64 encryption?
No. Base64 only writes bytes as 64 printable characters, so anyone can turn it back into the original value without a key. For example, YWRtaW46MTIzNA== in a Basic auth header decodes straight to admin:1234. To protect a password or token, use HTTPS and real encryption.
Why does the same text give a different Base64 on different sites?
Usually the bytes are different. 'café' is Y2Fmw6k= in UTF-8, Y2Fm6Q== in Windows-1252 and YwBhAGYA6QA= in UTF-16LE. A trailing newline added by echo (hello becomes aGVsbG8K), CRLF instead of LF, URL-safe characters, a missing = and 76-character line wrapping also change the result. The 'Same text, different Base64' list under the tool shows these cases side by side.
What is the = at the end, and can I remove it?
The = is padding that fills the last group of 4 characters when it comes from fewer than 3 bytes. It is not part of the data. One leftover byte gives ==, two give =. Some formats, such as JWT, say to drop it and others do not, so follow the receiving side. This tool reads the value with or without it.
How do I calculate the length of Base64?
With padding it is 4 × ⌈bytes ÷ 3⌉; without padding it is ⌈4 × bytes ÷ 3⌉. Hello is 5 bytes and gives 8 characters, 'Hello, café 👋' is 17 bytes and gives 24, and 1 MiB (1,048,576 bytes) gives 1,398,104, about 33% more. Wrapping every 76 characters with CRLF adds 2 characters per line.
What if the decoded text shows broken characters?
The original bytes are probably not UTF-8. If they do not read as UTF-8, this tool retries them as Windows-1252 and UTF-16. If é turns into é or the text still looks wrong, pick UTF-8, UTF-16LE, Windows-1252 or another encoding yourself in the settings bar and compare.
Which Base64 format should I put in a URL?
Use URL-safe Base64. In standard Base64 the + is read as a space when form data is parsed, and / and = have meaning inside a URL. URL-safe replaces characters 62 and 63 with - and _ (RFC 4648 section 5); if the receiver does not want =, also choose 'No ='.
How do I read an email subject like =?UTF-8?B?…?=?
It is an RFC 2047 encoded-word. The part before the second question mark is the character encoding, B means Base64, and the next part is the Base64 body. Paste the whole value into the Base64 box and it is decoded with the named encoding; a subject split into several words is joined. A value marked Q is not Base64 and is not decoded.
Can I turn a Base64 image or PDF back into a file?
Yes. If the value in the Base64 box is not text, the tool looks at the first bytes to find the type, such as PNG, JPEG, PDF or ZIP, shows a file card and lets you save it. In the other direction, 'Add file' converts a file of up to 5 MB. Everything happens in your browser and nothing is sent to a server.