# Share an HTML Coverage Report — Drop the Whole htmlcov Folder

Canonical: https://commareports.com/share-coverage-report
Published: 2026-08-18

> coverage.py and Istanbul write a folder of HTML nobody can open. Drag htmlcov/ into Comma and get one browsable link, anchored comments on uncovered lines, and a revision per run.

# Share an HTML coverage report

Coverage tooling produces the most obviously shareable artifact in the
build — a browsable, line-by-line map of what your tests actually touch —
and then hands you a **folder**. `htmlcov/index.html` plus a hundred
sibling pages and a stylesheet. You can't paste a folder into Slack. So it
gets zipped into CI artifacts, where it expires unread, and the team goes
back to arguing about a single percentage number in the build log.

The percentage is the least interesting thing in that folder.

## Drop the folder in

Comma takes HTML bundles, not just single files. Drag `htmlcov/` (or
`coverage/lcov-report/` from Istanbul, or a zip of either) into
[the app](https://commareports.com/):

- `index.html` becomes the **report body** — the page with the comment
  layer on it.
- Every other HTML page, the CSS, and the images are uploaded alongside it.
- Relative `src` and `href` references are rewritten to the uploaded
  assets, so the drill-down links from the summary table keep working.

The result is one URL that browses like the local report, opens in any
browser, and doesn't expire when the CI retention window closes.

## From CI, with one curl

For a pipeline, publish the summary page and PATCH the same report id on
every run so there is one stable URL per repo:

```bash
coverage html   # writes htmlcov/

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 htmlcov/index.html '{html: $html}')"
```

Use a [scoped token](/docs/api-tokens) with only `reports:write`. Each
push appends a revision at the same URL, so "did this PR move coverage,
and where?" is a [diff](/docs/ci) between two revisions rather than two
numbers in two build logs. The general pipeline pattern is written up in
[publish from CI](/docs/ci).

Supporting files go up as [assets](/docs/api) — 25 MB per file, 250 MB and
500 files per report. For a large monorepo, publish per-package reports
rather than one giant bundle; it's also how anyone actually reads them.

## Coverage numbers don't start conversations. Lines do.

"We're at 68%" is not a discussion. "This branch in
`billing/refunds.py` has never been executed by a test" is — and it's a
sentence that belongs *on that line*, not in a Slack thread three days
later.

Comma renders the coverage report with an [anchored comment
layer](/comment-on-html) on top. A reviewer highlights the uncovered
block and pins a thread to it: "this is the partial-refund path — worth a
test before the Q4 pricing change." The thread stays attached to that
report as revisions accumulate, so the next person to open the coverage
report sees the reasoning instead of rediscovering the gap.

For teams that review coverage on a cadence, a [routine](/features/routines)
can refresh the published report on a schedule so the link is never stale.

## What renders, what doesn't

- **Renders faithfully** — the summary table, per-file source listings,
  syntax highlighting, and the green/red line shading. All of it is CSS.
- **Inert** — coverage.py's keyboard shortcuts and the filter box, and
  Istanbul's sortable headers. Comma strips `<script>` on write as
  defense-in-depth on an endpoint that accepts arbitrary HTML.
- **Browsable** — the per-module pages, via the same relative links the
  index already uses.

Comment threads live on the report body. If a specific module is the one
under review, publish *that* page as the report and attach the rest.

## Try it

Comma is free — unlimited reports, unlimited commenters, unlimited
revision history. Run `coverage html`, drag the folder in, and send the
link to the person who keeps asking about the number.

**[Create your first report →](https://commareports.com/)**
