Base64 Encoding & Decoding in Swift
Swift's Foundation framework provides Base64 support through the Data type. Data.base64EncodedString() and Data(base64Encoded:) cover the majority of use cases with minimal code.
Basic String Encoding
import Foundation
// Encode string to Base64
let original = "Hello, world!"
if let data = original.data(using: .utf8) {
let encoded = data.base64EncodedString()
print(encoded) // "SGVsbG8sIHdvcmxkIQ=="
}
// Decode Base64 to string
let encoded = "SGVsbG8sIHdvcmxkIQ=="
if let data = Data(base64Encoded: encoded),
let decoded = String(data: data, encoding: .utf8) {
print(decoded) // "Hello, world!"
}
Encoding Options
import Foundation
let data = "Hello, world!".data(using: .utf8)!
// Default: no line breaks
let compact = data.base64EncodedString()
// With line breaks every 64 characters (for MIME/PEM)
let formatted = data.base64EncodedString(
options: .lineLength64Characters
)
// With line breaks every 76 characters
let mime = data.base64EncodedString(
options: .lineLength76Characters
)
URL-Safe Base64
Foundation doesn't have a built-in URL-safe encoder, but it's easy to add:
import Foundation
extension Data {
func base64URLEncodedString() -> String {
return base64EncodedString()
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.trimmingCharacters(in: CharacterSet(charactersIn: "="))
}
}
extension String {
static func fromBase64URL(_ base64url: String) -> String? {
var base64 = base64url
.replacingOccurrences(of: "-", with: "+")
.replacingOccurrences(of: "_", with: "/")
// Restore padding
let remainder = base64.count % 4
if remainder > 0 {
base64 += String(repeating: "=", count: 4 - remainder)
}
guard let data = Data(base64Encoded: base64) else { return nil }
return String(data: data, encoding: .utf8)
}
}
// Usage
let encoded = "Hello 🌍".data(using: .utf8)!.base64URLEncodedString()
let decoded = String.fromBase64URL(encoded)
Encoding Images (UIImage / NSImage)
import Foundation
#if canImport(UIKit)
import UIKit
func imageToBase64(_ image: UIImage) -> String? {
guard let data = image.pngData() else { return nil }
return data.base64EncodedString()
}
func imageToDataURI(_ image: UIImage) -> String? {
guard let data = image.pngData() else { return nil }
return "data:image/png;base64," + data.base64EncodedString()
}
func base64ToImage(_ base64: String) -> UIImage? {
guard let data = Data(base64Encoded: base64) else { return nil }
return UIImage(data: data)
}
#endif
Encoding Files
import Foundation
// Encode file at URL to Base64
func encodeFile(at url: URL) throws -> String {
let data = try Data(contentsOf: url)
return data.base64EncodedString()
}
// Decode Base64 and write to file
func decodeToFile(_ base64: String, outputURL: URL) throws {
guard let data = Data(base64Encoded: base64) else {
throw NSError(domain: "Base64Error", code: 1,
userInfo: [NSLocalizedDescriptionKey: "Invalid Base64"])
}
try data.write(to: outputURL)
}
// Example
let fileURL = Bundle.main.url(forResource: "document", withExtension: "pdf")!
let encoded = try? encodeFile(at: fileURL)
Handling Malformed Input
import Foundation
func safeBase64Decode(_ input: String) -> Data? {
// Remove whitespace that may have been added
let cleaned = input.components(separatedBy: .whitespacesAndNewlines).joined()
// Restore padding if stripped
var padded = cleaned
let remainder = padded.count % 4
if remainder > 0 {
padded += String(repeating: "=", count: 4 - remainder)
}
return Data(base64Encoded: padded)
}
Verify your Swift Base64 output
Paste the encoded string from your Swift app into base64.dev to decode and inspect it.
Open base64.dev →