docs/sources/view-and-analyze-profile-data/profile-cli.md
Pyroscope provides a command-line interface (CLI), profilecli.
This utility enables various productivity flows such as:
{{< admonition type="tip">}}
Use the help command (profilecli help) for a full list of capabilities and help information.
{{< /admonition>}}
You can install Profile CLI using a package or by compiling the code.
On macOS, you can install Profile CLI using Homebrew:
brew install pyroscope-io/brew/profilecli
For other platforms, you can manually download the profilecli release asset for your operating system and architecture and make it executable.
For example, for Linux with the AMD64 architecture:
Download and extract the package (archive).
curl -fL https://github.com/grafana/pyroscope/releases/download/v1.13.2/profilecli_1.13.2_linux_amd64.tar.gz | tar xvz
Make profilecli executable:
chmod +x profilecli
Optional: Make profilecli reachable from anywhere:
sudo mv profilecli /usr/local/bin
To build from source code, you must have:
$GOPATH or $GOBIN configured and added to your PATH environment variable.To build the source code:
Clone the repository.
git clone [email protected]:grafana/pyroscope.git
Run the Go install command to build and install the package.
cd pyroscope
go install ./cmd/profilecli
The command places the profilecli executable in $GOPATH/bin/ (or $GOBIN/) and makes it available to use.
The profilecli commands that interact with a Pyroscope server use the same connection and authentication flags. You can pass them as command flags or environment variables.
| Purpose | Flag | Environment variable | Default | When it helps |
|---|---|---|---|---|
| Pyroscope endpoint | --url | PROFILECLI_URL | http://localhost:4040 | Point the command to your local server, Grafana Cloud Profiles endpoint, or Grafana data source proxy URL. |
| Basic authentication | --username, --password | PROFILECLI_USERNAME, PROFILECLI_PASSWORD | empty | Authenticate with a Cloud Profiles endpoint using stack ID and API token. |
| Bearer token | --token | PROFILECLI_TOKEN | empty | Authenticate through Grafana data source proxy URLs or token-based environments. |
| Tenant header | --tenant-id | PROFILECLI_TENANT_ID | empty | Set X-Scope-OrgID when you query or upload against multi-tenant deployments. |
| Transport protocol | --protocol | Not available | connect | Troubleshoot compatibility by switching to grpc or grpc-web if needed. |
Use the method that matches your environment.
Use this pattern when you connect directly to a Cloud Profiles endpoint.
export PROFILECLI_URL=https://profiles-prod-001.grafana.net
export PROFILECLI_USERNAME=<cloud_stack_id>
export PROFILECLI_PASSWORD=<cloud_access_policy_token>
profilecli query series --query='{service_name="checkout"}'
This is the most common setup when you are querying Cloud Profiles directly.
Use this pattern when you connect through a Grafana data source proxy URL.
export PROFILECLI_URL=https://grafana.example.net/api/datasources/proxy/uid/<uid>
export PROFILECLI_TOKEN=<glsa_or_glc_token>
profilecli query profile --profile-type=process_cpu:cpu:nanoseconds:cpu:nanoseconds
This is helpful when you want to use existing Grafana access controls instead of direct Pyroscope credentials.
Use this pattern for self-managed, multi-tenant Pyroscope deployments.
export PROFILECLI_URL=https://pyroscope.example.net
export PROFILECLI_TENANT_ID=team-a
profilecli upload --extra-labels=service_name=payments ./cpu.pprof
This is useful when a shared Pyroscope deployment routes data by tenant.
You can use environment variables to avoid passing flags to every command and to reduce accidental credential exposure in shell history.
Environment variables have a PROFILECLI_ prefix. Here is an example:
export PROFILECLI_URL=<pyroscope_server_url>
export PROFILECLI_USERNAME=<username>
export PROFILECLI_PASSWORD=<password>
# now you can run profilecli commands without repeating URL or credentials:
profilecli <command>
{{< admonition type="caution" >}}
If you're querying data from Cloud Profiles, use the URL of your Cloud Profiles server in PROFILECLI_URL (for example, https://profiles-prod-001.grafana.net) and not the URL of your Grafana Cloud tenant (for example, <your-tenant>.grafana.net).
{{< /admonition >}}
profilecliUsing profilecli streamlines the process of uploading profiles to Pyroscope, making it a convenient alternative to manual HTTP requests.
Use profilecli upload when you have an exported pprof file and want to:
profilecli installed on your system by following the installation steps above.Identify the pprof file.
path/to/your/pprof-file.pprofOptional: Specify any extra labels.
--extra-labels flag.service_name label (defaults to profilecli-upload). This will be useful when querying the data via profilecli or the UI.--override-timestamp if you want the uploaded profile to be treated as "now" instead of its original capture time.Construct and execute the Upload command.
Here's a basic command template:
export PROFILECLI_URL=<pyroscope_server_url>
export PROFILECLI_USERNAME=<username>
export PROFILECLI_PASSWORD=<password>
profilecli upload --extra-labels=<label_name>=<label_value> <pprof_file_path>
Example command:
export PROFILECLI_URL=https://profiles-prod-001.grafana.net
export PROFILECLI_USERNAME=my_username
export PROFILECLI_PASSWORD=my_password
profilecli upload path/to/your/pprof-file.pprof
Example command with extra labels:
export PROFILECLI_URL=https://profiles-prod-001.grafana.net
export PROFILECLI_USERNAME=my_username
export PROFILECLI_PASSWORD=my_password
profilecli upload \
--extra-labels=service_name=my_application_name \
--extra-labels=cluster=us-east \
path/to/your/pprof-file.pprof
Example command with timestamp override:
profilecli upload \
--override-timestamp \
--extra-labels=service_name=debug-replay \
./local-capture.pprof
Check for successful upload.
profilecli provides error messages to help you troubleshoot.profilecliYou can use the profilecli query command to look up the available profiles on a Pyroscope server and read actual profile data.
This can be useful for debugging purposes or for integrating profiling in CI pipelines (for example to facilitate profile-guided optimization).
You can use the profilecli query series command to look up the available profiles on a Pyroscope server.
By default, it queries the last hour of data, though this can be controlled with the --from and --to flags.
You can narrow the results down with the --query flag. See profilecli help query series for more information.
This command is most helpful when you are exploring an unfamiliar environment and need to discover:
Optional: Specify a query, time range, and output format.
--query flag, for example: --query='{service_name="my_application_name"}'.--from and --to flags, for example, --from="now-3h" --to="now".--label-names flag, for example, --label-names=__profile_type__,service_name.--output=table (default) or --output=json. The table view renders one row per series with label names as sorted column headers. The JSON format emits a structured envelope containing from, to, and a series array, which is useful for scripting and pipeline integrations.Construct and execute the Query Series command.
Here's a basic command template:
export PROFILECLI_URL=<pyroscope_server_url>
export PROFILECLI_USERNAME=<username>
export PROFILECLI_PASSWORD=<password>
profilecli query series --query='{<label_name>="<label_value>"}'
Example command:
export PROFILECLI_URL=https://profiles-prod-001.grafana.net
export PROFILECLI_USERNAME=my_username
export PROFILECLI_PASSWORD=my_password
profilecli query series --query='{service_name="my_application_name"}'
Example command with label filtering and default table output:
profilecli query series \
--query='{service_name="my_application_name"}' \
--label-names=__profile_type__ \
--label-names=service_name
Example table output (default):
+---------------------------------------------+---------------------+
| PROFILE TYPE | SERVICE NAME |
+---------------------------------------------+---------------------+
| memory:inuse_objects:count:space:bytes | my_application_name |
| process_cpu:cpu:nanoseconds:cpu:nanoseconds | my_application_name |
+---------------------------------------------+---------------------+
Columns are sorted alphabetically by their raw label name. Column headers are derived from label names with underscores replaced by spaces and converted to uppercase (for example, __profile_type__ becomes PROFILE TYPE).
Example command using --output=json:
profilecli query series \
--query='{service_name="my_application_name"}' \
--output=json
Example JSON output:
{
"from": "2026-03-12T08:54:07.667114Z",
"to": "2026-03-12T09:54:07.667114Z",
"series": [
{
"__name__": "memory",
"__period_type__": "space",
"__period_unit__": "bytes",
"__profile_type__": "memory:inuse_objects:count:space:bytes",
"__service_name__": "my_application_name",
"__type__": "inuse_objects",
"__unit__": "count",
"cluster": "eu-west-1",
"service_name": "my_application_name"
}
]
}
You can use the profilecli query profile command to retrieve a merged (aggregated) profile from a Pyroscope server.
The command merges all samples found in the profile store for the specified query and time range.
By default it looks for samples within the last hour, though this can be controlled with the --from and --to flags. The source data can be narrowed down with the --query flag in the same way as with the series command.
This command is useful when you want to inspect merged profile data directly, save it for offline analysis, or compare profile windows in scripts and CI jobs.
Specify optional flags.
--query flag, for example, --query='{service_name="my_application_name"}'.--from and --to flags, for example, --from="now-3h" --to="now".--profile-type flag. The available profile types are listed in the output of the profilecli query series command.--output=pprof=./result.pprof to save the merged profile as a pprof file.--function-names-only for faster responses when you don't need full mapping and line details.Construct and execute the query profile command.
Here's a basic command template:
export PROFILECLI_URL=<pyroscope_server_url>
export PROFILECLI_USERNAME=<username>
export PROFILECLI_PASSWORD=<password>
profilecli query profile \
--profile-type=<profile_type> \
--query='{<label_name>="<label_value>"}' \
--from="<from>" --to="<to>"
Example command:
export PROFILECLI_URL=https://profiles-prod-001.grafana.net
export PROFILECLI_USERNAME=my_username
export PROFILECLI_PASSWORD=my_password
profilecli query profile \
--profile-type=memory:inuse_space:bytes:space:bytes \
--query='{service_name="my_application_name"}' \
--from="now-1h" --to="now"
Example command saving pprof output:
profilecli query profile \
--profile-type=process_cpu:cpu:nanoseconds:cpu:nanoseconds \
--query='{service_name="checkout"}' \
--from="now-30m" --to="now" \
--output=pprof=./checkout-cpu.pprof
Example output:
level=info msg="query aggregated profile from profile store" url=http://localhost:4040 from=2023-12-11T13:38:33.115683-04:00 to=2023-12-11T14:38:33.115684-04:00 query={} type=memory:inuse_space:bytes:space:bytes
PeriodType: space bytes
Period: 524288
Time: 2023-12-11 13:59:59.999 -0400 AST
Duration: 59m5
Samples:
inuse_space/bytes[dflt]
115366240: 107 13 14 15 16 17 1 2 3
...
You can use the profilecli query go-pgo command to retrieve an aggregated profile from a Pyroscope server for use with Go PGO.
Profiles retrieved with profilecli query profile include all samples found in the profile store, resulting in a large profile size.
The profile size may cause issues with network transfer and slow down the PGO process.
In contrast, profiles retrieved with profilecli query go-pgo include only the information used in Go PGO, making them significantly smaller and more efficient to handle.
By default, it looks for samples within the last hour, though this can be controlled with the --from and --to flags. The source data can be narrowed down with the --query flag in the same way as with the query command.
Specify optional flags.
--query flag, for example, --query='{service_name="my_application_name"}'.--from and --to flags, for example, --from="now-3h" --to="now".--profile-type flag. The available profile types are listed in the output of the profilecli query series command.--keep-locations flag. The default value is 5. The Go compiler does not use the full stack trace. Reducing the number helps to minimize the profile size.--aggregate-callees flag. By default, this option is enabled, meaning samples are aggregated based on the leaf location, disregarding the callee line number, which the Go compiler does not utilize. To disable aggregation, use the --no-aggregate-callees flag.Construct and execute the command.
Example command:
export PROFILECLI_URL=https://profiles-prod-001.grafana.net
export PROFILECLI_USERNAME=my_username
export PROFILECLI_PASSWORD=my_password
profilecli query go-pgo \
--query='{service_name="my_service"}' \
--from="now-1h" --to="now"
Example output:
level=info msg="querying pprof profile for Go PGO" url=https://localhost:4040 query="{service_name=\"my_service\"}" from=2024-06-20T12:32:20+08:00 to=2024-06-20T15:24:40+08:00 type=process_cpu:cpu:nanoseconds:cpu:nanoseconds output="pprof=default.pgo" keep-locations=5 aggregate-callees=true
# By default, the profile is saved to the current directory as `default.pgo`
The following commands are also useful in day-to-day operations.
Use profilecli query top to identify the biggest contributors in a time window.
This is useful when triaging spikes and you need a quick ranked view before doing deeper exploration.
profilecli query top \
--query='{__profile_type__="process_cpu:cpu:nanoseconds:cpu:nanoseconds"}' \
--label-names=service_name \
--top-n=10
Use profilecli query label-values-cardinality to find label keys with many values.
This is useful when troubleshooting query cost, dashboard slowness, or label design issues.
profilecli query label-values-cardinality \
--query='{service_name=~".+"}' \
--top-n=20
Use profilecli ready in scripts and CI checks to verify endpoint health before running upload or query automation.
profilecli ready --url=http://localhost:4040
Use profilecli recording-rules commands to list, create, get, and delete recording rules without leaving your terminal.
This is useful for GitOps-style workflows and automated rollout validation.
profilecli recording-rules list
Use profilecli source-code coverage to measure how well your .pyroscope.yaml mappings translate symbols from a pprof profile to source files.
This is useful when source links in the UI are missing or incomplete.
The command requires GitHub API access. Provide a token with --github-token or PROFILECLI_GITHUB_TOKEN.
export PROFILECLI_GITHUB_TOKEN=<github_token>
profilecli source-code coverage \
--profile=./cpu.pprof \
--config=./.pyroscope.yaml \
--output=detailed