# Share a TensorBoard Report — Training Curves Without a Port Forward

Canonical: https://commareports.com/share-tensorboard-report
Published: 2026-09-12

> TensorBoard runs on localhost:6006 and TensorBoard.dev is gone. Export the scalars to a self-contained HTML page and publish it to Comma so the training curves live at a URL anyone can open.

# Share a TensorBoard report

TensorBoard.dev was the answer to this question and it was switched off in
January 2024. What is left is `tensorboard --logdir runs/`, bound to
`localhost:6006`, on a machine that is usually not the one you are sitting at.

So the ritual is an SSH tunnel, or a screenshot of a loss curve cropped just
tightly enough to lose the axis.

## Export the scalars to one HTML file

```python
import plotly.graph_objects as go
from tensorboard.backend.event_processing.event_accumulator import EventAccumulator

acc = EventAccumulator("runs/exp-42")
acc.Reload()

fig = go.Figure()
for tag in ("loss/train", "loss/val"):
    events = acc.Scalars(tag)
    fig.add_trace(go.Scatter(
        x=[e.step for e in events],
        y=[e.value for e in events],
        mode="lines",
        name=tag,
    ))

fig.update_layout(title="exp-42", xaxis_title="step", yaxis_title="loss")
fig.write_html("tensorboard.html", include_plotlyjs="inline")
```

`include_plotlyjs="inline"` is the part people skip. The default pulls
plotly.js from a CDN, and a report whose chart library is a remote script is a
report that renders blank the day the CDN is blocked — see
[self-contained HTML](/glossary/self-contained-html).

Drag the file into [the app](https://commareports.com/), or publish from the
training job:

```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 tensorboard.html \
        --arg title "exp-42 — step $STEP" '{title: $title, html: $html}')"
```

Call it every N epochs from a callback and the URL becomes a live-ish training
dashboard that costs you nothing to operate.

## Why this beats a screenshot in the run channel

- **Anchored threads** — "val loss diverges at step 8k, did the LR schedule
  change?" sits on the chart. See [commenting on HTML](/comment-on-html).
- **Revisions** — one report id per experiment; every publish is kept, so the
  URL is a history of the run rather than its last frame.
- **Access per report** — private, team-only, or domain-gated. See the
  [sharing model](/docs/sharing).

## Limits

- **Entry HTML: 5 MB.** Inlined plotly.js is about 3 MB of that, so downsample
  long runs (every Nth step) rather than plotting every point.
- **Assets: 25 MB per file, 250 MB and 500 files per report.**
- **60 requests/minute per token.**

## Try it

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

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

### Related

- [Share a W&B report](/share-wandb-report) · [Share an MLflow report](/share-mlflow-report)
- [Share a Plotly HTML chart](/share-plotly-html) · [Share an Optuna dashboard](/share-optuna-dashboard)
- [Scheduled HTML reports](/features/routines/scheduled-html-reports) · [For data scientists](/for/data-scientists)
