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.5.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.5.0
File Size Uploaded
protobuf_py-0.5.0.tar.gz 160.9 kB Details

Built distribution (wheel)

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

Total release size: 375.1 kB

Release files / protobuf_py-0.5.0.tar.gz

Download URL protobuf_py-0.5.0.tar.gz
Size 160.9 kB
Tags Source
SHA-256 checksum
How to use checksums
a7be567fbcade37f7ead5c7ebdcda7d5d833afb0e68a569a7a80837f2f5defc1
BLAKE2b-256 checksum
How to use checksums
e0df744b304857f9727dad5938e37c88b834c7874581df4bdd36546e0718c5ba
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 15, 2026.

Transparency log

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

Download URL protobuf_py-0.5.0-py3-none-any.whl
Size 214.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1582e21c920a9c6932d5b9398aa55635315ecf7e05ab6eb09dcd3f9aba8ff7ac
BLAKE2b-256 checksum
How to use checksums
c94df574b8fece5fbce107bdaa2d4f81743e810275d584fda83456475ce3a836
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 15, 2026.

Transparency log

Release history Release notifications | RSS feed

0.6.0

2 release files

This release

0.5.0 This release

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