Image Tools

Image Base64

Convert images to and from Base64 Data URLs.

Choose image
💡 Usage
Data URL format:data:image/png;base64,iVBORw0KGgoAAAANS...

Use in HTML img src or CSS background-image

Base64 plain text:iVBORw0KGgoAAAANS...

Only the Base64 string—add the prefix manually when needed

What is Image to Base64?

Image to Base64 converter encodes images as Base64 strings for embedding directly in HTML, CSS, or JSON.

Features

  • Drag and drop support
  • Multiple format support
  • Data URI output
  • Copy to clipboard

Use Cases

  • Inline images in HTML/CSS
  • Email templates
  • Reducing HTTP requests

Tips

  • Best for small images (< 100KB)
  • Large images increase page size
  • All processing is done locally

Reads a local image file into a Data URL or a bare Base64 string, and turns either form back into a previewable, downloadable image. Useful for inlining small icons in HTML or CSS, shipping images inside JSON payloads, or recovering a file from a Base64 blob pasted out of a log.

The encoder reads bytes, not pixels

Encoding is one FileReader.readAsDataURL() call on the selected file, so the payload is a character-for-character re-encoding of the bytes on disk: no canvas is involved, and no resampling, recompression or metadata stripping happens. A 300 KB PNG produces a payload of about 400,000 characters, and the preview shows the very file you uploaded. The media type in the prefix is not sniffed from the bytes; it is file.type, which the browser maps from the file extension through the operating system. Rename photo.jpg to photo.png and you get data:image/png;base64, in front of JPEG bytes, which browsers still render but strict consumers reject: object-storage content-type checks, toBlob re-exports and upload validators key off the declared type.

Why the output has exactly that shape

A Data URL is data: plus media type plus ;base64, plus payload, with no whitespace between segments. The prefix costs 22 characters for PNG and 26 for SVG, whose subtype carries a plus sign. The payload runs at 4 characters per 3 bytes rounded up, so a 1000-byte icon becomes 1336 characters (133.6% of its size) while larger files converge on 133.3%. Divisibility by three decides the tail: 69 bytes is exactly 23 groups and ends in plain characters, whereas 68 bytes needs ==. The eight-byte PNG signature encodes to iVBORw0KGgo=, and because a 13-byte IHDR chunk always follows it, every PNG payload opens with iVBORw0KGgoAAAANSUhE; JPEG opens with /9j/, GIF with R0lGOD, WebP with UklGR. Those first characters are the cheapest way to test whether a declared MIME type is plausible.

Assumptions made while decoding

Decode mode takes either a complete Data URL or bare Base64. Bare input gets a hardcoded image/png prefix, then one shape check requires something of the form data:image/<subtype>;base64,. No byte-level test follows: validation is simply assigning the string to an Image object and waiting for its load event, so the browser image decoder is the judge. Well-formed Base64 of non-image bytes therefore fails silently, with no preview and no diagnostic text. Downloading decodes with atob into a Blob typed image/<subtype> and names the file decoded-image.<subtype>, so SVG yields decoded-image.svg+xml, an extension no OS recognises, and a JPEG pasted without any prefix is saved as decoded-image.png while still holding JPEG bytes.

Worked example

Encoding a 69-byte 1x1 PNG

Input
pixel.png : 1x1 px, 8-bit RGB, solid red (#ff0000), 69 bytes on disk
Output
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR4nGP4z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC

69 bytes divides evenly into 23 three-byte groups, so the payload is 92 characters with no = padding and the Data URL totals 114 characters once the 22-character prefix is added. Switching to base64-only returns those same 92 characters with the prefix cut off, and the preview is identical because neither mode alters the encoded bytes.

Limits and pitfalls

  • The component defines no file-size ceiling; the real limits are browser memory for the string and the textarea that renders it, so a multi-megabyte photo becomes a multi-megabyte text node.
  • Only files whose file.type starts with image/ are accepted, so a real image with an unusual or unregistered extension is refused before any encoding starts.
  • The output is one unbroken line: the payload is never wrapped at 76 characters, so it has to be refolded before entering MIME or email contexts that enforce line limits.
  • Bare Base64 pasted for decoding is always labelled PNG, so a JPEG or WebP payload downloaded from that mode carries the wrong extension.
  • Because the prefix follows the extension rather than the content, verifying a file real format means inspecting the leading Base64 characters instead of trusting data:image/....

Related tools

When it goes wrong

A Data URL exported from a design tool is refused as an invalid Base64 format, although the same string renders when opened in a tab.

CauseThe shape check is /^data:image\/[^;]+;base64,/, which expects ;base64, immediately after the subtype. A charset=utf-8 parameter sitting between them, as SVG exporters often add, leaves a semicolon where that literal is required, so the string is rejected before any decoder runs.

FixDelete the parameter so the header reads data:image/svg+xml;base64, and decode again. Do not fall back to pasting the bare payload for an SVG: the page would label those bytes PNG, and the download would be named decoded-image.png while holding SVG text.

The string copied in Base64-only mode shows a broken image when pasted into a src attribute or a CSS url().

CauseBase64-only mode cuts everything before the first comma, and that includes the header — 22 characters for data:image/png;base64,. A URL slot needs the header to say what the bytes are; a bare payload is not a URL at all, however valid the encoding.

FixCopy again in Data URL mode, or put the header back in front of the payload yourself, keeping the subtype truthful: for PNG that header is 22 characters of text, and strict consumers such as content-type validators reject one that contradicts the bytes.

After a successful decode there is no way to lift the bare payload out — the Data URL / Base64-only switch is gone.

CauseThat switch is rendered inside the encode section header only, so it disappears the moment the mode changes. Decode mode offers a textarea, a decode button and, once an image loads, a download button; the string keeps whichever header it arrived with.

FixSwitch back to encode, reload the same file and pick Base64-only, or delete the characters up to and including the first comma by hand. Decoding never rewrites the header, so the output format is decided by the input.

Right after encoding, switching to decode finds the textarea already full, as if the clipboard had been read without asking.

CauseBoth modes share one base64String ref, and the mode radio only changes which section renders — nothing clears the value. The encode output happens to be exactly the input the decode branch wants.

FixPress the decode button to round-trip the file you just encoded, or press the clear button in the input header, which resets the string, the preview and the file input together.

A phone screenshot leaves the output pane with millions of characters, and the tab starts to stutter while scrolling it.

CauseA single FileReader.readAsDataURL call turns the whole file into one string that is held for the preview and mirrored into a read-only textarea, and the length is 4 × ⌈n / 3⌉: 3,200,000 bytes becomes 4,266,668 characters, with the final group padded because 3,200,000 leaves 2 bytes over. This page declares no size limit, so nothing stops the attempt.

FixCompress or downscale first with Image Compressor, or convert to WebP with Image Converter, then encode the smaller file. If the image is only meant to be displayed, reference it as a file instead of inlining it.

Inline it now, script it later, or leave it to the bundler

The situationThis pageChoose instead
One or two icons have to ride along inside markupDrop the file in encode mode and copy the Data URL: 3,024 bytes yields a 4,032-character payload — every 3 bytes become 4 characters, and 3,024 divides cleanly — so the box counts 4,054 with the PNG header included. Worth the manual step for a one-off asset, where previewing before pasting is the point.For a set that ships with the app, let the build do it: Vite rewrites any asset below assetsInlineLimit — 4,096 bytes by default — into a Data URL, and leaves larger ones as separate files. Take that route once the icons are versioned and regenerated on every deploy, so nobody has to recopy them by hand.
A Base64 blob has to become a file on disk againDecode mode shows the image first, then saves it as decoded-image.<subtype>; a payload pasted without any header is assumed to be PNG, so the filename can disagree with the bytes. Pick it when you want to look before naming.On a shell, base64 --decode < payload.txt > out.jpeg writes the bytes unchanged and you choose the name, and the string never sits inside a textarea. Pick the shell when the format is already known and the payload runs to megabytes.
The bytes are a font, a wasm module or a PDFNot reachable: the picker drops anything whose file.type does not start with image/ and clears the input, and the decode side only ever judges a string by whether an Image loads it.Use the File to Base64 tool on this site, which accepts any file and refuses only beyond 50 MB, or stay in the terminal with base64 < font.woff2, which never asks for a media type. Pick those when the payload was never an image.
The source image is already several megabytesNothing is compressed or resampled, so text length is 4 × ⌈n / 3⌉: 4,194,304 bytes of JPEG arrives as 5,592,408 characters in a single node, next to the decoded preview. Use it only for images you had decided to inline anyway.Shrink first — Image Compressor for quality, Image Converter for WebP — then encode the smaller result. That order matters whenever the string ends up in HTML or CSS, where it is downloaded with the document and cannot be cached on its own.
You only need the pixel size or the real formatThe page reports a character count, plus a KB figure that shows only while the original file is still attached in encode mode; it never reports dimensions. Pick it when the number you want is the encoded length that will land in your file.Image Info Viewer reads the header and answers dimensions, format and alpha channel without encoding anything. Pick it while you are still deciding whether to inline, since pixel size is what the budget is actually about.

Frequently Asked Questions

When should an image be inlined as Base64?
Small assets under roughly 2–3 KB: icons, logos, loading placeholders — it saves a request and caches with the document. Not for content images or large files: +33% size, no independent caching, CSS parsing bloat. Rule of thumb: if it would be in a sprite, consider inlining.
Does inlining images hurt page performance?
Both ways: fewer requests, but no caching — every referencing page re-downloads the whole CSS/HTML — plus parsing bloat. Lighthouse flags large Base64 segments. The middle path: inline SVG for small icons, files with lazy-loading for photos.
Why does my converted image "not open"?
Usually a usage mismatch: saving raw Base64 as a .jpg file (no binary header), or a Data URI whose MIME type contradicts the real format (png labeled jpeg). This tool attaches the correct MIME prefix on output and detects the type when decoding back.

Content reviewed: