Download a module’s FileDescriptorSet
The BSR can return the compiled form of any module as a google.protobuf.FileDescriptorSet, served directly over HTTP. This gives you a module’s schema in the native format that every Protobuf runtime understands, without having to install the Buf CLI or compile .proto files yourself.
What is a FileDescriptorSet?
A FileDescriptorSet is Protobuf’s own representation of a compiled schema: a list of FileDescriptorProto messages that describe every file, message, enum, service, and method. It’s the artifact protoc writes when you pass -o, and any Protobuf runtime can load one to power reflection, dynamic message decoding, and gRPC server reflection. For a full treatment of descriptors and how they’re used, see the Descriptors reference.
Note
The BSR returns a pure google.protobuf.FileDescriptorSet here, not a Buf image. Buf images are wire-compatible with FileDescriptorSets but carry extra Buf-specific metadata, which this endpoint strips. If you need that metadata, build the module locally with buf build; if you want a plain FileDescriptorSet from local sources, use buf build --as-file-descriptor-set.
When to use this endpoint
Common reasons to fetch the FileDescriptorSet from the BSR rather than building it locally:
- Populating gRPC server reflection with the schemas your server exposes, without checking
.protofiles into the server’s own source tree. - Building schema-driven tooling in a language that doesn’t have first-class Buf support, such as a Ruby or PHP service that dynamically decodes messages at runtime.
- Running checks in CI pipelines that can’t install the Buf CLI. A plain
curlcall works from any image. - Feeding other
bufinvocations. The Buf CLI accepts a FileDescriptorSet on stdin, so you can pipe this endpoint’s output straight intobuf lint,buf breaking, and the like.
If none of those apply and you already have the Buf CLI available, buf build --as-file-descriptor-set produces the same artifact from local .proto files.
URL structure
Syntax
https://BSR_INSTANCE/ORGANIZATION/MODULE/descriptor/REFERENCE- BSR_INSTANCE is the domain name of your BSR instance. (Default:
buf.build) - ORGANIZATION is the BSR organization that owns the module.
- MODULE is the name of the module.
- REFERENCE is either a commit ID or a label. Each repository has a default label named
mainthat always points at the latest commit on that label, so usemainwhen you want “the latest published schema.”
Basic usage
Download the latest commit on the default label to a local file:
curl -sSL "https://buf.build/acme/petapis/descriptor/main" -o petapis.binpbPin to an exact commit instead:
curl -sSL "https://buf.build/acme/petapis/descriptor/7abdb7802c8f4737a1a23a35ca8266ef" -o petapis.binpbOr pipe the response directly into another tool. The Buf CLI, for example, accepts a FileDescriptorSet on stdin:
curl -sSL "https://buf.build/acme/petapis/descriptor/main" | buf lint -The -o <file> flag tells curl where to write the response body. You may also see --output - (or -o -) in some examples; that’s curl’s way of writing to stdout. The rest of this page uses -o petapis.binpb for clarity.
Private modules
Modules in private repositories require a BSR token in the Authorization header:
curl -sSL "https://buf.build/acme/private-apis/descriptor/main" \
-H "Authorization: Bearer ${BUF_TOKEN}" \
-o private-apis.binpbPublic modules don’t require authentication.
Choosing what the FileDescriptorSet contains
Three query parameters control what ends up in the response. They’re independent and can be combined.
Imports
Every .proto file that a module transitively imports, whether it comes from within the module, from a dependency, or from a Well-Known Type, is represented by its own FileDescriptorProto. By default the endpoint includes all of them, so the returned FileDescriptorSet is self-contained and a Protobuf runtime can load it without resolving anything else.
If you only want the target module’s own files, add imports=false:
curl -sSL "https://buf.build/acme/petapis/descriptor/main?imports=false" -o petapis.binpbMost runtimes can’t build descriptor wrapper types without the full transitive closure, so leave this at the default unless you specifically need a stripped-down set.
Source code info
SourceCodeInfo records the file position and comments for every declaration. It’s what powers documentation generators, comment-aware reflection, and the BSR’s own UI. It’s also bulky, so the endpoint omits it by default. Request it with source_info=true:
curl -sSL "https://buf.build/acme/petapis/descriptor/main?source_info=true" -o petapis.binpbSource retention options
Source retention options are options declared with retention = RETENTION_SOURCE. They’re visible to compilers and code generators but are meant to be stripped before the descriptor is used at runtime. The endpoint strips them by default. Set source_retention_options=true if your tooling treats the descriptor as a source-level input rather than a runtime artifact:
curl -sSL "https://buf.build/acme/petapis/descriptor/main?source_retention_options=true" -o petapis.binpbResponse formats
The endpoint supports content negotiation via the Accept and Accept-Encoding headers.
Binary or JSON
The default response is the FileDescriptorSet in the Protobuf binary format, which is what every Protobuf runtime expects. Set Accept: application/json if you’d rather inspect the response by eye:
curl -sSL "https://buf.build/acme/petapis/descriptor/main" \
-H "Accept: application/json" \
-o petapis.jsonFor anything that’s going to parse the descriptor programmatically, stick with the binary default.
Compression
Ask for a gzip-compressed response with Accept-Encoding: gzip:
curl -sSL "https://buf.build/acme/petapis/descriptor/main" \
-H "Accept-Encoding: gzip" \
-o petapis.binpb.gzConnect API alternative
If your environment already speaks Connect or gRPC, the BSR exposes the same operation as the RPC method buf.registry.module.v1.FileDescriptorSetService/GetFileDescriptorSet. The HTTP endpoint on this page and that RPC return the same data; pick whichever is more natural in your environment.
Using the result
Once you have the FileDescriptorSet, any Protobuf runtime can load it. The quickest demonstration is feeding it back into the Buf CLI, which accepts a FileDescriptorSet as an input:
curl -sSL "https://buf.build/acme/petapis/descriptor/main?source_info=true" | buf lint -For programmatic use, see Dynamic messaging for a worked Go example that loads a FileDescriptorSet and decodes an arbitrary message by fully qualified name, and Runtime library support for the equivalent APIs in C++, Java, Python, C#, PHP, and TypeScript.
See also
- Export modules from the BSR - download the raw
.protosource files instead of a compiled FileDescriptorSet. - Descriptors - deep dive into what descriptors are and how Protobuf runtimes use them.
- Buf images - Buf’s FileDescriptorSet superset, used when Buf-specific metadata is needed.