Go Base64
Last modified: July 16, 2026
This Go Base64 tutorial shows how to encode and decode binary data to and from
Base64 in Go using the encoding/base64 package. We cover standard
encoding, URL-safe encoding, raw encodings, stream encoding, and image encoding.
Base64
Base64 is a binary-to-text encoding scheme that represents binary data in an ASCII string format by translating it into a radix-64 representation. It is defined in RFC 4648. Each Base64 digit represents exactly six bits of data, so three bytes (24 bits) can be represented using four Base64 characters.
Base64 encoding schemes are commonly used when we need to store and transfer binary data over media that are designed to deal with text. Common use cases include embedding images in HTML and CSS files, encoding email attachments via MIME, storing binary data in JSON or XML, and transmitting credentials in HTTP headers (Basic authentication).
In Go, we use the encoding/base64 package for Base64 encoding and
decoding. It implements the base encoding specified by RFC 4648.
The following is the Base64 alphabet as defined by RFC 4648. Each character represents a six-bit value, ranging from 0 to 63.
Value Encoding Value Encoding Value Encoding Value Encoding 0 A 17 R 34 i 51 z 1 B 18 S 35 j 52 0 2 C 19 T 36 k 53 1 3 D 20 U 37 l 54 2 4 E 21 V 38 m 55 3 5 F 22 W 39 n 56 4 6 G 23 X 40 o 57 5 7 H 24 Y 41 p 58 6 8 I 25 Z 42 q 59 7 9 J 26 a 43 r 60 8 10 K 27 b 44 s 61 9 11 L 28 c 45 t 62 + 12 M 29 d 46 u 63 / 13 N 30 e 47 v 14 O 31 f 48 w (pad) = 15 P 32 g 49 x 16 Q 33 h 50 y
Go's encoding/base64 package provides four encoding variants
to accommodate different use cases. The table below summarises each variant's
characteristics.
| Encoding | Description |
|---|---|
base64.StdEncoding |
Standard Base64 encoding with padding (=). |
base64.URLEncoding |
URL-safe encoding. Replaces + and / with - and _. Includes padding. |
base64.RawStdEncoding |
Standard encoding without padding. |
base64.RawURLEncoding |
URL-safe encoding without padding. |
The StdEncoding and URLEncoding variants append
padding characters (=) to make the output length a multiple of
four. The RawStdEncoding and RawURLEncoding variants
omit padding, which is acceptable when the length is known or padding is
unnecessary.
Encode with StdEncoding
The base64.StdEncoding.Encode function encodes a source slice of
bytes into a destination slice of bytes using the standard Base64 alphabet.
func (*base64.Encoding).Encode(dst []byte, src []byte)
The destination is the first parameter, the source is the second.
package main
import (
"encoding/base64"
"fmt"
)
func main() {
msg := "one 🐘 and three 🐋"
fmt.Println(msg)
data := make([]byte, base64.StdEncoding.EncodedLen(len(msg)))
base64.StdEncoding.Encode(data, []byte(msg))
fmt.Println(data)
encoded := string(data)
fmt.Println(encoded)
}
The program encodes a string containing emoji characters to Base64.
msg := "one 🐘 and three 🐋"
We have a string with two emojis.
data := make([]byte, base64.StdEncoding.EncodedLen(len(msg)))
The EncodedLen function returns the length in bytes of the
Base64 encoding of an input buffer, so we can pre-allocate the destination
slice.
base64.StdEncoding.Encode(data, []byte(msg))
We encode the data with base64.StdEncoding.Encode. The encoded
bytes are written to the pre-allocated data slice.
$ go run main.go one 🐘 and three 🐋 [98 50 53 108 73 80 67 102 107 74 103 103 89 87 53 ... 115 61] b25lIPCfkJggYW5kIHRocmVlIPCfkIs=
Decode with StdEncoding
The base64.StdEncoding.Decode function decodes a Base64-encoded
source slice of bytes into a destination slice of bytes.
package main
import (
"encoding/base64"
"fmt"
"log"
)
func main() {
encoded := "b25lIPCfkJggYW5kIHRocmVlIPCfkIs="
fmt.Println(encoded)
data := make([]byte, base64.StdEncoding.DecodedLen(len(encoded)))
n, err := base64.StdEncoding.Decode(data, []byte(encoded))
fmt.Println(data)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data[:n]))
}
The program decodes a Base64-encoded string back to its original form.
encoded := "b25lIPCfkJggYW5kIHRocmVlIPCfkIs="
This is the Base64-encoded string from the previous example.
data := make([]byte, base64.StdEncoding.DecodedLen(len(encoded)))
We pre-allocate a destination buffer using DecodedLen, which
returns the maximum decoded length.
n, err := base64.StdEncoding.Decode(data, []byte(encoded))
The data is decoded. The function returns the number of bytes written and any decoding error.
$ go run main.go b25lIPCfkJggYW5kIHRocmVlIPCfkIs= [111 110 101 32 240 159 144 152 32 97 110 100 ... 240 159 144 139 0] one 🐘 and three 🐋
Encode and decode strings
The EncodeToString and DecodeString convenience
functions handle Base64 encoding and decoding directly with string types.
package main
import (
"encoding/base64"
"fmt"
"log"
)
func main() {
msg := "one 🐘 and three 🐋"
fmt.Println(msg)
str := base64.StdEncoding.EncodeToString([]byte(msg))
fmt.Println(str)
data, err := base64.StdEncoding.DecodeString(str)
if err != nil {
log.Fatal(err)
}
fmt.Println(data)
fmt.Println(string(data))
}
The program encodes a string to Base64 and decodes it back using the convenience functions.
$ go run main.go one 🐘 and three 🐋 b25lIPCfkJggYW5kIHRocmVlIPCfkIs= [111 110 101 32 240 159 144 152 32 ... 32 240 159 144 139] one 🐘 and three 🐋
URL-safe encoding
The standard Base64 alphabet includes + and /
characters, which have special meaning in URL path segments and query strings.
The URL-safe encoding replaces these with - and _
respectively.
package main
import (
"encoding/base64"
"fmt"
)
func main() {
msg := "<<Hello>>"
std := base64.StdEncoding.EncodeToString([]byte(msg))
fmt.Println("StdEncoding:", std)
url := base64.URLEncoding.EncodeToString([]byte(msg))
fmt.Println("URLEncoding:", url)
data, _ := base64.URLEncoding.DecodeString(url)
fmt.Println("Decoded:", string(data))
}
We encode the string <<Hello>> with both
standard and URL-safe encoders. The < and >
characters produce bytes that map to + and / in
standard Base64, which are replaced with - and _ in
URL-safe encoding.
$ go run main.go StdEncoding: PDxIZWxsbz4+ URLEncoding: PDxIZWxsbz4- Decoded: <<Hello>>
The standard encoding produces PDxIZWxsbz4+, which contains a
+ — a / would appear with different input. The
URL-safe encoding produces PDxIZWxsbz4-, replacing +
with -. Both decode correctly to the original string.
Raw encoding without padding
The RawStdEncoding and RawURLEncoding variants omit
the trailing padding characters (=). This is useful when the
encoded data length is known or padding is not required.
package main
import (
"encoding/base64"
"fmt"
)
func main() {
msg := "Hello there!"
std := base64.StdEncoding.EncodeToString([]byte(msg))
raw := base64.RawStdEncoding.EncodeToString([]byte(msg))
fmt.Println("StdEncoding:", std)
fmt.Println("RawStdEncoding:", raw)
}
We compare the output of StdEncoding (with padding) and
RawStdEncoding (without padding).
$ go run main.go StdEncoding: SGVsbG8gdGhlcmUh RawStdEncoding: SGVsbG8gdGhlcmUh
The RawStdEncoding output omits the == padding suffix.
Both variants decode to the same original data.
Stream encoding
The base64.NewEncoder function creates a write stream that encodes
data on the fly. This is efficient for large data sets that should not be held
entirely in memory.
package main
import (
"bytes"
"encoding/base64"
"fmt"
"io"
)
func main() {
msg := []byte("one 🐘 and three 🐋")
var buf bytes.Buffer
encoder := base64.NewEncoder(base64.StdEncoding, &buf)
encoder.Write(msg)
encoder.Close()
fmt.Println(buf.String())
decoder := base64.NewDecoder(base64.StdEncoding, &buf)
decoded, _ := io.ReadAll(decoder)
fmt.Println(string(decoded))
}
The example uses NewEncoder and NewDecoder to encode
and decode data through streaming I/O.
encoder := base64.NewEncoder(base64.StdEncoding, &buf)
NewEncoder wraps a writer and returns an io.WriteCloser
that encodes any data written to it.
decoder := base64.NewDecoder(base64.StdEncoding, &buf)
NewDecoder wraps a reader and returns an io.Reader
that decodes data as it is read.
$ go run main.go b25lIPCfkJggYW5kIHRocmVlIPCfkIs= one 🐘 and three 🐋
Encoding images
A common practical use of Base64 is embedding binary image data directly into HTML or CSS files. The following example reads an image file and encodes it.
package main
import (
"encoding/base64"
"fmt"
"os"
)
func main() {
data, err := os.ReadFile("image.png")
if err != nil {
fmt.Println(err)
return
}
encoded := base64.StdEncoding.EncodeToString(data)
fmt.Println("data:image/png;base64," + encoded)
}
The example reads a PNG image into a byte slice and encodes it with Base64,
producing a data URI suitable for embedding in an <img> tag.
data, err := os.ReadFile("image.png")
os.ReadFile reads the entire image file into a byte slice.
fmt.Println("data:image/png;base64," + encoded)
The encoded data is prefixed with the data URI scheme, which browsers recognize and can render directly.
Source
Go encoding/base64 package - reference
In this article we have worked with Base64 encoding in Go.
Author
List all Go tutorials.