The Python implementation of Connect: Protobuf RPC that works.
See the codeConnect is the easiest way to build modern APIs.
Building an API usually means writing the same types at least twice: once on the server, and once in every client. Connect makes this simple - define your API schema using Protobuf, and Connect generates type-safe server stubs and idiomatic client libraries in every major language, including for your frontend. All that's left to write is your business logic, in plain Python.
Connect already works with your current tech stack:
curl works out of the box.pyqwestInstall the runtime library:
uv add connectrpc
For codegen, install buf and create buf.gen.yaml:
version: v2
plugins:
- remote: buf.build/bufbuild/py
out: gen
- remote: buf.build/connectrpc/py
out: gen
The example above uses a Buf-hosted plugin server. To generate code entirely locally, install the relevant plugins:
uv add --dev protoc-gen-py protoc-gen-connectrpc
Now edit your buf.gen.yaml:
version: v2
plugins:
- local: .venv/bin/protoc-gen-py
out: gen
- local: .venv/bin/protoc-gen-connectrpc
out: gen
google-protobufConnect defaults to targeting protobuf-py as the Protocol Buffers implementation, but it also supports Google's Protocol Buffers for Python. Pass protobuf=google to the codegen plugin to use it.
version: v2
plugins:
- remote: buf.build/protocolbuffers/python
out: .
- remote: buf.build/protocolbuffers/pyi
out: .
- remote: buf.build/connectrpc/py
out: .
opt: protobuf=google
If configuring a client for JSON codec, make sure to pass connectrpc.compat.google_protobuf_json_codec instead of connectrpc.codec.proto_json_codec.
A basic Connect server is easy to set up. Just import the stubs, subclass the generated service, and serve:
from connectrpc.request import RequestContext
from your_service_pb import HelloRequest, HelloResponse
from your_service_connect import HelloService, HelloServiceASGIApplication
class MyHelloService(HelloService):
async def say_hello(
self, request: HelloRequest, ctx: RequestContext
) -> HelloResponse:
return HelloResponse(message=f"Hello, {request.name}!")
# Create ASGI app
app = HelloServiceASGIApplication(MyHelloService())
# Run with any ASGI server, e.g. uvicorn:
# uvicorn server:app --port 8080
Client libraries are automatically generated for you. Here's what the async client looks like:
from your_service_pb import HelloRequest, HelloResponse
from your_service_connect import HelloServiceClient
async def main():
# Create async client
async with HelloServiceClient("https://api.example.com") as client:
response = await client.say_hello(HelloRequest(name="World"))
print(response.message) # "Hello, World!"
And the sync client:
from your_service_pb import HelloRequest
from your_service_connect import HelloServiceClientSync
def main():
# Create sync client
with HelloServiceClientSync("https://api.example.com") as client:
response = client.say_hello(HelloRequest(name="World"))
print(response.message) # "Hello, World!"
if __name__ == "__main__":
main()
Check out the docs for more detailed usage.
932 followers · starred Jul 2026
761 followers · starred Jan 2026
62 followers · starred Jan 2026
52 followers · starred Oct 2026
The Python implementation of Connect: Protobuf RPC that works.
See the codeConnect is the easiest way to build modern APIs.
Building an API usually means writing the same types at least twice: once on the server, and once in every client. Connect makes this simple - define your API schema using Protobuf, and Connect generates type-safe server stubs and idiomatic client libraries in every major language, including for your frontend. All that's left to write is your business logic, in plain Python.
Connect already works with your current tech stack:
curl works out of the box.pyqwestInstall the runtime library:
uv add connectrpc
For codegen, install buf and create buf.gen.yaml:
version: v2
plugins:
- remote: buf.build/bufbuild/py
out: gen
- remote: buf.build/connectrpc/py
out: gen
The example above uses a Buf-hosted plugin server. To generate code entirely locally, install the relevant plugins:
uv add --dev protoc-gen-py protoc-gen-connectrpc
Now edit your buf.gen.yaml:
version: v2
plugins:
- local: .venv/bin/protoc-gen-py
out: gen
- local: .venv/bin/protoc-gen-connectrpc
out: gen
google-protobufConnect defaults to targeting protobuf-py as the Protocol Buffers implementation, but it also supports Google's Protocol Buffers for Python. Pass protobuf=google to the codegen plugin to use it.
version: v2
plugins:
- remote: buf.build/protocolbuffers/python
out: .
- remote: buf.build/protocolbuffers/pyi
out: .
- remote: buf.build/connectrpc/py
out: .
opt: protobuf=google
If configuring a client for JSON codec, make sure to pass connectrpc.compat.google_protobuf_json_codec instead of connectrpc.codec.proto_json_codec.
A basic Connect server is easy to set up. Just import the stubs, subclass the generated service, and serve:
from connectrpc.request import RequestContext
from your_service_pb import HelloRequest, HelloResponse
from your_service_connect import HelloService, HelloServiceASGIApplication
class MyHelloService(HelloService):
async def say_hello(
self, request: HelloRequest, ctx: RequestContext
) -> HelloResponse:
return HelloResponse(message=f"Hello, {request.name}!")
# Create ASGI app
app = HelloServiceASGIApplication(MyHelloService())
# Run with any ASGI server, e.g. uvicorn:
# uvicorn server:app --port 8080
Client libraries are automatically generated for you. Here's what the async client looks like:
from your_service_pb import HelloRequest, HelloResponse
from your_service_connect import HelloServiceClient
async def main():
# Create async client
async with HelloServiceClient("https://api.example.com") as client:
response = await client.say_hello(HelloRequest(name="World"))
print(response.message) # "Hello, World!"
And the sync client:
from your_service_pb import HelloRequest
from your_service_connect import HelloServiceClientSync
def main():
# Create sync client
with HelloServiceClientSync("https://api.example.com") as client:
response = client.say_hello(HelloRequest(name="World"))
print(response.message) # "Hello, World!"
if __name__ == "__main__":
main()
Check out the docs for more detailed usage.
932 followers · starred Jul 2026
761 followers · starred Jan 2026
62 followers · starred Jan 2026
52 followers · starred Oct 2026