# Working with YAML Binary Data and Base64 Encoding in yaml-cpp

> Learn how to work with YAML binary data and Base64 encoding in yaml-cpp. Explore easy serialization and deserialization of byte sequences using the YAML::Binary class and public APIs.

- Repository: [Jesse Beder/yaml-cpp](https://github.com/jbeder/yaml-cpp)
- Tags: deep-dive
- Published: 2026-07-11

---

**yaml-cpp automatically handles binary data by encoding it as Base64 strings using the `YAML::Binary` class, enabling seamless serialization and deserialization of raw byte sequences through the public Node and Emitter APIs.**

When working with the jbeder/yaml-cpp library, handling raw binary data requires special consideration since YAML is a text-based format. The library provides first-class support for binary blobs through the `YAML::Binary` class, which automatically manages Base64 encoding during emission and decoding during parsing. This integration allows you to work with binary data as naturally as you would with strings or integers.

## Understanding the YAML::Binary Class

Located in [`include/yaml-cpp/binary.h`](https://github.com/jbeder/yaml-cpp/blob/main/include/yaml-cpp/binary.h), the `YAML::Binary` class serves as the primary container for binary data. It can hold either owned data via `std::vector<unsigned char>` or maintain a reference to unowned data through a pointer and size pair. The class provides essential methods including `size()`, `data()`, and `swap()`, along with equality comparison operators and copy utilities.

## How Base64 Encoding and Decoding Works

The actual Base64 implementation resides in [`src/binary.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/binary.cpp). The `EncodeBase64` function (lines 9-44) processes the byte stream by mapping every 3-byte chunk to 4 Base64 characters, implementing the standard RFC 4648 encoding. For decoding, `DecodeBase64` (lines 68-106) validates padding characters, skips whitespace, and reconstructs the original byte sequence. These functions are pure C++ implementations used internally by the conversion and emitter systems.

## Emitting Binary Data with the Emitter

When emitting binary data, the `Emitter` class (defined in [`include/yaml-cpp/emitter.h`](https://github.com/jbeder/yaml-cpp/blob/main/include/yaml-cpp/emitter.h)) provides the `Write(const Binary&)` method and stream operator overloads. These forward to low-level utilities in [`src/emitterutils.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/emitterutils.cpp) such as `WriteBinary`, `WriteLiteralBinary`, and `WriteSingleQuotedBinary`. These helpers invoke `EncodeBase64` and automatically apply the `!!binary` tag to the output scalar, ensuring standards-compliant YAML output.

## Parsing Binary Scalars from Nodes

The integration with the Node API happens through the `convert<Binary>` specialization in [`include/yaml-cpp/node/convert.h`](https://github.com/jbeder/yaml-cpp/blob/main/include/yaml-cpp/node/convert.h) (lines 94-103). When you call `Node::as<YAML::Binary>()`, the conversion specialization reads the scalar value, passes it to `DecodeBase64`, and swaps the resulting vector into the `Binary` object. This allows automatic decoding of Base64 strings back into raw bytes without manual intervention.

## Complete Code Examples

### Emitting Binary Data

```cpp
#include <yaml-cpp/yaml.h>
#include <iostream>

int main() {
    // Sample binary payload
    const unsigned char payload[] = {0x48, 0x65, 0x6c, 0x6c, 0x6f}; // "Hello"

    YAML::Binary bin(payload, sizeof(payload));

    YAML::Emitter out;
    out << YAML::BeginMap
        << YAML::Key << "greeting"
        << YAML::Value << bin          // <-- binary is emitted as Base64
        << YAML::EndMap;

    std::cout << out.c_str() << std::endl;
    /* Output:
       greeting: !!binary |
         SGVsbG8=
    */
}

```

The emitter automatically adds the `!!binary` tag and encodes the payload using the implementation in [`src/emitterutils.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/emitterutils.cpp).

### Parsing Base64-Encoded Scalars

```cpp
#include <yaml-cpp/yaml.h>
#include <iostream>

int main() {
    const std::string yaml = R"(
        picture: !!binary |
          iVBORw0KGgoAAAANSUhEUgAAAAUA
          AAAFCAYAAACNbyblAAAAHElEQVQI12P4
          //8/w38GIAXDIBKE0DHxgljNBAAO
          9TXL0Y4OHwAAAABJRU5ErkJggg==
    )";

    YAML::Node root = YAML::Load(yaml);
    YAML::Binary bin = root["picture"].as<YAML::Binary>(); // <-- decoded automatically

    // Access raw bytes
    const unsigned char* data = bin.data();
    std::size_t size = bin.size();

    std::cout << "Decoded " << size << " bytes.\n";
}

```

The `as<YAML::Binary>()` call triggers `convert<Binary>::decode`, which internally runs `DecodeBase64` from [`src/binary.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/binary.cpp).

### Mixing Binary with Other Types

```cpp
YAML::Emitter out;
out << YAML::BeginSeq
    << "plain text"
    << YAML::Binary("\x01\x02\x03", 3)  // will be emitted as base64
    << 42
    << YAML::EndSeq;

```

The emitter detects the type at compile-time and selects the appropriate `Write...Binary` helper from [`src/emitterutils.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/emitterutils.cpp).

## Summary

- The `YAML::Binary` class in [`include/yaml-cpp/binary.h`](https://github.com/jbeder/yaml-cpp/blob/main/include/yaml-cpp/binary.h) encapsulates binary data as either owned or unowned byte sequences.
- Base64 encoding and decoding are implemented in [`src/binary.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/binary.cpp) via `EncodeBase64` (lines 9-44) and `DecodeBase64` (lines 68-106).
- The `convert<Binary>` specialization in [`include/yaml-cpp/node/convert.h`](https://github.com/jbeder/yaml-cpp/blob/main/include/yaml-cpp/node/convert.h) enables automatic conversion between YAML nodes and binary data.
- The `Emitter` class automatically applies the `!!binary` tag and handles Base64 encoding when writing binary scalars.
- Binary data can be mixed seamlessly with other YAML types in sequences and mappings.

## Frequently Asked Questions

### How does yaml-cpp store binary data internally?

According to the source code in [`include/yaml-cpp/binary.h`](https://github.com/jbeder/yaml-cpp/blob/main/include/yaml-cpp/binary.h), the `YAML::Binary` class stores binary data as a `std::vector<unsigned char>` for owned data, or maintains a pointer and size for unowned data references. This dual approach allows efficient handling of both standalone binary objects and views into existing memory buffers without unnecessary copying.

### What Base64 variant does yaml-cpp use?

The implementation in [`src/binary.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/binary.cpp) uses standard Base64 encoding with padding characters as defined in RFC 4648. The `EncodeBase64` function maps 3-byte input chunks to 4-character output blocks, while `DecodeBase64` validates padding and skips whitespace during parsing, ensuring compatibility with standard YAML binary scalars.

### Can I decode Base64 strings manually without using YAML::Binary?

The `DecodeBase64` function in [`src/binary.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/binary.cpp) is an internal implementation detail. The recommended approach is to use `YAML::Load` to parse the YAML document and then call `Node::as<YAML::Binary>()` to trigger the conversion specialization in [`include/yaml-cpp/node/convert.h`](https://github.com/jbeder/yaml-cpp/blob/main/include/yaml-cpp/node/convert.h), which handles the decoding automatically through the `convert<Binary>` template.

### Does yaml-cpp support other binary encodings besides Base64?

The source code analysis shows that yaml-cpp specifically implements Base64 encoding for binary data to comply with the YAML 1.2 specification. The `!!binary` tag automatically triggers Base64 processing, and there is no built-in support for alternative encodings like hexadecimal or base85 in the current implementation.