Skip to content

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 .proto files 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 curl call works from any image.
  • Feeding other buf invocations. The Buf CLI accepts a FileDescriptorSet on stdin, so you can pipe this endpoint’s output straight into buf 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

text
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 main that always points at the latest commit on that label, so use main when you want “the latest published schema.”

Basic usage

Download the latest commit on the default label to a local file:

sh
curl -sSL "https://buf.build/acme/petapis/descriptor/main" -o petapis.binpb

Pin to an exact commit instead:

sh
curl -sSL "https://buf.build/acme/petapis/descriptor/7abdb7802c8f4737a1a23a35ca8266ef" -o petapis.binpb

Or pipe the response directly into another tool. The Buf CLI, for example, accepts a FileDescriptorSet on stdin:

sh
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:

sh
curl -sSL "https://buf.build/acme/private-apis/descriptor/main" \
    -H "Authorization: Bearer ${BUF_TOKEN}" \
    -o private-apis.binpb

Public 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:

sh
curl -sSL "https://buf.build/acme/petapis/descriptor/main?imports=false" -o petapis.binpb

Most 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:

sh
curl -sSL "https://buf.build/acme/petapis/descriptor/main?source_info=true" -o petapis.binpb

Source 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:

sh
curl -sSL "https://buf.build/acme/petapis/descriptor/main?source_retention_options=true" -o petapis.binpb

Response 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:

sh
curl -sSL "https://buf.build/acme/petapis/descriptor/main" \
    -H "Accept: application/json" \
    -o petapis.json

For 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:

sh
curl -sSL "https://buf.build/acme/petapis/descriptor/main" \
    -H "Accept-Encoding: gzip" \
    -o petapis.binpb.gz

Connect 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:

sh
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 .proto source 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.