Use encoding/base64 for golang base64 encode and golang base64 decode (and searches like base64 encode golang, base64 decode golang, or base64 golang). EncodeToString and DecodeString work on []byte and string. A separate sharp edge is JSON: json.Marshal encodes a []byte field as a base64 string in JSON, which drives queries such as golang json prevent encoding byte to base64 and go encoding/json marshal []byte base64 string. This page covers both. For JSON workflows, see JSON unmarshal in Go and parse JSON; for bytes and text, see bytes to string in Go. URL percent-encoding is different from Base64—see URL encode and decode.
Tested with Go 1.24 on Linux.
golang base64 encode and decode (standard)
package main
import (
"encoding/base64"
"fmt"
)
func main() {
s := "Hello, world!"
enc := base64.StdEncoding.EncodeToString([]byte(s))
fmt.Println("encoded:", enc)
raw, err := base64.StdEncoding.DecodeString(enc)
if err != nil {
panic(err)
}
fmt.Println("decoded:", string(raw))
}You should see a padded Base64 line then decoded: Hello, world!.
URL-safe base64 (URLEncoding)
Use base64.URLEncoding when the payload may sit in a query string or path without +// surprises:
package main
import (
"encoding/base64"
"fmt"
)
func main() {
b := []byte{0xfb, 0xff, 0xbf}
s := base64.URLEncoding.EncodeToString(b)
out, err := base64.URLEncoding.DecodeString(s)
if err != nil {
panic(err)
}
fmt.Println(s, out)
}You should see the same three bytes round-trip.
Padding (NoPadding) and decoders
Some systems emit Base64 without = padding. Build an encoder with WithPadding(base64.NoPadding) and decode with the same alphabet and padding settings:
package main
import (
"encoding/base64"
"fmt"
)
func main() {
enc := base64.StdEncoding.WithPadding(base64.NoPadding)
s := enc.EncodeToString([]byte("Hi"))
fmt.Println(s)
dec := base64.StdEncoding.WithPadding(base64.NoPadding)
b, err := dec.DecodeString(s)
if err != nil {
panic(err)
}
fmt.Println(string(b))
}You should see SGk then Hi.
JSON: why []byte becomes Base64, and how to change it
By default, encoding/json marshals []byte as a Base64 JSON string (not a JSON array of integers). Example:
package main
import (
"encoding/json"
"fmt"
)
type Payload struct {
Blob []byte `json:"blob"`
}
func main() {
b, _ := json.Marshal(Payload{Blob: []byte{1, 2, 3}})
fmt.Println(string(b))
}You should see "blob":"AQID" (Base64 of 0x010203).
Ways to avoid that default when you need something else:
- Use
stringfor the field if the JSON should hold UTF-8 text (or your own hex/base64 layout you control). json.RawMessagewhen the value is already JSON bytes you want nested verbatim.MarshalJSONon a named type (type alias over[]byte) to emit a custom JSON shape.
Illustration with string plus explicit Base64 you manage:
package main
import (
"encoding/base64"
"encoding/json"
"fmt"
)
type Payload struct {
BlobB64 string `json:"blob_b64"`
}
func main() {
raw := []byte{1, 2, 3}
p := Payload{BlobB64: base64.StdEncoding.EncodeToString(raw)}
out, _ := json.Marshal(p)
fmt.Println(string(out))
}You should see a JSON object whose blob_b64 value is the same letters as EncodeToString, as a normal string field.
Encode small binary blobs (e.g. icons)
Read bytes with os.ReadFile (not deprecated ioutil), then EncodeToString for data: URLs or storage. This snippet skips a real file and encodes sample bytes so it stays self-contained:
package main
import (
"encoding/base64"
"fmt"
)
func main() {
icon := []byte{0x89, 0x50, 0x4e, 0x47} // fake PNG header prefix
s := base64.StdEncoding.EncodeToString(icon)
fmt.Println("data:image/png;base64," + s)
}You should see a data:image/png;base64,... prefix suitable for HTML src attributes.
Summary
Golang base64 encode flows through base64.StdEncoding or URLEncoding, EncodeToString, and decode with DecodeString plus error checks (how to decode base64 data in golang). Match encoder and decoder for alphabet and padding. For APIs, remember json.Marshal treats []byte as Base64 in JSON; to match golang json prevent encoding byte to base64 expectations, switch the field type or implement custom JSON. Pair binary transport with bytes/string helpers when you cross text boundaries.

