# Share a Flame Graph — A Link That Keeps the Zoom and Search

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

> A flame graph SVG is interactive until you send it. GitHub strips its scripts, Slack flattens it to a preview. Publish it to Comma for a URL where click-to-zoom and Ctrl-F still work.

# Share a flame graph

A flame graph is one of the few artifacts where the interaction *is* the
finding. The picture tells you something is wide. Clicking into it — zooming a
frame, hitting Ctrl-F to highlight every `malloc` in the stack — is how you
work out *why*.

Which is why sending one is so consistently disappointing. `flamegraph.pl`
writes a self-contained SVG with the whole interaction layer in an embedded
`<script>` block, and almost every place you'd naturally drop it removes that
script:

- **GitHub** sanitizes SVG on render and strips `<script>`. Zoom and search die;
  the image survives.
- **Slack** shows a flattened preview. Everything below the fold is gone.
- **Confluence and Notion** treat it as an image attachment.
- **Email** is a coin flip between an inline flat render and an attachment the
  reader has to save and open by hand.

So the profile gets screenshotted, and the person reading it has to trust your
crop.

## Publish the SVG

Whichever tool produced it, the output is one file:

```bash
# perf, the original path
perf record -F 99 -g -- ./myserver
perf script | stackcollapse-perf.pl | flamegraph.pl > flame.svg

# Rust
cargo flamegraph --bin myserver          # → flamegraph.svg

# Python
py-spy record -o flame.svg --pid 12345
```

Drag that SVG into [the app](https://commareports.com/), or send it to the API:

```bash
curl -fsS -X POST "https://commareports.com/api/v1/reports" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile svg flame.svg \
        --arg t "CPU profile — checkout path" '{title: $t, html: $svg}')"
```

Report content renders with scripts enabled inside a sandboxed iframe
(`allow-scripts`, no `allow-same-origin`), which is exactly the capability
GitHub's sanitizer removes. Click-to-zoom, the reset-zoom link, the search box
and the frame tooltips all behave at the URL.

## Publish the differential too

The single most useful flame graph is usually the *second* one. If you have a
before and an after:

```bash
stackcollapse-perf.pl < before.perf > before.folded
stackcollapse-perf.pl < after.perf  > after.folded
difffolded.pl before.folded after.folded | flamegraph.pl > diff.svg
```

PATCH both onto the same report id and you get a revision history rather than
two orphaned files named `flame.svg` and `flame(2).svg`:

```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 svg diff.svg \
        --arg t "CPU profile — after batching" '{title: $t, html: $svg}')"
```

One URL per service, a revision per investigation. "Is this the same regression
as March?" becomes a diff instead of a Slack search.

## What review adds

Profiles are read by people who did not run them, which is where they usually
stall:

- **Anchored threads** on the wide frame, so the diagnosis lives with the
  evidence — see [commenting on HTML](/comment-on-html).
- **Revisions**, so the before/after pair is one artifact.
- **Access per report** — private, team, domain-gated, or named reviewers.
  Stack traces leak internal module and path names, so this is worth setting
  deliberately. See the [sharing model](/docs/sharing).

## Limits

- **Entry HTML/SVG: 5 MB.** A deep profile with hundreds of thousands of unique
  stacks can approach this — sample at a lower frequency (`-F 49`) or narrow the
  recording window rather than trimming the graph.
- **60 requests/minute per token.**

## Try it

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

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

### Related

- [Share a py-spy profile](/share-py-spy-profile) · [Share an async-profiler report](/share-async-profiler-report)
- [Share a speedscope profile](/share-speedscope-profile) · [Share a profiling report](/share-profiling-report)
- [Share a benchmark report](/share-benchmark-report) · [Publish from CI](/docs/ci)
