Base64 Encode & Decode in C++

Encode or decode below — it runs locally in your browser — then grab the canonical C++ code. The C++ standard library has no Base64, so you drop in a small self-contained std::string encoder, or call OpenSSL's EVP functions if you already link it.

INPUT
OUTPUT
Type or paste to encode / decode

Encode and decode a string

Encoding takes three bytes (24 bits) at a time, splits them into four 6-bit groups, and indexes each into the alphabet — padding the tail with =. Decoding reverses it with a reusable lookup table:

#include <array>
#include <cstdint>
#include <string>

static const char kTable[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789+/";

std::string base64_encode(const unsigned char* data, std::size_t len) {
    std::string out;
    out.reserve(((len + 2) / 3) * 4);
    std::size_t i = 0;
    while (i + 3 <= len) {
        std::uint32_t n = (data[i] << 16) | (data[i + 1] << 8) | data[i + 2];
        out.push_back(kTable[(n >> 18) & 0x3F]);
        out.push_back(kTable[(n >> 12) & 0x3F]);
        out.push_back(kTable[(n >> 6)  & 0x3F]);
        out.push_back(kTable[n & 0x3F]);
        i += 3;
    }
    if (std::size_t rem = len - i; rem > 0) {
        std::uint32_t n = data[i] << 16;
        if (rem == 2) n |= data[i + 1] << 8;
        out.push_back(kTable[(n >> 18) & 0x3F]);
        out.push_back(kTable[(n >> 12) & 0x3F]);
        out.push_back(rem == 2 ? kTable[(n >> 6) & 0x3F] : '=');
        out.push_back('=');
    }
    return out;
}

std::string base64_decode(const std::string& in) {
    static const auto table = [] {
        std::array<int, 256> t; t.fill(-1);
        for (int i = 0; i < 64; ++i)
            t[static_cast<unsigned char>(kTable[i])] = i;
        return t;
    }();
    std::string out;
    std::uint32_t buf = 0; int bits = 0;
    for (unsigned char c : in) {
        if (c == '=') break;
        int v = table[c];
        if (v < 0) continue;            // skip whitespace / newlines
        buf = (buf << 6) | v; bits += 6;
        if (bits >= 8) {
            bits -= 8;
            out.push_back(static_cast<char>((buf >> bits) & 0xFF));
        }
    }
    return out;
}

Tip: the C++ standard library has no Base64 — you either roll your own (as above) or use a library such as OpenSSL or Boost.Beast. Always index the decode table with unsigned char: a signed char > 127 is undefined behavior.

Using OpenSSL (EVP)

If your app already links OpenSSL, EVP_EncodeBlock / EVP_DecodeBlock from <openssl/evp.h> do it in one call. Link with -lcrypto:

#include <openssl/evp.h>
#include <string>
#include <vector>

std::string openssl_encode(const std::string& input) {
    std::string out;
    out.resize(4 * ((input.size() + 2) / 3));   // exact encoded size
    int n = EVP_EncodeBlock(
        reinterpret_cast<unsigned char*>(out.data()),
        reinterpret_cast<const unsigned char*>(input.data()),
        static_cast<int>(input.size()));
    out.resize(n);
    return out;
}

std::string openssl_decode(const std::string& encoded) {
    std::vector<unsigned char> out(3 * (encoded.size() / 4));
    int n = EVP_DecodeBlock(
        out.data(),
        reinterpret_cast<const unsigned char*>(encoded.data()),
        static_cast<int>(encoded.size()));
    if (n < 0) return {};   // decode error
    return std::string(reinterpret_cast<char*>(out.data()), n);
}

EVP_DecodeBlock always returns a multiple of three and does not account for padding — count the trailing = characters (0, 1, or 2) and subtract that many bytes for the true length, or use the streaming EVP_DecodeUpdate / EVP_DecodeFinal API.

URL-safe variant

The URL-safe alphabet (RFC 4648 §5) swaps + for - and / for _, and usually drops the = padding. With the custom encoder above it is a two-character change to the alphabet table:

static const char kUrlSafeTable[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789-_";   // '+' -> '-', '/' -> '_'

std::string base64url_encode(const unsigned char* data, std::size_t len) {
    std::string out = base64_encode(data, len);   // standard encode
    for (char& c : out) {
        if (c == '+') c = '-';
        else if (c == '/') c = '_';
    }
    while (!out.empty() && out.back() == '=') out.pop_back();  // strip padding
    return out;
}

To decode, translate - and _ back to + and / first. The bit-count decoder above reconstructs bytes without relying on padding, so unpadded input works as-is.

Frequently asked questions

Does C++ have a built-in Base64 function?

No. As of C++23 there is no Base64 in the standard library — no std::base64_encode, no header. You roll your own (under 100 lines) or use OpenSSL or Boost.Beast.

How do I Base64 encode a string in C++?

Use a small std::string encoder: base64_encode((const unsigned char*)"Hello", 5) returns "SGVsbG8=".

How do I Base64 encode with OpenSSL in C++?

Call EVP_EncodeBlock / EVP_DecodeBlock from <openssl/evp.h> and link with -lcrypto; remember EVP_DecodeBlock ignores padding.

How do I do URL-safe Base64 in C++?

Swap +// for -/_ in the alphabet table and strip the = padding (RFC 4648 §5).

Need image, file, or URL-safe modes?

The main base64.dev tool handles text, images, files, and URL-safe Base64 with auto-detect.

Open base64.dev →