unsandbox.com
Anonymous remote code, compile, & execution API for humans & machine learning agents.
Docs 📚 View Pricing →December 02, 2025
Protocol Buffers Playground: Compile and Test Protobufs in the Browser
Working with Protocol Buffers usually means setting up protoc, language-specific plugins, and build pipelines. What if you could just upload a .proto file and immediately start serializing and deserializing messages?
Today we’ll show you how to use unsandbox as a protobuf playground - perfect for learning, debugging, and rapid prototyping.
The Setup: Zero Installation Required
unsandbox containers come with:
-
protoc3.21.12 (protobuf compiler) -
Python
protobuflibrary -
Ruby
google-protobufgem - Go protobuf support
- Full input file support
This means you can upload a .proto schema and immediately work with it - no local installation needed.
Example 1: Your First Protobuf in Python
Let’s define a simple Person message and serialize it:
person.proto:
syntax = "proto3";
message Person {
string name = 1;
int32 age = 2;
}
API Request:
{
"language": "python",
"code": "import subprocess, sys, os\nos.chdir('/tmp/input')\nsubprocess.run(['protoc', '--python_out=.', 'person.proto'], check=True)\nsys.path.insert(0, '.')\nimport person_pb2\n\n# Create a Person message\nperson = person_pb2.Person(name='Alice', age=30)\nprint(f'Created: {person}')\n\n# Serialize to binary\ndata = person.SerializeToString()\nprint(f'Serialized ({len(data)} bytes): {data.hex()}')\n\n# Deserialize back\nperson2 = person_pb2.Person()\nperson2.ParseFromString(data)\nprint(f'Deserialized: name={person2.name}, age={person2.age}')",
"input_files": [
{"filename": "person.proto", "content": "c3ludGF4ID0gInByb3RvMyI7CgptZXNzYWdlIFBlcnNvbiB7CiAgc3RyaW5nIG5hbWUgPSAxOwogIGludDMyIGFnZSA9IDI7Cn0K"}
]
}
Output:
Created: name: "Alice"
age: 30
Serialized (9 bytes): 0a05416c696365101e
Deserialized: name=Alice, age=30
What just happened:
-
Uploaded
person.protoas base64 -
protoccompiled it toperson_pb2.py - Created a Person message
-
Serialized to 9 bytes:
0a05416c696365101e - Deserialized it back
Example 2: Decode Unknown Protobuf Binary
Have a mystery .bin file and its schema? Upload both and decode:
{
"language": "python",
"code": "import subprocess, sys, os\nos.chdir('/tmp/input')\nsubprocess.run(['protoc', '--python_out=.', 'person.proto'], check=True)\nsys.path.insert(0, '.')\nimport person_pb2\n\n# Read the binary protobuf data\nwith open('data.bin', 'rb') as f:\n data = f.read()\nprint(f'Binary data: {data.hex()}')\n\n# Decode it\nperson = person_pb2.Person()\nperson.ParseFromString(data)\nprint(f'Decoded: name={person.name}, age={person.age}')",
"input_files": [
{"filename": "person.proto", "content": "c3ludGF4ID0gInByb3RvMyI7CgptZXNzYWdlIFBlcnNvbiB7CiAgc3RyaW5nIG5hbWUgPSAxOwogIGludDMyIGFnZSA9IDI7Cn0K"},
{"filename": "data.bin", "content": "CgVBbGljZRAe"}
]
}
Output:
Binary data: 0a05416c696365101e
Decoded: name=Alice, age=30
This is perfect for debugging - paste your hex dump, convert to base64, and see what’s inside!
Example 3: Nested Messages and Repeated Fields
Let’s try something more complex:
addressbook.proto:
syntax = "proto3";
message Person {
string name = 1;
int32 id = 2;
string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phones = 4;
}
message AddressBook {
repeated Person people = 1;
}
Python code to populate and serialize:
import subprocess, sys, os
os.chdir('/tmp/input')
subprocess.run(['protoc', '--python_out=.', 'addressbook.proto'], check=True)
sys.path.insert(0, '.')
import addressbook_pb2
# Create an address book
book = addressbook_pb2.AddressBook()
# Add first person
alice = book.people.add()
alice.name = "Alice"
alice.id = 1234
alice.email = "alice@example.com"
phone = alice.phones.add()
phone.number = "555-1234"
phone.type = addressbook_pb2.Person.MOBILE
# Add second person
bob = book.people.add()
bob.name = "Bob"
bob.id = 5678
bob.email = "bob@example.com"
phone = bob.phones.add()
phone.number = "555-5678"
phone.type = addressbook_pb2.Person.WORK
# Serialize
data = book.SerializeToString()
print(f"Address book ({len(data)} bytes):")
print(f"Hex: {data.hex()}")
# Show the text format
print("\nText format:")
print(book)
Output:
Address book (62 bytes):
Hex: 0a1e0a05416c696365...
Text format:
people {
name: "Alice"
id: 1234
email: "alice@example.com"
phones {
number: "555-1234"
}
}
people {
name: "Bob"
id: 5678
email: "bob@example.com"
phones {
number: "555-5678"
type: WORK
}
}
Example 4: Raw Wire Format Inspection
Want to understand the protobuf wire format? Let’s decode it byte by byte:
import subprocess, sys, os
os.chdir('/tmp/input')
subprocess.run(['protoc', '--python_out=.', 'person.proto'], check=True)
sys.path.insert(0, '.')
import person_pb2
person = person_pb2.Person(name="Alice", age=30)
data = person.SerializeToString()
print("Wire format breakdown:")
print(f"Raw bytes: {data.hex()}")
print()
# Decode wire format manually
i = 0
while i < len(data):
tag_byte = data[i]
field_number = tag_byte >> 3
wire_type = tag_byte & 0x07
wire_type_names = {0: 'varint', 1: '64-bit', 2: 'length-delimited', 5: '32-bit'}
print(f"Field {field_number}, Wire type {wire_type} ({wire_type_names.get(wire_type, 'unknown')})")
i += 1
if wire_type == 0: # Varint
value = 0
shift = 0
while data[i] & 0x80:
value |= (data[i] & 0x7f) << shift
shift += 7
i += 1
value |= data[i] << shift
i += 1
print(f" Value: {value}")
elif wire_type == 2: # Length-delimited
length = data[i]
i += 1
content = data[i:i+length]
i += length
print(f" Length: {length}, Content: {content} ({content.hex()})")
Output:
Wire format breakdown:
Raw bytes: 0a05416c696365101e
Field 1, Wire type 2 (length-delimited)
Length: 5, Content: b'Alice' (416c696365)
Field 2, Wire type 0 (varint)
Value: 30
Now you can see exactly how protobuf encodes data!
Example 5: Schema Evolution Testing
Protobuf is famous for backward/forward compatibility. Test it:
v1.proto (original):
syntax = "proto3";
package v1;
message User {
string name = 1;
int32 age = 2;
}
v2.proto (new field added):
syntax = "proto3";
package v2;
message User {
string name = 1;
int32 age = 2;
string email = 3; // New field!
}
Test forward compatibility:
import subprocess, sys, os
os.chdir('/tmp/input')
# Compile both versions
subprocess.run(['protoc', '--python_out=.', 'v1.proto'], check=True)
subprocess.run(['protoc', '--python_out=.', 'v2.proto'], check=True)
sys.path.insert(0, '.')
import v1_pb2
import v2_pb2
# Create v2 message with new field
user_v2 = v2_pb2.User(name="Alice", age=30, email="alice@example.com")
data = user_v2.SerializeToString()
print(f"v2 serialized: {data.hex()}")
# Read with v1 (old code reading new data)
user_v1 = v1_pb2.User()
user_v1.ParseFromString(data)
print(f"v1 reads: name={user_v1.name}, age={user_v1.age}")
print("Email field? v1 ignores unknown fields - forward compatible!")
Quick Reference: Base64 Encoding Your Proto Files
To upload files, you need base64. Here’s how:
Linux/Mac:
base64 -w 0 person.proto
Python:
import base64
with open('person.proto', 'rb') as f:
print(base64.b64encode(f.read()).decode())
JavaScript:
const content = "syntax = \"proto3\";\n\nmessage Person {\n string name = 1;\n int32 age = 2;\n}\n";
console.log(btoa(content));
Use Cases
1. Learning Protobufs
Skip the installation hassle. Just write a .proto, upload it, and experiment.
2. Debugging Wire Format
Got a hex dump from a network capture? Paste it, decode it, understand it.
3. Schema Validation
Test if your schema compiles before committing. Verify field numbers don’t conflict.
4. Cross-Language Testing
Serialize in Python, deserialize in Go. Verify your messages work across languages.
5. API Documentation
Show working examples of your protobuf messages with actual serialized output.
Limits
- File size: Max 5MB per file (plenty for schemas)
- Execution time: 15 minute timeout
- protoc version: 3.21.12 (proto3 fully supported)
Try It Now
- Go to unsandbox.com
- Select Python
- Paste your protobuf code
-
Upload your
.protofile (or use the base64 input_files parameter) - Run!
No installation. No build pipeline. Just protobufs.
Happy serializing!