The quick answer
You have a string like SGVsbG8= that you need to read, or a file or an image that has to travel as plain text. Open the Base64 encoder and decoder. It converts text, files and images in both directions, and it runs in your browser.
- Choose Encode, Decode, Image to Base64 or Base64 to image at the top.
- Paste text or choose a file. The result updates as you type, with nothing to submit.
- Change the options only if the place you will use the result needs them: the URL-safe alphabet, no
=padding, or lines wrapped at 64 (PEM) or 76 (MIME) characters. - Copy the result. When decoding a file, download the original.
What Base64 is for
Base64 writes any bytes using 64 characters that survive anywhere text goes: A to Z, a to z, 0 to 9, + and /, with = as padding. It exists because many channels were built for text and damage raw bytes. You meet it in email attachments (MIME), data: URIs, binary values inside JSON or XML, HTTP Basic authentication headers, PEM certificate files and JWTs.
It works on 3 bytes at a time. The word Man is the bytes 77, 97 and 110, which are 24 bits. Base64 cuts those 24 bits into four groups of 6 bits and writes each group as one character, so Man becomes TWFu. Six bits is 64 possible values, hence the name.
Why Base64 is 33 percent bigger
Three bytes in, four characters out. That is a ratio of 4 to 3, so the text is one third larger than the data. For n bytes the text is 4 × ceil(n ÷ 3) characters: the last group is padded up to a full four.
| Original size | Base64 text | Growth |
|---|---|---|
| 1 byte | 4 characters | 300% |
| 2 bytes | 4 characters | 100% |
| 3 bytes | 4 characters | 33.3% |
| 1,000 bytes | 1,336 characters | 33.6% |
| 1,000,000 bytes | 1,333,336 characters | 33.3% |
| 3,000,000 bytes (a 3 MB photo) | 4,000,000 characters | 33.3%, one extra megabyte |
Line wrapping adds a little more: with lines of 76 characters, a 1,000,000 byte file grows by 35.1 to 36.8 percent, depending on whether a line break is one character or two. Only the tiny inputs look dramatic. For anything larger, plan on one third more.
Standard and URL-safe Base64
Standard Base64 uses + and /, and both mean something in a URL or a file name. The URL-safe form swaps them for - and _ and often drops the = padding. Take the text hi??>:
| Variant | hi??> becomes | Where you see it |
|---|---|---|
| Standard | aGk/Pz4= | Email, PEM files, data URIs, Basic authentication, most encode buttons |
| URL-safe, no padding | aGk_Pz4 | JWTs, many API tokens, file-name-safe identifiers |
The two differ in a couple of characters, but a decoder that expects one can reject the other. The Decode view reads both, and adds a note when the text is URL-safe or mixes the two. To put ordinary text into a link instead, use the URL encoder, which escapes characters one by one and leaves the rest readable.
Images and files as Base64
A data URI puts a file inside a page or a stylesheet: data:image/png;base64, followed by the Base64. Image to Base64 gives you that URI, a ready img tag, a CSS background-image line or Markdown, with the file size next to the size of the text. Base64 to image goes back: it shows the picture, reads the real type from the bytes and saves it with the right extension, even when the data URI's label is wrong.
- Inline it for a tiny icon of a few kilobytes, or for a single-file page, demo or bug report that must work on its own.
- Serve a normal file for anything bigger. An inlined image cannot be cached on its own, so it travels with whatever file holds it, and it carries the 33 percent extra.
- Not in email. Many email clients do not show images inlined as data URIs, so attach the image or link to a hosted copy.
In the encoder's file mode any file type works, up to 50 MB (Image to Base64 takes images only), because the browser holds the file and its Base64 text in memory at once. APIs often send files as Base64 strings inside JSON; if the response will not parse, format and validate the JSON first.
Reading Base64 at a glance
Every file format starts with fixed bytes, so its Base64 starts with fixed characters. A few are worth knowing:
| Starts with | Decodes to |
|---|---|
eyJ | {" followed by a letter: a JSON object, which is how a JWT header and payload usually begin |
JVBERi0 | %PDF-, a PDF |
iVBORw0KGgo | The 8 byte PNG signature |
/9j/ | The bytes FF D8 FF, a JPEG |
R0lGOD | GIF8, the start of GIF87a or GIF89a: a GIF |
UEsDB | PK followed by control bytes: a ZIP file, including .docx and .xlsx |
Why a decode fails
Start from the symptom:
| Symptom | Cause | Fix |
|---|---|---|
| A character is "not part of the alphabet" | A quotation mark, a % or another stray character, or - and _ fed to a standard-only decoder | Remove it. The Decode view accepts both alphabets and names the character |
| The length is wrong | The text was cut off. Unpadded Base64 leaves a remainder of 0, 2 or 3 when divided by 4, never 1, because one leftover character holds 6 bits and a byte needs 8 | Copy the whole string |
An = in the middle | Two Base64 strings were joined | Decode them one at a time |
é shows as é | Wrong text encoding. In UTF-8, é is the bytes C3 A9, which is w6k=, and read as Latin-1 those bytes are é. Latin-1 é is one byte, E9: 6Q== | Switch Show text as between UTF-8, Latin-1 and UTF-16 |
| A wall of symbols | It was never text: an image, PDF or ZIP | The tool names the type and offers a download |
| The result is Base64 again | It was encoded twice | Decode the result again |
| Backslashes before slashes | Copied from a JSON string, where / may be written \/ | Remove the backslashes |
Two more cases cause mismatches between tools. echo "hello" | base64 encodes the line break that echo adds and gives aGVsbG8K, while printf hello | base64 gives aGVsbG8=. And JavaScript's btoa() throws on any character outside Latin-1, such as 你 or an emoji, so text must become UTF-8 bytes first, which the tool does for you. The same bytes-versus-letters mix-up breaks accents in a CSV, as converting CSV to Excel and JSON explains.
Base64 is not security
Anyone can decode Base64 with no key. The header Authorization: Basic dXNlcjpwYXNz carries user:pass in plain sight, which is why Basic authentication must always run over HTTPS. The readable parts of a token are the same story, as decode a JWT token shows. A password stored as Base64 in a config file is a plain password.
If data must be secret, it needs real encryption, and any password that protects it should be long and random: see make a strong password. If you only need to know that a file was not changed, you need a hash, and verifying a download with a hash explains that job with the hash generator.
A note on privacy: pasted Base64 often holds a credential or a customer's file, and anyone can decode it. The converter runs in your browser, and the Network tab of your developer tools will show that no request carries what you paste.