Marcio Cunha

How to inspect gRPC traffic in terminal with grpcurl

Learn how to debug microservices via terminal using gRPC reflection with grpcurl without heavy graphical interfaces.

Marcio Cunha•7 min
Also available in:PortuguêsEspañol
Summary
  • The gRPC protocol uses HTTP/2 and Protocol Buffers for fast communication between microservices.
  • gRPC reflection allows discovering server methods and data structures without local .proto files.
  • The grpcurl tool acts like traditional curl but adapted for calling and inspecting gRPC services.
  • Simple terminal commands help list active services and test JSON payloads directly in production or development.
  • Proper use of TLS certificates and metadata ensures secure testing in complex cloud environments.

The challenge of debugging modern microservices

When developing microservice-based architectures, communication between components moves away from simple readable text formats and adopts highly optimized protocols. If you have ever needed to investigate data flow in distributed systems, you know that traditional network tools do not always provide the necessary visibility. To understand what is happening on the network, many engineers turn to deep inspections, much like what occurs when analyzing traffic with how to inspect HTTPS traffic in Wireshark using session keys, although gRPC brings specific challenges due to its binary serialization.

Created by Google, gRPC is built on top of HTTP/2 and uses Protocol Buffers to pack data into a compact binary format. In practice, this means packets that once looked like simple readable JSON now appear as incomprehensible character sequences if you open a standard packet analyzer. To make matters worse, since applications talk directly to each other behind the scenes, developers often remain blind, unable to know exactly which payload was sent or which response returned with an error.

Graphical interfaces for gRPC inspection are usually heavy, require complex installation, or depend on desktop environments that are not always available on remote servers. This is precisely the scenario where the grpcurl utility becomes indispensable. It brings the same agility and simplicity to the gRPC world that the classic curl command offers for traditional REST APIs, allowing direct interaction with services from the command line.

What is gRPC reflection and why it matters

Before firing arbitrary commands against a server, we need to understand how grpcurl discovers what the service is capable of. In traditional REST-based applications, documentation usually resides on web pages or OpenAPI files. In gRPC, contracts are defined in .proto files that rigorously describe messages and available methods.

However, requiring developers to have all those exact .proto files on their computer every time they need a quick test would be unfeasible. This is where gRPC reflection comes in, an internal mechanism allowing the server to expose its own data structure on demand. When reflection is enabled on the microservice, any authorized client can ask the server: Which services do you offer and what are the accepted fields?

In practice, this means you can connect to a container running in a remote cluster and instantly discover the entire API without loading local files. If the server does not have reflection enabled for security reasons, you can still provide definition files manually, but reflection drastically accelerates the feedback cycle during development and technical support in staging environments.

Installing and preparing the environment for use

Installing grpcurl is straightforward and can be accomplished using major package managers on modern operating systems. Because the tool is written in the Go language, it is distributed as a single compiled binary without complex external library dependencies to run in your terminal.

To verify basic tool functionality and ensure it is accessible in your execution path, we can run a quick command that displays its current version. If you are using Linux or macOS-based systems, installation usually takes just a few seconds using utilities like Homebrew or downloading the official binary directly from GitHub.

Below, we highlight the fundamental steps to get the test environment up and running in your working terminal, allowing you to start inspecting your services immediately:

  1. Download the binary compatible with your operating system architecture directly from the official GitHub repository or use a package manager.
  2. Move the downloaded executable to a directory included in your system's PATH environment variable, such as /usr/local/bin/.
  3. Validate the installation by running the base command to check if the utility responds correctly without dependency errors.
# Example of validating grpcurl installation in the terminal
grpcurl --version

Keeping diagnostic tools clean and organized in the system helps avoid future operational issues, much like the routine of how to clear system cache on Ubuntu via terminal safely to free up disk space and ensure the development environment responds with maximum efficiency.

Discovering services and listing available methods

With the tool installed and gRPC reflection active on the target server, the first practical step is mapping the API surface. We want to know exactly which services are running on that specific IP address and port, without guessing route names or message structures.

The list command in grpcurl is the ideal starting point for this exploration. It communicates with the endpoint and returns a readable tree with available packages and service names. Let's see how to execute this initial query against a server running locally on port 50051:

# List all available services that support reflection
grpcurl -plaintext localhost:50051 list

The -plaintext flag indicates we are connecting without TLS encryption, which is common in local development environments. If the server exposes multiple services, the command will list all of them. To detail the methods of a specific service, simply pass the full service name right after the command:

# List methods of a specific service named MyService
grpcurl -plaintext localhost:50051 list MyService

Describing data structures and contracts

Knowing which methods exist is only half the battle; to interact with them, we need to know the data types expected in requests and returned in responses. The describe command in grpcurl reveals the exact contract of any message or service exposed by reflection.

If we want to understand the structure of a specific request object, we run the query pointing directly to the data type. This provides a massive advantage over manually reading extensive .proto files, delivering the formatted result straight to the terminal.

# Describe the detailed structure of a gRPC message
grpcurl -plaintext localhost:50051 describe MyService.ExampleRequest

In practice, the terminal will display accepted fields, their corresponding data types, and whether they are required or optional. This detailed inspection prevents common typing errors when sending complex payloads.

Sending requests and testing endpoints in real time

Now that we know the services, methods, and data structures, we can execute actual calls using the call command. grpcurl accepts input data in standard JSON format and automatically converts it to the binary Protocol Buffers format required by gRPC behind the scenes.

Imagine we need to test a user creation method that receives a simple JSON containing name and email. Execution in the terminal is straightforward and displays the formatted response as soon as the server processes the request:

# Send a gRPC request using a direct JSON payload in the terminal
grpcurl -plaintext -d '{"name": "Marcio", "email": "[email protected]"}' localhost:50051 MyService/CreateUser

The -d flag allows injecting the JSON payload directly into the command line. If the payload is very long or complex, you can also read the content of a local JSON file using the @ prefix followed by the file path.

Handling authentication and secure TLS connections

In production environments or advanced staging setups, microservices rarely run without encryption. They require secure connections via TLS and frequently use authorization tokens based on HTTP/2 metadata, such as JWT tokens passed in the authorization header.

To interact with secure servers, we remove the -plaintext flag and provide the necessary certificates or allow insecure connections for testing with self-signed certificates using the -insecure flag. Additionally, we can inject custom metadata with the -H flag:

# Execute a gRPC call on a secure server with an authentication token
grpcurl -insecure -H 'authorization: Bearer your_jwt_token_here' -d '{"id": 123}' api.example.com:443 MyService/GetUser

This flexibility turns grpcurl into an indispensable Swiss Army knife for engineers who need to diagnose integration failures, validate API contracts, and inspect microservice behavior directly from the command line without heavy operational barriers. To explore these architectural concepts further in production, see our related technical analysis on Container crashing? How to track the Linux OOM Killer.

Final considerations

Mastering command-line tools like grpcurl significantly increases an engineer's autonomy when investigating, debugging, and validating microservice-based architectures. By eliminating the dependency on heavy graphical interfaces and harnessing the power of gRPC reflection, we make the development workflow more agile and transparent. Integrating this practice into your daily routine ensures fast and precise diagnostics, allowing you to understand the exact behavior of the network and services under your responsibility.