Skip to main content

The Buf logo

protobuf-py

PyPI version License Slack

protobuf-py is an ergonomic and modern Protobuf library for Python.

Well-typed, generated code you can read. High-performance encoder/decoder written in Rust. 100% conformance.
Zero third-party dependencies or tooling required.

Getting started • Examples • New to Protobuf?

from gen.user_pb import User

# Messages are plain Python objects: pass fields as keyword args, or set them later.
user = User(id="123", first_name="Alice")
user.last_name = "Smith"

# Serialize to the Protobuf wire format, then parse it back.
data = user.to_binary()
user = User.from_binary(data)

print(user.first_name)  # Alice
print(user.to_json())  # {"id": "123", "firstName": "Alice", "lastName": "Smith"}

Protobuf is the easiest way to build APIs. We recommend using it with Connect for Python, which generates server stubs for you:

from connectrpc.request import RequestContext

from gen.user_connect import UserService, UserServiceASGIApplication
from gen.user_pb import GetUserRequest, GetUserResponse, User


class UserHandler(UserService):
    async def get_user(
        self, request: GetUserRequest, ctx: RequestContext
    ) -> GetUserResponse:
        user = User(id=request.id, first_name="Alice", last_name="Smith")
        return GetUserResponse(user=user)


# Serve it with any ASGI server, e.g. `uvicorn server:app`.
app = UserServiceASGIApplication(UserHandler())

Connect can also generate client libraries for every major language, including your frontend. Here's what the generated Python client looks like:

from gen.user_connect import UserServiceClient
from gen.user_pb import GetUserRequest

client = UserServiceClient("http://localhost:8080")
response = client.get_user(GetUserRequest(id="123"))

print(response.user.first_name)  # Alice

Quickstart

// proto/user.proto
syntax = "proto3";

service UserService {
  rpc GetUser(GetUserRequest) returns (GetUserResponse);
}

message GetUserRequest {
  string id = 1;
}

message GetUserResponse {
  User user = 1;
}

message User {
  string id = 1;
  string first_name = 2;
  string last_name = 3;
}
# buf.gen.yaml
version: v2
inputs:
  - directory: proto
plugins:
  - local: protoc-gen-py
    out: src/gen
  - local: protoc-gen-connectrpc
    out: src/gen
$ uv add protobuf-py connectrpc
$ uv add --dev protoc-gen-py protoc-gen-connectrpc buf-bin
$ uv run -- buf generate

That's all - typed messages and Connect stubs now live in src/gen.

Feature highlights

Generated code you can read

class User(Message[_UserFields]):
    __slots__ = ("id", "first_name", "last_name")

    def __init__(
        self, *, id: str = "", first_name: str = "", last_name: str = ""
    ) -> None: ...

    id: str
    first_name: str
    last_name: str

Typed oneofs with pattern matching

from protobuf import Oneof

match msg.result:
    case Oneof(field="value", value=v):
        handle_value(v)
    case Oneof(field="error", value=e):
        handle_error(e)

Well-known types with friendly helpers

from datetime import UTC, datetime, timedelta
from protobuf.wkt import Any, Duration, Timestamp

ts = Timestamp.from_datetime(datetime.now(UTC))
td = Duration.from_timedelta(timedelta(minutes=5))
packed = Any.pack(user)

Seamless reflection

# Iterate over message fields
for field in user:
    # Access field name / value
    value = user[field]
    print(field.name, value)

    # Check for presence
    print(field in user)

    # Assign / delete fields
    user[field] = value
    del user[field]

How it compares

  • google-protobuf is complete, but generates code with unreadable binary blobs, broken imports, and a hostile API.
  • betterproto improves ergonomics, but it is proto3-only. The original project now points to betterproto2, which calls out active development, incomplete docs, and breaking changes.
Click here for a full comparison.
protobuf-py google-protobuf betterproto
Spec coverage ✅ 100% ⚠️ Known conformance failures ❌ proto3-only
Type annotations ✅ Built-in ❌ Third-party tooling needed ✅ Built-in
Readable generated code ✅ ❌ Classes are built only at runtime and cannot be inspected ✅
Imports ✅ Relative imports ❌ Broken without third-party tooling ✅ Relative imports
Oneofs ✅ Ergonomic, match-compatible ❌ String-returning WhichOneof() ⚠️ Tuple-returning helpers
Enums ✅ Python-native IntEnum ❌ int + EnumTypeWrapper ⚠️ Custom int subclass
Field presence ✅ msg.has_field("x") with IDE completions ⚠️ HasField("x") raises for proto3 scalars ⚠️ Helper-based
Field assignment (foo.x = 123) ✅ Direct assignment ❌ CopyFrom() required ✅ Direct assignment
copy.copy() / copy.replace() ✅ ❌ ❌
Global mutable registry ✅ Explicit Registry ❌ Process-wide singleton behavior ✅ N/A
Zero dependencies ✅ ✅ ❌ Includes grpclib, python-dateutil

Migration guide

google-protobuf protobuf-py
msg.SerializeToString() msg.to_binary()
MessageType.FromString(data) MessageType.from_binary(data)
msg.HasField("nickname") msg.has_field("nickname")
msg.WhichOneof("result") + string checks match msg.result with typed Oneof
msg.Extensions[ext] msg[ext]
msg.child.CopyFrom(other) msg.child = other

Metadata

Release files for protobuf-py 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for protobuf-py 0.6.0
File Size Uploaded
protobuf_py-0.6.0.tar.gz 161.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for protobuf-py 0.6.0
File Interpreter ABI Platform
protobuf_py-0.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 377.6 kB

Release files / protobuf_py-0.6.0.tar.gz

Download URL protobuf_py-0.6.0.tar.gz
Size 161.5 kB
Tags Source
SHA-256 checksum
How to use checksums
be6b8d84ba54380ca5e5e50f20e4dd42df81c845cf9dc8c021f147d8c516b341
BLAKE2b-256 checksum
How to use checksums
712a6a08d3a3ddbfd745f987c5ff22129a979ea74319fbfe5b9d59c7a6730d25
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.

Transparency log

Release files / protobuf_py-0.6.0-py3-none-any.whl

Download URL protobuf_py-0.6.0-py3-none-any.whl
Size 216.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2aba52a2d017487901cb4b8a7983e64a7bd369128c2ca86cafa4dd03da31012e
BLAKE2b-256 checksum
How to use checksums
0ed26271d5682d244b5b771f72fe7536a0c7e680e14300ea58f7d033fce813a8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.6.0 This release

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page