Images not showing in an HTML file

On your machine the report is fine. Sent to someone else — attached to an email, dropped in Slack, uploaded to a server — every chart is a broken-image icon and the alt text is showing where the pictures were.

The HTML is intact. The images just never came with it.

Find the cause in 30 seconds

Open the page where it is broken, right-click a broken image and choose Open image in new tab (or check DevTools → Network, filter Img). The URL it tried tells you which of these it is:

The failed URL looks like Cause
file:///…/Downloads/img/chart.png Relative file that was never sent
file:///C:/Users/you/project/… Absolute path to your disk
file:///images/logo.png Root-relative path opened from disk
https://site/img/Chart.PNG → 404 Case mismatch on a Linux server
https://bucket.s3…?X-Amz-Expires=… → 403 Signed URL that has expired
http://… on an https:// page, blocked Mixed content
http://localhost:… Only exists on the machine that made it

1. The images are separate files, and only the HTML travelled

By far the most common. Notebook exports, test reporters, coverage tools and coding agents write the page and a folder of images:

report/
  index.html        ← you sent this
  img/
    latency.png     ← not this
    errors.png      ← or this

<img src="img/latency.png"> is a pointer to a neighbour. The recipient's copy has no neighbours.

Fixes, from quickest to sturdiest:

  • Embed the images in the file. Drop the whole folder into the HTML inliner and download one .html with every image, stylesheet and font inside it. For a single picture, the image to Base64 converter gives you the data: URI to paste in.
  • Send the folder as a zip. Works, but the recipient has to unzip it, keep the structure intact, and open the right file — and mail filters often strip zips containing .html.
  • Send a link instead of a file. Publish the folder and every relative path keeps resolving, because the assets are hosted next to the page.

2. An absolute path to your own disk

<img src="C:\Users\dana\project\out\chart.png" />
<img src="file:///Users/dana/project/out/chart.png" />

Some tools and copy-pastes write the full local path. It works for exactly one person. Replace it with a path relative to the HTML file (out/chart.png), then apply fix #1. Backslashes are a Windows-ism — use forward slashes in src, even on Windows.

3. A root-relative path, opened from disk

<img src="/static/logo.png" />

The leading / means the root of the site. Behind a web server that works. Double-clicked from a folder, the page is on file://, and the root is your drive — so the browser looks for /static/logo.png on the filesystem. Drop the leading slash, or open the folder through a local server rather than by double-clicking.

4. Letter case on a Linux server

Chart.PNG and chart.png are the same file on Windows and on macOS's default filesystem. On Linux, on S3 and on most static hosts they are two different names, and only one exists. Everything works locally, then 404s on deploy. Rename the files or the src so the case matches exactly — extension included.

5. An expired or private URL

The image is hosted, but behind a pre-signed link (X-Amz-Expires, se= on Azure, Expires= on GCS) that was valid for an hour when the report was generated. A week later it returns 403. The same happens with images in a private bucket, a logged-in dashboard, or a Google Drive "anyone with the link" file that isn't actually an image URL.

Either embed the image so it never depends on that URL again, or host it somewhere public and stable.

6. http:// images on an https:// page

Browsers upgrade or block plain-HTTP images on secure pages — see mixed content blocked. And anything on localhost was only ever reachable from the machine that generated it; see the localhost link doesn't work for others.

Embed or host?

Embed (data URI) Host next to the page
Works as an attachment Yes No — needs a link
File size ~33% bigger per image Unchanged
Caching Re-downloaded every visit Each image cached separately
Good for Charts, icons, a logo Photos, many large images

For a report with a handful of charts, embedding is the right call — the file stops being fragile. Past a few megabytes of images, a link is kinder to everyone's inbox; see HTML file too big to email.

Or send a link, not a file

Publish the report folder to Comma and send one URL. The images, stylesheets and scripts are uploaded alongside the page, so nothing goes missing; readers comment on the exact chart they mean; and a re-run replaces it as a new revision at the same link. Lock it to a password, an invite list or your email domain when it isn't public.

Try it

Inline a page into one file →

Related