# Share a speedscope Profile — Without Asking Anyone to Install It

Canonical: https://commareports.com/share-speedscope-profile
Published: 2026-09-08

> speedscope keeps your profile local, which is great for privacy and terrible for review. Publish the viewer and the trace together to Comma for one URL that opens in any browser.

# Share a speedscope profile

speedscope has the best flame chart interaction of any of the free profile
viewers — the time-ordered view, the left-heavy view, the sandwich view for
"where is this function called from" — and it has a design decision that makes
sharing genuinely hard:

**it never uploads your profile.** speedscope.app is a static page that parses
the file in your browser. Nothing leaves the machine, which is the right call
for a production profile, and which means there is no URL to send anybody.

So the normal workflow is: attach `profile.json` to a message, and add a
paragraph explaining that the recipient should go to speedscope.app and drag
the file in. Most of them don't.

## Publish the viewer with the trace

speedscope ships as a static bundle. Publish that bundle as the report and put
the trace next to it:

```bash
# get the static build
npm pack speedscope && tar -xzf speedscope-*.tgz    # → package/dist/release/

# produce a trace in a format speedscope reads
py-spy record -f speedscope -o profile.speedscope.json --pid 12345
```

Drop the folder into [the app](https://commareports.com/):

- `index.html` becomes the **report body**.
- The viewer's JS/CSS and your trace JSON upload alongside it as assets, and
  their relative references are rewritten to the uploaded copies.
- Scripts run inside a sandboxed iframe (`allow-scripts`, no
  `allow-same-origin`), so the flame chart, the view switcher and the keyboard
  navigation all behave.

Append `#profileURL=` pointing at the uploaded trace, or simply upload a trace
named so the reader can open it from speedscope's file picker — the point is
that the viewer is already on screen when they follow the link.

## Which profilers this covers

speedscope reads more formats than most people realize, so this one report
shape works across languages:

| Source | Command |
| --- | --- |
| Python | `py-spy record -f speedscope -o out.json --pid <pid>` |
| Node.js | `node --cpu-prof app.js` → `*.cpuprofile` |
| Chrome / DevTools | Performance panel → Save profile |
| Go | `go tool pprof -raw` → `pprof-to-speedscope` |
| Linux perf | `perf script > out.perf` |
| Ruby | `stackprof --format=speedscope` |

That is the practical argument for standardizing on it: one viewer, one
publish step, whatever the runtime was.

## Keep one URL per investigation

PATCH the same report id as you re-profile, and the link you pasted into the
incident channel on the first capture is still the right link on the fifth:

```bash
curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html index.html \
        --arg t "Profile — checkout, after cache fix" '{title: $t, html: $html}')"
```

## What review adds

- **Anchored threads** on the frame under discussion — see
  [commenting on HTML](/comment-on-html).
- **Revisions**, so a sequence of captures reads as an investigation.
- **Access per report** — the trace carries real stack frames from a real
  process. Private, team or named-reviewer access is the right default here.
  See the [sharing model](/docs/sharing).

## Limits

- **Entry HTML: 5 MB.** Assets: 25 MB per file, 250 MB and 500 files total. The
  trace JSON is the file to watch — a long high-frequency capture is the one
  that gets big; shorten the window rather than downsampling the stacks.
- **60 requests/minute per token.**

## Try it

Comma is free — unlimited reports, unlimited commenters, unlimited revision
history.

**[Publish a profile →](https://commareports.com/)**

### Related

- [Share a flame graph](/share-flamegraph) · [Share a py-spy profile](/share-py-spy-profile)
- [Share an async-profiler report](/share-async-profiler-report) · [Share a profiling report](/share-profiling-report)
- [Share an HTML folder](/share-html-folder) · [Publish from CI](/docs/ci)
