Command line Base64 is the fastest way to inspect a token, prepare an authentication header, or turn a small file into a text blob for a configuration system. It is also where portability problems bite hardest, because the tool named base64 behaves differently depending on which operating system shipped it.
The differences are small but consequential: flag names, line wrapping, and how trailing newlines are handled. A script that works perfectly on a developer laptop can produce subtly invalid output on a build server. This guide covers the common invocations and the traps behind them.
Base64 encode command line tools on Linux
On most Linux distributions, base64 comes from GNU coreutils. Encoding a file is base64 input.bin, and to decode Base64 Linux users pass the long flag --decode or its short form -d. Both read standard input when no file is given, so they compose naturally with pipes.
By default GNU base64 wraps output at seventy-six characters. That is correct for email but wrong for a header value or a JSON field, so disable it with -w 0. Forgetting this flag is the most frequent cause of a token that looks right in a terminal but is rejected by an API.
The macOS and BSD differences
The BSD base64 that ships with macOS does not understand -w, and older releases used -D rather than -d for decoding. Scripts that hardcode GNU flags therefore fail on macOS with an unhelpful usage message.
For portable scripts, avoid the differences entirely by piping through tr -d '\n' to strip line breaks instead of relying on a wrapping flag. Alternatively, use openssl base64, which is present on both platforms and takes -A for single-line output and -d for decoding.
The trailing newline trap
Shell tools add a trailing newline where humans expect one, and Base64 encodes every byte it receives, including that newline. This is why echo "secret" | base64 and the encoding of the literal six characters produce different results.
Use printf '%s' or echo -n to suppress the newline when encoding a string that must match a value produced elsewhere. This matters most for HTTP basic authentication, where a stray newline inside the encoded user:password pair produces a header that fails authentication for no visible reason.
Working with files and binary data
Encoding a file is straightforward because the tool reads bytes without interpreting them: base64 -w 0 certificate.der > certificate.txt. Any Base64 decode CLI writes bytes back, so always redirect to a file rather than to the terminal, since a binary stream can leave a terminal in a broken state.
A common pipeline is decoding and decompressing in one pass, such as base64 -d payload.txt | gunzip > payload.json. When a payload arrives from a log or an API and its type is unknown, decode it to a file and run file on the result to identify it before guessing.
PowerShell and Windows
Windows has no base64 command, and PowerShell exposes the operation through .NET instead. Encoding uses [Convert]::ToBase64String() over a byte array, and decoding uses [Convert]::FromBase64String(), which returns bytes that you then write to a file or convert to a string.
Because you supply the byte array yourself, the character set is explicit rather than implied. Use [Text.Encoding]::UTF8.GetBytes() for text, not the default encoding, since PowerShell's historical defaults differ between Windows PowerShell and PowerShell Core and will produce different output for non-ASCII input.
Base64 in shell scripts
The reliable pattern is to be explicit about every variable: suppress trailing newlines, disable wrapping, and state the character set. Encode with printf '%s' "$value" | base64 | tr -d '\n', which behaves identically on GNU and BSD systems without any flags that differ between them.
Remember that command line arguments and environment variables are visible to other processes and are often captured by shell history. Encoding a secret does not conceal it, so pass sensitive values through files with restrictive permissions or through standard input rather than embedding them in a command.
Command reference across shells
The table collects the invocations people reach for most, including the differences that make a Base64 decode command linux users rely on fail elsewhere.
| Task | Command |
|---|---|
| Base64 encode a file, Linux | base64 -w 0 input.bin > out.txt |
| Base64 encode file, portable | openssl base64 -A -in input.bin |
| Base64 encode a string without a newline | printf '%s' "$v" | base64 -w 0 |
| Decode base64 bash, from a variable | printf '%s' "$b64" | base64 -d |
| Decode base64 command line, to a file | base64 -d in.txt > out.bin |
| Base64 decode bash command, macOS | base64 -D in.txt |
| Base64 encode command line windows | certutil -encode in.bin out.txt |
| Decode base64 PowerShell | [Convert]::FromBase64String($b64) |
| Base64 decode binary file, identify it | base64 -d in.txt > out && file out |
Running Base64 encode Linux side is the common case, and a Base64 encode a file Linux command is the first row above. A decode Base64 CLI invocation is the same binary with -d, and a decode Base64 command linux users type most often is simply base64 -d reading from a pipe. To decode Base64 code pasted from a log, quote it carefully so the shell does not eat the padding.
The wrapping flag is the main portability trap: -w 0 is GNU-only, so a Base64 encode command linux script fails on macOS, where openssl base64 -A or a pipe through tr -d '\n' works on both. Decoding an ASCII payload needs no special handling, but a Base64 decode ASCII assumption applied to binary will corrupt output the moment the data is not text.
Decoding untrusted input
Strings pulled from logs, headers, or third-party APIs frequently fail to decode on the first attempt. Check three things before concluding the data is corrupt: whether the string uses the URL-safe alphabet with - and _ instead of + and /, whether padding was stripped, and whether a copy step introduced spaces or quotation marks.
Restore the standard alphabet with tr '_-' '/+' before decoding, and re-add padding by appending = until the length is a multiple of four. GNU base64 also accepts -i to ignore characters outside the alphabet, which is convenient interactively but a poor default in scripts because it hides genuine truncation.
Verifying a round trip
Whenever a Base64 step sits inside an automated pipeline, add a round trip check. Encode the input, decode it back, and compare against the original with cmp or a checksum. This catches newline contamination, wrapping, and character set mistakes at the point where they are introduced.
Check exit codes rather than output alone, because a decoder that fails partway can still write a truncated file and return a status your script never inspects. In a pipeline, enable set -o pipefail so a failure in the middle of a chain is not masked by a successful final command.
For interactive debugging, a browser-based encoder and decoder is often clearer than a terminal because it displays the exact string without shell quoting getting in the way. Use it to confirm what a value should be, then reproduce that result on the command line.
Further reading: RFC 4648 defines the Base64 and Base64URL alphabets and their padding rules, and MDN’s Base64 glossary entry covers the browser APIs.