Embed Images in a Single HTML File
You need one .html file that still shows its images — offline on a USB stick, forwarded as an email attachment, pasted into a CMS field that refuses uploads, or opened in an air-gapped browser. External src="https://…" links fail the moment the file leaves the network that hosted those assets. The fix is not another CDN. The fix is to put the image bytes inside the HTML as Base64 data URIs.
Encode the image locally with the Image to Base64 converter, paste the string into the template below, and ship a single file.
When a single file is the real constraint
People reach for Base64 HTML when the workflow forbids a second file:
- Offline / air-gapped demos — sales decks, factory-floor kiosks, or review builds that must open from
file://with no HTTP server. - Emailable HTML packages — a stakeholder gets one attachment, not a zip of assets that mail clients often strip.
- CMS / CRM paste-only fields — the editor accepts HTML but blocks media libraries or remote URLs.
- Disposable prototypes — a one-pager you can drop in Slack/Discord as a file without hosting screenshots.
If you can host images on HTTPS and control the page for months, keep normal files. Single-file Base64 is for the cases where the delivery unit must be one document.
How Base64 removes the asset dependency
A data URI is a URL that is the file:
<img src="data:image/png;base64,iVBORw0KGgo..." alt="Logo">
The browser does not fetch anything. The MIME type and the Base64 payload travel with the HTML. Relative paths like ./logo.png die as soon as you move the HTML alone; a data URI does not.
Trade-off: Base64 expands payload by about 33%, and inlined images cannot be cached separately. Keep icons, logos, and small diagrams inline; leave large photos as external files when the environment allows.
Step-by-step — encode, paste, ship one file
- Shrink first if needed. Large PNGs blow up HTML fast. Run them through Compress PNG to Base64 or check size with the Base64 image size calculator before you commit.
- Encode in the browser. Open Image to Base64 (or the Data URI Generator), drop the file, and copy the full data URI — the string that starts with
data:image/…;base64,. - Paste into
srcor CSSurl(). Use the template in the next section. Do not wrap the data URI in quotes incorrectly, and do not prefix it withhttp://. - Ship the one file. Open it from disk, attach it, or paste the HTML. No
images/folder travels with it.
For a site favicon that should also live inside the same file, generate the <link rel="icon"> tag with Base64 Favicon.
Copy-paste template (img + CSS background)
Replace PASTE_DATA_URI_HERE with the full data URI from the converter. The 1×1 PNG below is only a structural placeholder so the template validates before you swap real assets.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Self-contained report</title>
<style>
body { font-family: system-ui, sans-serif; margin: 2rem; color: #111; }
.hero {
width: 320px;
height: 120px;
background-image: url("PASTE_DATA_URI_HERE");
background-size: contain;
background-repeat: no-repeat;
border: 1px solid #ddd;
}
.logo { max-width: 160px; height: auto; }
</style>
<!-- Optional inline favicon: paste from /base64-favicon -->
<!-- <link rel="icon" href="data:image/png;base64,..." type="image/png"> -->
</head>
<body>
<h1>Quarterly snapshot</h1>
<p>This file has no external image requests.</p>
<!-- Inline image -->
<img
class="logo"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="
alt="1x1 placeholder — replace with your data URI">
<!-- CSS background using the same pattern -->
<div class="hero" role="img" aria-label="Chart"></div>
<p>Generated for offline delivery. Encode real assets at
https://image2base64.com/</p>
</body>
</html>
Need to pull a data URI back out of an existing stylesheet later? Use Extract Base64 image from CSS.
Size, caching, and when not to inline
| Situation | Prefer |
|---|---|
| Logo ≤ ~20–40 KB after encode | Inline data URI |
| Full-bleed photo / screenshot gallery | Hosted HTTPS files |
| Markdown README on GitHub | Relative path — GitHub strips data: URIs; see Embed Base64 image in Markdown |
| API JSON payload | Raw or prefixed Base64 per API docs — Image to Base64 for API |
If the HTML must stay under a mail-gateway size limit, compress first and favor SVG/PNG icons over camera JPEGs.
Troubleshooting
Image shows as a broken icon. The data URI was truncated on copy, the data: prefix was dropped, or a line break was inserted mid-string. Re-copy from the converter in one shot.
Works in the browser preview, fails after CMS save. Some editors sanitize data: URLs. Confirm the field allows them; if not, the constraint has moved — you need a host that permits uploads, not a bigger Base64 string.
File opens fine locally but looks empty in email. Many clients block or strip CSS backgrounds and sometimes <img data:>. Treat email as a separate constraint — see the Outlook and Gmail signature pages on this site.
Frequently asked questions
Does a single-file HTML with Base64 images work offline?
Yes. Once the data URIs are in the file, no network is required to render those images.
Is Base64 secure?
Encoding is not encryption. Anyone with the HTML can decode the image. Do not inline secrets.
Should every image be inlined?
No. Inline the assets that must travel with the document; leave heavy, cacheable media external when you can.
How do I encode an image for a single HTML file?
Open the Image to Base64 converter, drop the file, and copy the full data URI. Paste it into an img src or a CSS url().
Related tools
- Image to Base64 — encode any image locally
- Data URI Generator — build
data:URLs for paste - Base64 Favicon — inline
rel=icon - How to convert image to Base64 — method overview
- Embed Base64 image in Markdown — when the host is Markdown instead of HTML