# You Sent a localhost Link — Why It Can Never Work, and the Two Real Options

Canonical: https://commareports.com/fix/localhost-link-doesnt-work-for-others
Published: 2026-09-07

> http://localhost:8080 resolves to the recipient's own machine, so the link is guaranteed to fail. Why tunnels are the wrong tool for a report, and the one-step alternative.

# `http://localhost:8080` will never open for them

You started a local server so the report would render, copied the
address out of the URL bar, and pasted it into the thread. They reply:
`This site can't be reached`.

## The name means "your own machine"

`localhost` resolves to `127.0.0.1` — the loopback address, defined to
mean _the computer doing the resolving_. When your colleague opens the
link, their browser dials **their** port 8080, finds nothing, and gives
up. The same is true of `0.0.0.0`, `127.0.0.1`, and anything under
`*.localhost`.

There is no firewall rule, VPN setting or port forward that fixes this,
because nothing is broken. The link is an instruction to look in the
wrong place.

## The things people try next

**Send the LAN IP** (`http://192.168.1.34:8080`). Works, sometimes, for
a colleague on the same office network — provided the server is bound to
`0.0.0.0` and not just loopback, and provided the host firewall permits
inbound connections on that port. It fails for anyone remote, breaks
when your DHCP lease changes, and is a support conversation every time.

**Open a tunnel** — ngrok, Cloudflare Tunnel, `ssh -R`, VS Code port
forwarding. These genuinely work, and they are the right tool for a
_live_ thing: debugging a webhook, demoing an app mid-development,
letting a client click through a running prototype.

They are the wrong tool for a report, because:

- The URL dies when your laptop sleeps, and you find out via a message
  saying the link is broken.
- Free tiers hand out a new random hostname each session, so the link in
  yesterday's thread is already dead.
- You are exposing a process on your machine to the public internet in
  order to deliver a static document.
- There is nowhere for the reader's comment to live.

Fuller comparison in [ngrok alternatives](/alternatives/ngrok-alternatives).

## Why you started the server at all

Usually because double-clicking the file didn't work. That is worth
naming, because it points at the actual fix:

Reports that load their results over XHR — [Allure](/fix/allure-report-blank-page),
[Playwright](/fix/playwright-report-blank), most coverage UIs — render
blank from `file://` because a local file has an opaque origin and
same-origin rules block the fetches. `python -m http.server` gives them
a real origin, so they work.

But so does any HTTPS origin. The server was never the requirement —
**`http://` was**. Publishing the report satisfies it permanently
instead of for as long as your terminal stays open.

## Publish it instead

Drag the report directory (or a zip of it) into the app, or POST the
HTML from the script that generated it:

```bash
curl -sS -X POST https://commareports.com/api/v1/reports \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data @<(jq -Rs '{title: "Coverage", html: .}' htmlcov/index.html)
```

What you get: a URL that resolves from anyone's machine, assets uploaded
alongside the entry file with their relative references rewritten,
interactivity preserved inside a sandboxed iframe, per-report access
(private, invited, link, public), and a comment thread anchored to the
paragraph someone has a question about
([comment on HTML](/comment-on-html)).

Nothing has to stay running. Close the laptop.

## Try it

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

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

### Related

- [Serve an HTML file locally](/serve-html-file-locally)
- [ngrok alternatives](/alternatives/ngrok-alternatives)
- [Host an HTML file](/host-html-file) · [Share an HTML folder](/share-html-folder)
- [My HTML report lost its CSS](/html-report-broken-css)
