Bytes in, characters out
A file is a sequence of bytes, and Base64 maps every 3 of them onto 4 printable ASCII characters. That is the whole trick: a PDF, a font or a ZIP archive becomes a string that survives channels built for text, JSON fields, XML documents, email bodies, environment variables. The output of this page for a given file is byte-for-byte identical to what base64 file.pdf prints on Linux or macOS.
The critical word is bytes. The corruption stories behind "my Base64 file is broken" almost always start with a binary file being read as text: an editor substitutes characters it cannot display, a charset conversion rewrites everything past ASCII, and the damage is invisible until decoding produces a file that no longer opens. This converter reads the dropped file with a raw byte read, so what goes into the encoder is exactly what was on disk.
How to use this converter
- Drop a file on the left pane (or pick one via the file link). Any type works, because the encoder never interprets the content. The pane shows a receipt with name, size and detected MIME type.
- Pick the shape you need.
--data-uriprefixes the string withdata:<type>;base64,, using the MIME type of the dropped file.--url-safeswitches to the Base64URL alphabet and strips padding, for tokens and URLs.--wrap-76breaks the output into 76-character lines the way MIME email wants it. - Copy or download. Both always carry the complete string, no matter how large.
That last point is deliberate. A 20 MB file produces a 27 MB string, and a page that pours 27 million characters into the DOM freezes the tab, which is how most online converters die. Here the output pane shows the first stretch of the string plus a count of what is omitted, while copy and download work on the full string in memory. You can also just paste plain text into the left pane; it is encoded as UTF-8, the same as our text-first Base64 encoder would do.
Where the string ends up
- JSON API payloads: attachments in email APIs, images in ML inference requests, documents in webhook bodies. Base64 is the standard answer to "JSON has no binary type".
- Data URIs: a file inlined into HTML or CSS. For images specifically, the image to Base64 page also builds the CSS rule and the
<img>tag for you. - Config files and env vars: a keystore, certificate or binary blob that has to live in YAML, TOML or a CI secret. Kubernetes Secrets work exactly this way.
- Email attachments: every attachment in a MIME message is wrapped Base64, which is what
--wrap-76reproduces. - Test fixtures: a small binary checked into a test as a string, so the repository stays free of opaque files.
Encoding a file in code
| Environment | File to Base64 |
|---|---|
| Shell (Linux/macOS) | base64 -w0 file.pdf (GNU; BSD prints unwrapped by default) |
| Node.js | fs.readFileSync('file.pdf').toString('base64') |
| Browser | new Uint8Array(await file.arrayBuffer()), then bytes.toBase64() where available, else btoa over the byte string |
| Python | base64.b64encode(open('file.pdf','rb').read()).decode() |
| PowerShell | [Convert]::ToBase64String([IO.File]::ReadAllBytes('file.pdf')) |
Two details bite in practice. GNU base64 wraps output at 76 columns unless you pass -w0, and an API that expects one unbroken line will reject the wrapped version with an unhelpful parse error. And in Python, forgetting the 'rb' flag makes open() decode the file as text first, which crashes on most binary files and silently mangles the rest.
Size, memory and limits
Base64 output is input × 4/3: a 3 MB image becomes a 4 MB string, plus a fraction more if line wrapping is on. The overhead stat under the tool shows the real number for your file. Because the encoding is deterministic, there is no way around the tax; compressing first (ZIP, gzip) helps only for file types that are not already compressed.
Memory is the quieter constraint. Every step of the pipeline holds the full string: the encoder, the JSON serializer, the HTTP client, the server parsing the body. A file that streams comfortably as multipart chokes services when it travels as one giant string field, and this is the actual reason upload APIs prefer multipart over Base64 in JSON, not the 33%. Base64-in-JSON is great up to a few megabytes and a liability after that.
Files as strings, in practice
How do I Base64 encode a file, for example a PDF?
Read the file as bytes, then encode the bytes, never the text representation. In the browser: const buf = await file.arrayBuffer(); btoa(String.fromCharCode(...new Uint8Array(buf))) for small files, or FileReader.readAsDataURL for a ready-made data URI. In Node.js: fs.readFileSync("doc.pdf").toString("base64"). On the shell: base64 doc.pdf. The classic mistake is opening the file in an editor and copying the contents, which corrupts every byte the editor cannot represent as text. Dropping the file on the pane above does the byte-level read for you.
How do I send a file as Base64 in a JSON API request?
Encode the bytes and put the string in a JSON field, typically next to the filename and MIME type: {"filename":"report.pdf","content_type":"application/pdf","data":"JVBERi0…"}. It works everywhere JSON works, which is why webhook payloads and email APIs (SendGrid, Mailgun, Gmail) all do it. The costs are a 33% bigger request and the whole file held in memory on both ends, so past a few megabytes multipart/form-data is the better transport: it streams and carries raw bytes. Check the API limit either way; many providers cap Base64 attachments around 10 MB decoded.
What is the maximum file size I can convert to Base64?
Base64 itself has no limit; the limits are memory and whatever consumes the string. Practical numbers: a browser tab holds the file plus the one-third-bigger string in RAM at once, so a few hundred megabytes is where in-browser encoding gets uncomfortable. Email providers cap messages around 25 MB, which is roughly 18 MB of attachment once the encoding overhead is paid. JSON APIs commonly reject bodies past 10 MB. If you are bumping into any of these, the answer is usually a real file transfer (multipart, S3 presigned URL), not a bigger string.
Why is my Base64-encoded file corrupted after decoding?
Almost always because the bytes were treated as text somewhere along the way. The usual suspects: the file was opened in an editor and copied (the editor rewrites bytes it cannot display), it was read with a charset conversion (Python open() without "rb", PowerShell Get-Content without -AsByteStream), or the string picked up line breaks and stray whitespace in transit that a strict decoder then rejects or a lenient one silently misreads. Encode from a binary read, transport the string untouched, and compare checksums (sha256sum before and after) when in doubt.
How do I convert a Base64 string back to a file?
Decode to bytes and write them in binary mode. Shell: base64 -d encoded.txt > file.pdf. Python: open("file.pdf","wb").write(base64.b64decode(s)). Node.js: fs.writeFileSync("file.pdf", Buffer.from(s, "base64")). In the browser, build a Blob from the decoded bytes and trigger a download via an object URL. Never paste decoded output into a text editor and save from there; that is the corruption path from the previous question in reverse. Our Base64 decoder does the decode-and-download step and names the file after its magic bytes.
How do I Base64 encode a file in PowerShell or on Windows?
[Convert]::ToBase64String([IO.File]::ReadAllBytes("C:\path\file.pdf")) gives you the clean string. The often-suggested alternative certutil -encode file.pdf out.txt works but wraps the output in -----BEGIN CERTIFICATE----- markers and 64-character lines, both of which have to be stripped before an API accepts the payload (certutil -encodehex -f file.pdf out.txt 0x40000001 emits it bare on newer Windows builds). For the reverse direction, [IO.File]::WriteAllBytes("file.pdf",[Convert]::FromBase64String($s)).
How do I embed a PDF as Base64 in HTML?
Put a data URI into an iframe, embed or object element: <embed src="data:application/pdf;base64,JVBERi0…" type="application/pdf">. It renders in desktop browsers with a built-in PDF viewer, but know the limits before shipping it: the document grows by a third and cannot be cached separately, mobile browsers often refuse inline PDF rendering entirely, and browsers block data: URIs at the top level, so a plain link to the URI will not open. Past a small handful of pages, serving the PDF as a normal file with a download link is the version that works everywhere.
Is it safe to convert a confidential file with an online Base64 tool?
Only if the tool encodes in the browser instead of on its server. A converter that uploads your file has a copy of it, and for a contract, an ID scan or an NDA-covered document that is already a data-handling incident regardless of what the privacy policy says. This page reads the file with JavaScript in your tab, encodes it locally and sends nothing, which you can verify in the Network tab of your devtools or by loading the page and then going offline. And remember the string itself is not protected: Base64 is encoding, not encryption, so the encoded file is exactly as readable as the original.