Base64 Decode & Encode: to PDF, Image or Any File
Paste Base64 and get the file back, whether it is a PDF, an image, text or a JWT, or drop a file to Base64 encode it. Everything happens in this tab.
Three bytes are 24 bits. Base64 cuts the same 24 bits into four groups of six, and each group names one of 64 characters. The white lines are where the bytes end: they do not line up with the groups, and that is the whole trick.
16 + 2 + 1 = 19 T
Index 19 in the standard alphabet.
How to use the Base64 decoder and encoder
This Base64 converter works both ways: paste anything into the one field (text, Base64, a whole data: URI or a JWT), or press Choose a file or drop one onto the card. The tool works out which way round it is, says so in the pill, and keeps the other reading one click away.
Decoding Base64 to text or to a file, you get the type read from the bytes themselves, the size, an image's pixel size, a Preview of an image or a PDF, and a download with the right extension. Encoding one, you get the Base64, a ready data: URI and what the encoding cost in size. The Alphabet, Padding and Line breaks options under the result change the output.

One field, both waysPaste text, Base64, a data: URI or a JWT. The pill says how it was read; the menu changes it.Choose a fileOr drop one anywhere on the card: it becomes Base64 and a data: URI, without leaving the tab.What the bytes areDecoding, the result opens with the file's type, size and signature, then a preview and a download.Output optionsStandard or URL-safe alphabet, padding on or off, and lines wrapped for MIME or PEM.3 bytes → 4 charactersYour own bytes, re-cut into groups of six. Point at a character to see its bits add up.What is Base64, and why does it exist?
Base64 writes any bytes using 64 characters that survive anywhere: A–Z, a–z, 0–9, + and /. It exists because email, URLs, JSON and XML were built for text, and a raw byte can be a control code, a quote mark or a null that breaks them.
It takes three bytes at a time, lays their 24 bits in a row and cuts the row into four groups of six. Six bits hold 64 values, so each group names exactly one character. Three bytes in, four characters out, every time: that is why Base64 is about a third bigger than what went in.
Three bytes are 24 bits. Base64 re-cuts them into four groups of six, and each group names one of 64 printable characters, so three bytes always cost four characters. That is where the 33% growth comes from.
Two bytes are 16 bits. Base64 adds 2 zero bits to finish the third group, and one = stands where the fourth character would be.
One byte is 8 bits. Base64 adds 4 zero bits to finish the second group, and two = stand where the third and fourth characters would be. = carries no bits at all.
How do I decode Base64 to a PDF?
Paste the string and the tool rebuilds the PDF: it shows the version and the size, opens the document in your browser's own PDF viewer and gives you a download. You don't have to say it is a PDF, and you don't have to remove a data: prefix first.
A PDF is recognised by its first five bytes, %PDF-, so the file is identified even when its name, the type the sender claimed or the field it came in say otherwise. If the bytes are not a PDF, the page says what they are instead of failing to open a document that was never there.
The file is rebuilt in your browser. Nothing is uploaded, which matters when the PDF is a payslip, a contract or an invoice.
"document": "JVBERi0xLjcKJeLjz9MKMS…"A field in a response. The quotes are not part of the Base64.Content-Transfer-Encoding: base64MIME wraps the body at 76 characters a line. Paste it with the line breaks: they are skipped.data:application/pdf;base64,JVBERi0x…Paste the whole thing. The prefix is read, not stripped by hand.- 25%
- 50P
- 44D
- 46F
- 2D-
- 311
- 2E.
- 377
The first 5 bytes, %PDF-, are the whole signature. Bytes 6 to 8 are the version: 1.7. No file extension is involved, so a PDF someone named .txt still comes back as a PDF.
How do I convert an image to Base64, and when should I?
Drop the image and you get its Base64 and a ready data: URI to paste into HTML or CSS. Whether you should is the harder question: Base64 always costs about a third more, and an inline image can't be cached on its own.
Going the other way, Base64 to image, you get the format, the size and the real pixel size read from the file's own header, not from the picture on screen, and a download with the right extension.
- The file on disk12.9 kB 100%
- As Base6417.3 kB +33.4%
- Wrapped at 76 characters for MIME17.5 kB +35.1%
- The file, gzipped11.7 kB -9.5%
- The Base64, gzipped12.5 kB -3.2%
- downloaded once
- cached by the browser and the CDN
- fetched beside the page, not inside it
- a third bigger before compression
- cached only as part of the file that holds it
- parsed as part of the stylesheet or the HTML
Compression wins most of it back: gzipped, the Base64 is only 7% bigger than the gzipped file. What it cannot give back is the image's own cache entry: inlined in an HTML page, it is downloaded again with every page that carries it.
The rule of thumb: inline a few hundred bytes (an icon, a spacer, a logo in an email) and link anything bigger. This 12.9 kB PNG image is already past the line.
Base64 vs URL-safe Base64: what is the difference?
URL-safe Base64 (RFC 4648 §5) is the same encoding with two characters swapped: + becomes - and / becomes _. The padding is often left off as well.
Use it wherever the result goes into a URL, a file name or a cookie. JSON Web Tokens use it throughout, which is why the parts of a token never end in =. This tool reads both alphabets and tells you when one string carries both.
+/8=-_8=-_8+→-Index 62. In a query string, a form decoder reads+as a space, so the data comes back wrong./→_Index 63. In a path,/starts a new segment, so the value is split in two.=droppedIn a URL,=is usually percent-encoded as%3D(RFC 4648 §5). A JWT drops it altogether (RFC 7515 §2): the length alone says where the bytes end.
The first 62 characters of the two alphabets are identical, which is why a tool that reads both alphabets can decode either, and why this page tells you when a string carries both.
Is Base64 encryption? No.
Base64 hides nothing. There is no key and no secret, and reversing it takes no effort at all: a decoder like this one does it as you type.
HTTP Basic authentication is where this matters most: the header carries the user name and password as one Base64 string, readable by anyone who sees it, which is why RFC 7617 counts the scheme as secure only over an encrypted connection such as TLS. If something must stay unreadable, it needs encryption. Base64 only gets bytes safely through a channel built for text.
An Authorization header, as RFC 7617 §2 builds it
Authorization: Basic dXNlcjpwYXNzd29yZA==user:passwordRFC 7617 builds the header step by step, and the last step is the whole of its “protection”: the client “obtains the basic-credentials by encoding this octet sequence using Base64”. Its §1 says what that means: unless TLS or a similar system protects the connection, “the user-id and password are passed over the network as cleartext”. Base64 has no key, so there is nothing to break: anyone who has the string has the password.
Why does my decoded text look like mojibake?
Because Base64 carries bytes, and bytes only become letters once something picks a character encoding. Read UTF-8 text as if it were ISO-8859-1 and é turns into é; read ISO-8859-1 as UTF-8 and it becomes a replacement mark.
A data: URI can declare its charset, and this page reads the text in that charset instead of forcing everything through UTF-8. When your browser has no decoder for the declared one, the page says so rather than quietly showing you the wrong letters.
In UTF-8, é is 2 bytes; in ISO-8859-1 it is 1 byte. Base64 carries bytes, not letters, so the string itself cannot tell a decoder which was meant.
Base64 in Python, JavaScript, Java, C#, Go, PowerShell and the shell
Every language has Base64 built in. The traps are the same everywhere: encode bytes, not a string, and say which character encoding the text is in.
JavaScript's btoa() is the sharpest edge: it only takes characters up to U+00FF, so anything beyond Latin-1 has to become UTF-8 bytes with TextEncoder first. Each example below encodes and decodes “Man” and was run to check its output.
import base64 b64 = base64.b64encode("Man".encode("utf-8")).decode("ascii") print(b64) # TWFu print(base64.b64decode(b64).decode("utf-8")) # Man
Run with Python 3.14.4 on October 26, 2026: it prints what the comments show.
const bytes = new TextEncoder().encode("Man"); const b64 = btoa(String.fromCharCode(...bytes)); console.log(b64); // TWFu const back = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0)); console.log(new TextDecoder().decode(back)); // Man
Run with Node.js 22.23.2 on October 26, 2026: it prints what the comments show.
import java.util.Base64;
import static java.nio.charset.StandardCharsets.UTF_8;
public class Main {
public static void main(String[] args) {
String b64 = Base64.getEncoder().encodeToString("Man".getBytes(UTF_8));
System.out.println(b64); // TWFu
byte[] back = Base64.getDecoder().decode(b64);
System.out.println(new String(back, UTF_8)); // Man
}
}Run with OpenJDK 25.0.2 on October 26, 2026: it prints what the comments show.
using System.Text; var b64 = Convert.ToBase64String(Encoding.UTF8.GetBytes("Man")); Console.WriteLine(b64); // TWFu var back = Convert.FromBase64String(b64); Console.WriteLine(Encoding.UTF8.GetString(back)); // Man
Run with .NET 10.0.103 on October 26, 2026: it prints what the comments show.
package main import ( "encoding/base64" "fmt" ) func main() { b64 := base64.StdEncoding.EncodeToString([]byte("Man")) fmt.Println(b64) // TWFu back, _ := base64.StdEncoding.DecodeString(b64) fmt.Println(string(back)) // Man }
Run with Go 1.25.5 on October 26, 2026: it prints what the comments show.
$b64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes('Man')) $b64 # TWFu [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($b64)) # Man
Run with PowerShell 7.5.5 on October 26, 2026: it prints what the comments show.
printf 'Man' | base64 # TWFu printf 'TWFu' | base64 -d # Man echo 'Man' | base64 # TWFuCg== (echo adds a newline)
Run with the base64 command of macOS 26.6 (bash) on October 26, 2026: it prints what the comments show.
base64 -d is -D on older macOS. Source: gnu.org, developer.mozilla.orgThe Base64 alphabet, 0 to 63
Each group of six bits is a number from 0 to 63, and this is the table it is looked up in. Base64 is case-sensitive: A is 0 and a is 26, so changing a letter's case breaks the string.
It is worth knowing by sight: a run of As is a run of zero bytes, and a Base64 string that starts with JVBER is a PDF, iVBOR a PNG and /9j/ a JPEG.
- A0
- B1
- C2
- D3
- E4
- F5
- G6
- H7
- I8
- J9
- K10
- L11
- M12
- N13
- O14
- P15
- Q16
- R17
- S18
- T19
- U20
- V21
- W22
- X23
- Y24
- Z25
- a26
- b27
- c28
- d29
- e30
- f31
- g32
- h33
- i34
- j35
- k36
- l37
- m38
- n39
- o40
- p41
- q42
- r43
- s44
- t45
- u46
- v47
- w48
- x49
- y50
- z51
- 052
- 153
- 254
- 355
- 456
- 557
- 658
- 759
- 860
- 961
- +URL-safe: -62
- /URL-safe: _63
0–25 are A–Z, 26–51 are a–z, 52–61 are 0–9. Only the table's last two characters differ between the two alphabets, marked above. = is not in the table at all: it is not a value, it is the mark that says the last group of three bytes was short.
Base64: questions and answers
What is a Base64 decode?
How do I decode a Base64 file?
What is Base64 used for?
data: URIs in HTML and CSS, binary fields in JSON and XML, JSON Web Tokens, HTTP Basic authentication, and certificates and keys in PEM files. In each case the data has to pass through a channel that might change or drop raw bytes, so it travels as plain letters and digits.Is Base64 encryption?
Is it safe to decode Base64 online?
Why is Base64 33% bigger than the original?
= padding characters can be added at the end, and wrapping lines at 76 characters for email adds a line break to every line, so a long string is often about 35% bigger than the bytes it carries. Compression such as gzip wins most of that back.What is URL-safe Base64?
+ replaced by - and / replaced by _, as RFC 4648 §5 defines it, so the result can go into a URL, a file name or a cookie without being escaped. The padding is usually dropped too, as in JSON Web Tokens. This tool reads both alphabets, even mixed in one string, and can write either one.Why does my Base64 decode fail?
Can I convert Base64 to an image?
data:image/png;base64,, and the image appears with its format, its size and its real pixel size, read from the file's own header. Then download it with the right extension. PNG, JPEG, GIF, WebP, BMP, ICO and AVIF are previewed; an SVG is shown as text first, because an SVG can carry script.What does the = at the end of Base64 mean?
=, and one leftover byte becomes two characters and ==. The padding carries no data at all: it only tells a decoder where the bytes end. Many decoders, this one included, also read Base64 whose padding was left off.Is there a size limit?
Can I decode a JWT here?
iat and exp claims and the signature shown as bytes. This page only decodes the three base64url parts: it does not verify the signature and never says a token is valid, so don't use it to decide whether to trust one.Missing something?Suggest a feature or a new tool
Related tools
Htpasswd Generator
Create .htpasswd users with bcrypt, APR1 or SHA-512, check a password against a line, and get the config for Apache, nginx, Caddy and more; hashed in your browser
Binary Translator
Translate text to binary and binary to text: auto-detect, hex, decimal and octal
UUID Generator
Generate UUID v4, v7, v1, v5 and v3 or GUIDs in bulk, in any format, and decode a UUID's version and timestamp
CSR & Certificate Decoder
Decode a CSR or SSL certificate: subject, SANs, key size, validity, issuer, fingerprint, signature check and CSR-to-certificate match
Invisible Character
Copy and paste an invisible character or blank space, and find or remove hidden characters in text