fetch supports making gRPC calls with automatic protocol handling, reflection-backed schema discovery, JSON-to-protobuf conversion, and formatted responses.
gRPC (gRPC Remote Procedure Calls) is a high-performance RPC framework that uses Protocol Buffers for serialization and HTTP/2 for transport.
Enable gRPC mode. This flag:
- Forces HTTP/2 protocol
- Sets method to POST
- Adds gRPC headers (
Content-Type: application/grpc+proto,TE: trailers,grpc-accept-encoding: gzip) - Applies gRPC message framing
- Handles gRPC response framing, including gzip-compressed response messages when the server sends
grpc-encoding: gzip
fetch --grpc https://localhost:50051/package.Service/MethodWhen --proto-file or --proto-desc is not provided, fetch automatically tries gRPC reflection for schema-aware request conversion and response formatting.
List available services from a reflection-enabled server:
fetch --grpc-list https://localhost:50051Or run the same lookup offline with a local descriptor set:
fetch --grpc-list --proto-desc service.pbDescribe a service, method, or message:
fetch --grpc-describe grpc.health.v1.Health https://localhost:50051
fetch --grpc-describe grpc.health.v1.Health/Check https://localhost:50051
fetch --grpc-describe grpc.health.v1.HealthCheckRequest --proto-desc service.pbNAME accepts:
package.Servicepackage.Service/Methodpackage.Service.Method- full message names
The service and method are specified in the URL path:
https://host:port/package.ServiceName/MethodName
Example:
# Call Echo method on EchoService in the echo package
fetch --grpc https://localhost:50051/echo.EchoService/EchoTo enable offline discovery, guaranteed JSON-to-protobuf conversion, or to bypass reflection entirely, provide a local proto schema.
Compile .proto files using protoc (must be installed). Supports multiple comma-separated paths.
fetch --grpc --proto-file service.proto \
-j '{"message": "hello"}' \
https://localhost:50051/echo.EchoService/EchoMultiple files:
fetch --grpc --proto-file common.proto,service.proto \
-j '{"request": "data"}' \
https://localhost:50051/pkg.Service/MethodUse a pre-compiled descriptor set file. Useful when:
protocis not available at run time- You want faster startup (no compilation)
- Building CI/CD pipelines
Generate a descriptor set:
protoc --descriptor_set_out=service.pb --include_imports service.protoUse the descriptor:
fetch --grpc --proto-desc service.pb \
-j '{"message": "hello"}' \
https://localhost:50051/echo.EchoService/EchoAdd import paths for proto compilation. Use with --proto-file when your protos have imports.
fetch --grpc \
--proto-file service.proto \
--proto-import ./proto \
--proto-import /usr/local/include \
-j '{"field": "value"}' \
https://localhost:50051/pkg.Service/Method- The service and method are extracted from the URL path
fetchlooks up the method's input/output message types in the schema- JSON request bodies are converted to protobuf wire format
- The request is framed with gRPC length-prefix
- Response protobuf is formatted as JSON with field names from the schema
When no local schema is provided:
fetchfirst tries gRPC reflection- If reflection is available, request/response descriptors are resolved automatically
- If reflection is unavailable, schema-less requests still work for raw/empty protobuf bodies and responses fall back to generic protobuf formatting
- JSON request bodies fail with an actionable error because descriptors are required for conversion
If reflection is unavailable and you need schema-aware behavior, pass --proto-file or --proto-desc.
With a proto schema, send JSON that matches your message structure:
fetch --grpc --proto-file user.proto \
-j '{
"name": "John Doe",
"age": 30,
"email": "john@example.com"
}' \
https://localhost:50051/users.UserService/CreateUserThe JSON is automatically converted to protobuf wire format.
fetch --grpc --proto-file order.proto \
-j '{
"customer": {
"id": 123,
"name": "Jane"
},
"items": [
{"product_id": 1, "quantity": 2},
{"product_id": 5, "quantity": 1}
]
}' \
https://localhost:50051/orders.OrderService/CreateOrderFor methods that take empty messages:
fetch --grpc --proto-file service.proto \
https://localhost:50051/health.HealthService/CheckOr with an empty JSON object:
fetch --grpc --proto-file service.proto \
-j '{}' \
https://localhost:50051/health.HealthService/Checkfetch --grpc --proto-file service.proto \
-j @request.json \
https://localhost:50051/pkg.Service/MethodResponses are formatted as JSON with field names:
{
"name": "John Doe",
"age": 30,
"email": "john@example.com",
"created_at": {
"seconds": 1704067200,
"nanos": 0
}
}Generic protobuf parsing shows field numbers:
1: "John Doe"
2: 30
3: "john@example.com"
4 {
1: 1704067200
2: 0
}
For development servers with self-signed certificates:
fetch --grpc --insecure \
--proto-file service.proto \
-j '{"request": "data"}' \
https://localhost:50051/pkg.Service/MethodFor local development servers that use plaintext HTTP/2, use an http:// URL:
fetch --grpc -j '{"service":""}' http://127.0.0.1:50051/grpc.health.v1.Health/Check
fetch --grpc-list http://127.0.0.1:50051fetch --grpc \
--ca-cert ca.crt \
--proto-file service.proto \
-j '{"request": "data"}' \
https://server.example.com:50051/pkg.Service/Methodfetch --grpc \
--cert client.crt \
--key client.key \
--ca-cert ca.crt \
--proto-file service.proto \
-j '{"request": "data"}' \
https://secure.example.com:50051/pkg.Service/MethodSee request and response headers:
fetch --grpc --proto-file service.proto \
-j '{"field": "value"}' \
-vv \
https://localhost:50051/pkg.Service/MethodInspect the request without sending:
fetch --grpc --proto-file service.proto \
-j '{"field": "value"}' \
--dry-run \
https://localhost:50051/pkg.Service/MethodModify the JSON request body in an editor:
fetch --grpc --proto-file service.proto \
-j '{"template": "value"}' \
--edit \
https://localhost:50051/pkg.Service/Methodfetch --grpc https://localhost:50051/grpc.health.v1.Health/Checkfetch --grpc --proto-file api.proto \
-j '{
"resource": {
"name": "my-resource",
"type": "TYPE_A",
"config": {"key": "value"}
}
}' \
https://api.example.com/resources.ResourceService/Createfetch --grpc --proto-file api.proto \
-j '{"page_size": 10, "page_token": ""}' \
https://api.example.com/users.UserService/ListUsersfetch --grpc --proto-file api.proto \
-H "Authorization: Bearer $TOKEN" \
-j '{"id": "123"}' \
https://api.example.com/users.UserService/GetUserInstall Protocol Buffers compiler:
# macOS
brew install protobuf
# Ubuntu/Debian
apt install protobuf-compiler
# Or use --proto-desc with pre-compiled descriptors- Verify the URL path matches
package.Service/Methodexactly - Check that your proto file defines the service and method
- Include all necessary imports with
--proto-import.
- Verify JSON syntax is correct
- Check field names match proto definitions (use snake_case)
- Make sure that the types match. Put quotation marks around strings, but not around numbers.
- gRPC requires HTTP/2. Make sure that the server supports it.
- Check port number (gRPC typically uses different ports than REST)
- For TLS issues, try
--insecurefor testing
- If response is empty, check gRPC status in headers (
-vv) - Verify proto schema matches server's actual message format
- Try without schema to see raw wire format
fetch supports server-streaming gRPC responses. It formats and displays each
response message when the message arrives. SSE and NDJSON responses use the
same streaming pattern.
fetch --grpc --proto-file service.proto \
-j '{"query": "search term"}' \
https://localhost:50051/search.SearchService/StreamResultsFor streaming responses, messages are separated by blank lines in the output. Formatting and flushing happen incrementally, so results appear in real time.
If a server compresses individual response messages, fetch decompresses gzip-framed gRPC messages before protobuf decoding. Unsupported per-message encodings are reported with the encoding name.
fetch reports gRPC status errors from response trailers. If the server returns a non-OK gRPC status (e.g., INTERNAL, NOT_FOUND), the error is printed to stderr and the exit code is set to 1.
fetch supports client-side streaming gRPC calls. When the proto schema indicates a method is client-streaming, multiple JSON objects in the request body are each converted to a separate protobuf message and sent as individual gRPC frames.
fetch uses the method descriptor in the proto schema to detect client
streaming. You do not need additional flags.
Provide multiple JSON objects separated by whitespace:
fetch --grpc --proto-file service.proto \
-d '{"value":"one"}{"value":"two"}{"value":"three"}' \
https://localhost:50051/pkg.Service/ClientStreamfetch --grpc --proto-file service.proto \
-d @messages.ndjson \
https://localhost:50051/pkg.Service/ClientStreamPipe data from stdin for real-time streaming. fetch sends each JSON object
when it completes parsing the object:
cat messages.ndjson | fetch --grpc --proto-file service.proto \
-d @- https://localhost:50051/pkg.Service/ClientStreamBidirectional streaming uses the same mechanism as client streaming. When you
pipe data from stdin, fetch sends request frames incrementally. At the same
time, it receives and displays response frames:
cat messages.ndjson | fetch --grpc --proto-file service.proto \
-d @- https://localhost:50051/pkg.Service/BidiStreamBoth directions use the same HTTP/2 stream. fetch formats and displays each
response message when it arrives.
- Client and bidirectional streaming require a proto schema: Specify
--proto-fileor--proto-desc.fetchuses the schema to identify a client-streaming method. - gRPC-Web: Standard gRPC protocol only, not gRPC-Web
- CLI Reference - All gRPC options
- Authentication - mTLS setup
- Troubleshooting - Common issues