Base64 encoding in PowerShell: encode and decode files and strings

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
Note: These .NET classes are available in Windows PowerShell 5.1 and PowerShell 7+. No modules need to be imported. All examples in this article run on Windows 10 and 11 without elevation.

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
Note: Always specify the encoding explicitly. [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
Result: The output is the original plain text string. If the decoded output looks garbled, the encoding used during encoding was not UTF-8 — try [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"
Note: Use -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"
Warning: Always use [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
Common mistake: Using UTF-8 encoding instead of UTF-16LE for -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"
}
Result: If both hashes match, the encode-decode round trip preserved the file exactly. This is more reliable than a text comparison because it works correctly with binary files.

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.

Common mistake: Writing Base64 output with 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
Note: Use PowerShell when the encoded output must be consumed by an API, a Linux tool, or any system that expects clean RFC 4648 Base64. Use certutil when working entirely within Windows CMD and both encode and decode will be done with certutil. For the full certutil workflow, see certutil -encode and -decode: Base64 encoding files from the Windows command line.

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 executionpowershell.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-File default 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

Related Guides