PowerShell can encode and decode Base64 natively using the [Convert] .NET class — no external utilities, no temporary files with PEM headers. Unlike certutil, PowerShell produces clean RFC 4648 Base64 that is directly compatible with web APIs, Linux systems, and any tool that expects standard Base64 input. This article covers encoding and decoding files and strings from PowerShell, explains how encoding behaves differently depending on whether you are working with text or binary data, and shows how to integrate Base64 into practical admin workflows.
Quick Answer
# Encode a string to Base64
[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes('hello world'))
# Decode a Base64 string
[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('aGVsbG8gd29ybGQ='))
# Encode a file to Base64 and save the result
[Convert]::ToBase64String([IO.File]::ReadAllBytes('C:\bat\app.conf')) | Out-File C:\bat\app_encoded.txt
# Decode a Base64 file back to its original
$b = [Convert]::FromBase64String(([IO.File]::ReadAllText('C:\bat\app_encoded.txt')).Trim())
[IO.File]::WriteAllBytes('C:\bat\app_restored.conf', $b)
What it does
PowerShell does not have a dedicated base64 cmdlet. Base64 operations are handled through two .NET classes that are available in every PowerShell session without any imports:
[Convert]::ToBase64String(byte[])— takes a byte array and returns a Base64 string[Convert]::FromBase64String(string)— takes a Base64 string and returns a byte array[Text.Encoding]::UTF8— converts between strings and byte arrays using UTF-8 encoding[IO.File]::ReadAllBytes(path)— reads a file as raw bytes, preserving binary content exactly
Practical Examples
1. Encode a string to Base64
The problem: You need to encode a plain text string — a connection string, a token value, or a config parameter — to Base64 before passing it to an API or embedding it in a script.
The solution: Convert the string to a UTF-8 byte array first, then encode that byte array to Base64.
# Define the string to encode
$text = 'Server=SRV-PROD-01;Port=8443;User=svcaccount'
# Convert the string to UTF-8 bytes, then encode to Base64
$encoded = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($text))
# Output the result
$encoded
[Text.Encoding]::UTF8 is the standard for cross-platform compatibility. Using [Text.Encoding]::Unicode (UTF-16) produces output that is incompatible with most Linux and web tools.
2. Decode a Base64 string back to plain text
The problem: You received a Base64-encoded value — from an API response, a config file, or a colleague — and need to read the original string.
The solution: Decode the Base64 string to a byte array, then convert those bytes back to a string using the correct encoding.
# The Base64 string to decode
$encoded = 'U2VydmVyPVNSVi1QUk9ELTAxO1BvcnQ9ODQ0MztVc2VyPXN2Y2FjY291bnQ='
# Decode from Base64 to byte array, then convert bytes to UTF-8 string
$decoded = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($encoded))
# Output the original string
$decoded
[Text.Encoding]::Unicode or [Text.Encoding]::ASCII instead.
3. Encode a file to Base64 and save to disk
The problem: You need to encode a file — a config, a certificate, a script — to Base64 and save the result as a text file for transfer or embedding in a payload.
The solution: Read the file as raw bytes using ReadAllBytes, encode to Base64, and write the result to a new file.
# Read the source file as raw bytes and encode to Base64
# ReadAllBytes preserves exact binary content - safe for any file type
$encoded = [Convert]::ToBase64String([IO.File]::ReadAllBytes('C:\bat\app.conf'))
# Write the Base64 string to a text file
# -Encoding ascii prevents PowerShell from adding a BOM that breaks other decoders
$encoded | Out-File -FilePath 'C:\bat\app_encoded.txt' -Encoding ascii
Write-Host "Encoded file saved: C:\bat\app_encoded.txt"
-Encoding ascii with Out-File when writing Base64 output. This prevents PowerShell from adding a UTF-8 BOM or UTF-16 byte order mark to the file, which would break decoding in other tools.
4. Decode a Base64 file back to the original
The problem: You have a Base64-encoded text file and need to restore the original binary or text file from it.
The solution: Read the encoded text, decode it to a byte array, and write those bytes directly to the output file using WriteAllBytes.
# Read the Base64 text from file and trim any trailing whitespace or newlines
# .Trim() is required - Out-File adds a newline that breaks FromBase64String
$encodedText = ([IO.File]::ReadAllText('C:\bat\app_encoded.txt')).Trim()
# Decode the Base64 string to a byte array
$bytes = [Convert]::FromBase64String($encodedText)
# Write the raw bytes to the output file
# WriteAllBytes preserves exact binary content - correct for any file type
[IO.File]::WriteAllBytes('C:\bat\app_restored.conf', $bytes)
Write-Host "File restored: C:\bat\app_restored.conf"
[IO.File]::WriteAllBytes() when writing decoded content, not Out-File or Set-Content. Those cmdlets write text and will corrupt binary files such as images, executables, or ZIP archives.
5. Encode a string for use in a PowerShell -EncodedCommand
The problem: You need to pass a PowerShell command to powershell.exe -EncodedCommand — for example, in a scheduled task, a remote execution payload, or a deployment script — without dealing with quote escaping.
The solution: Encode the command string as UTF-16LE Base64, which is the exact format -EncodedCommand requires.
# The command to encode
$command = 'Get-Service | Where-Object { $_.Status -eq "Running" } | Export-Csv C:\bat\running_services.csv'
# -EncodedCommand requires UTF-16LE (Unicode) encoding, not UTF-8
$bytes = [Text.Encoding]::Unicode.GetBytes($command)
$encoded = [Convert]::ToBase64String($bytes)
# Display the encoded string ready to use with powershell.exe
Write-Host "powershell.exe -EncodedCommand $encoded"
# Run it directly from the current session
powershell.exe -EncodedCommand $encoded
-EncodedCommand will cause PowerShell to silently fail or throw a parsing error. The -EncodedCommand parameter always expects UTF-16LE Base64. This is the one case where you must use [Text.Encoding]::Unicode, not UTF-8.
6. Verify round-trip integrity
The problem: After encoding and decoding a file, you want to confirm that the restored file is byte-for-byte identical to the original.
The solution: Compare the SHA256 hash of both files. Identical hashes confirm the round trip was clean.
# Compute SHA256 hash of the original file
$hashOriginal = (Get-FileHash -Path 'C:\bat\app.conf' -Algorithm SHA256).Hash
# Compute SHA256 hash of the restored file
$hashRestored = (Get-FileHash -Path 'C:\bat\app_restored.conf' -Algorithm SHA256).Hash
# Compare and report
if ($hashOriginal -eq $hashRestored) {
Write-Host "Integrity check passed: files are identical"
} else {
Write-Host "Integrity check FAILED: files differ"
}
Hidden Gems
Out-File silently adds a BOM that breaks decoders
In Windows PowerShell 5.1, Out-File writes UTF-16 with a byte order mark by default. If you write a Base64 string using Out-File without specifying -Encoding ascii, the resulting file will contain invisible extra bytes at the start. Any tool that reads that file and tries to decode the Base64 content — including another PowerShell session, a Python script, or a Linux utility — will fail silently or produce garbage output. Always use -Encoding ascii or use [IO.File]::WriteAllText() instead.
Out-File in Windows PowerShell 5.1 without -Encoding ascii adds a UTF-16 BOM to the file. The Base64 string looks correct when you open it in a text editor, but decoders will fail. PowerShell 7+ uses UTF-8 without BOM by default and does not have this problem.
Trim() is required when reading encoded files back
When you write a Base64 string to a file with Out-File, PowerShell appends a newline character at the end. When you read that file back and pass the string directly to [Convert]::FromBase64String(), the trailing newline causes a format exception. Always call .Trim() on the string before decoding. This applies to content read with Get-Content, ReadAllText(), or any other method.
Get-Content breaks binary files — always use ReadAllBytes
Get-Content reads files as text and applies line-ending normalization. For text files this is usually harmless, but for binary files — images, executables, ZIP archives, certificates — it will silently corrupt the data. Use [IO.File]::ReadAllBytes() for encoding and [IO.File]::WriteAllBytes() for decoding whenever file type is not guaranteed to be plain text.
Cross-shell equivalent
For CMD environments where PowerShell is not available or not preferred, certutil provides encode and decode operations. The key difference: certutil wraps the output in PEM headers (-----BEGIN CERTIFICATE----- / -----END CERTIFICATE-----) that make the result incompatible with standard Base64 consumers.
rem CMD equivalent using certutil
certutil -encode C:\bat\app.conf C:\bat\app_encoded.txt
certutil -decode C:\bat\app_encoded.txt C:\bat\app_restored.conf
Where this matters
Passing secrets to APIs and deployment tools — many CI/CD pipelines, REST APIs, and configuration management tools accept secrets and certificates as Base64 strings. PowerShell is the correct tool for this because the output is clean and RFC 4648 compliant without post-processing.
Encoding commands for scheduled tasks and remote execution — powershell.exe -EncodedCommand is a standard pattern for passing complex scripts through interfaces that do not handle special characters well. Encoding the command in PowerShell before registering the scheduled task avoids quote escaping entirely.
Embedding file content in JSON or YAML payloads — Ansible, Terraform, and similar tools sometimes require file content to be embedded directly in a payload as a Base64 string. PowerShell’s output drops in without modification.
Decoding certificate and key material — certificate stores, key vaults, and deployment scripts frequently deliver certificate content as Base64. Being able to decode and write the bytes directly to a .pfx or .cer file from PowerShell removes the need for OpenSSL or GUI tools.
Cross-platform script distribution — when a script needs to be transferred from Windows to a Linux system or passed through a tool that handles only ASCII, encoding it as Base64 in PowerShell produces output that Linux’s base64 -d can decode directly.
Tips and Limitations
- Encoding version matters: Windows PowerShell 5.1 and PowerShell 7+ behave differently with
Out-Filedefault encoding. PowerShell 7+ is safer for cross-platform work. When in doubt, use[IO.File]methods instead of cmdlets — they behave consistently across both versions. - Large files:
ReadAllBytes()loads the entire file into memory before encoding. For files larger than a few hundred MB, memory pressure can become a problem. Consider chunked encoding or an external tool for very large files. - Line length:
[Convert]::ToBase64String()produces a single unbroken line. Some systems expect Base64 with line breaks every 76 characters (MIME format). If a downstream system rejects the output, use[Convert]::ToBase64String($bytes, [Base64FormattingOptions]::InsertLineBreaks). - No streaming: Like certutil, PowerShell Base64 encoding requires the full input to be read into memory first. Piping large command output requires a temp file as intermediate storage.
Related Tool
Need to encode or decode a Base64 string directly in the browser without the command line? Use the Base64 Encoder / Decoder — no installation, no data sent to the server.
Official Reference
[Convert]::ToBase64String — .NET API | Microsoft Learn
