A Base64 image that refuses to display is almost never broken encoding. The bytes are usually fine — what breaks is the wrapper around them: a wrong MIME type in the data URI, a syntax slip in data:…;base64,, padding that a CMS quietly stripped, a URL-safe alphabet pasted into a strict standard decoder, or a string that got truncated in a database column. Work through these six fixes in order and you will find the fault in minutes, because each one has a telltale symptom.
| Symptom | Most likely cause | Check first |
|---|---|---|
| Broken-image icon everywhere the image appears | Wrong MIME type in the data URI | Does the data:image/… type match the actual file? |
| Works in HTML, breaks inside CSS (or vice versa) | Data URI syntax or quoting problem | Look for a missing ;base64,, stray whitespace, or unescaped quotes |
| Decoder says "invalid" but the string looks right | Stripped padding or URL-safe alphabet in a standard decoder | Check the ending for = and the alphabet for - / _ |
| Decodes to garbage or fails after storage | Case changed in transit (lowercased by a tool or database) | Compare the stored string with the original, character by character |
| Partial image, or the bottom half is grey | Truncated string — a field or column cut it off | Check the string length is a multiple of 4 and the field size |
| Shows in Chrome, missing in email clients or old browsers | Client doesn't support data URIs, or the string exceeds a limit | Test the same markup in the failing client with a hosted image |
Fix 1: Match the MIME type to the actual file
The single most common cause. A data URI starts with a declared media type — data:image/png;base64,… — and the browser trusts that declaration. If the bytes are actually a JPEG but the URI says image/png, the browser hands PNG bytes to the JPEG decoder, which fails, and you get the broken-image icon even though the Base64 itself is perfect.
The telltale: the beginning of the encoded string. Base64 preserves the file's magic bytes in recognizable prefixes. RFC 4648, the Base64 specification, defines the encoding, but the magic prefixes are a property of the image formats: a string starting with iVBORw0KGgo is a PNG, and one starting with /9j/ is a JPEG. If your data URI says image/png but the string starts with /9j/, you have found your bug — change the declared type to image/jpeg.
This happens most often when a converter was told the wrong input type, or when someone copies a data URI and edits the filename without updating the declaration. Re-encode from the original file with the correct type using an image-to-Base64 converter and the problem disappears.
Fix 2: Repair the data URI syntax
The data URI scheme has exactly one legal shape for this job, documented in MDN's data URL reference: data:[<mediatype>][;base64],<data>. Every piece matters, and the failures are silent:
- Missing
;base64. Without it, the browser reads the payload as URL-encoded text, not Base64. The image silently fails. - Stray whitespace or line breaks. Many encoders wrap output at 76 characters (the email convention). Pasted into HTML or CSS, those line breaks can break the URI. Strip all whitespace from the encoded string before embedding.
- Quote collisions in CSS. A data URI inside
url("…")is fine, but a stray double quote inside the payload — or mixing quote styles when the string itself contains one — terminates the URL early. Use single quotes for theurl()wrapper if the payload contains double quotes, or escape them. - A missing comma. The comma between the mediatype section and the data is mandatory.
data:image/png;base64iVBOR…(no comma) is not a data URI at all.
When in doubt, paste the full src value into a validator or a fresh HTML file with nothing else in it. If it renders there, the encoding was never the problem — something around it was.
Fix 3: Check the padding and the alphabet variant
Base64 output ends with zero, one, or two = characters as padding, and the standard alphabet uses + and /. Two corruptions are common here:
Stripped padding. Content management systems, URL routers, and some JSON serializers strip trailing = characters, treating them as insignificant. Many decoders tolerate missing padding; strict ones reject the string outright. If your string's length is not a multiple of 4, padding was lost — restore the = characters (one = if the length mod 4 is 3, two if it is 2) and try again.
URL-safe alphabet in a standard decoder. The URL-safe variant swaps +→- and /→_ and usually drops padding. Paste a URL-safe string into a decoder that expects the standard alphabet and it fails on the first - or _. The reverse is equally true. Convert the alphabet back, or use a Base64 encoder/decoder that accepts both variants instead of guessing which one you have.
Fix 4: Look for case corruption in transit
Base64 is case-sensitive — uppercase and lowercase letters are different values. Anything in the pipeline that normalizes case destroys the data: a database column with a case-insensitive collation (MySQL's default, for example), a slug generator, a URL lowercaser, or a well-meaning "sanitize" function.
The telltale: the string decodes to garbage bytes, or fails entirely, even though it decoded fine before it was stored. Compare the stored value against the original character by character — even a single flipped case corrupts the output from that point on. The fix is structural: store Base64 in a binary-safe column (a BLOB, or a TEXT column with a binary/case-sensitive collation), and never run it through case-normalizing helpers. For the full picture of why case matters at the bit level, see how Base64 encoding actually works.
Fix 5: Check for truncation
A data URI for even a small image is thousands of characters long, and plenty of storage layers silently cut strings short: a VARCHAR(255) column, a CMS custom field with a character limit, a form input with maxlength, or a log pipeline that truncates long values. The result decodes to a partial image — often the top renders and the bottom is grey or missing — or fails outright.
Two quick checks: the encoded length should be a multiple of 4 (a truncated string usually isn't), and re-encoding the original file should produce a longer string than what you have stored. If the stored value is shorter, raise the field limit or move the payload to a TEXT/MEDIUMTEXT column and re-save the complete string.
Fix 6: Confirm the client actually supports data URIs
Sometimes the image, the encoding, and the markup are all correct — and the client still shows nothing. Email clients are the classic case: several strip or refuse data URIs for images, and some webmail providers proxy and rewrite them. Older browsers and some in-app webviews have size limits on data URIs that a large image exceeds silently.
The diagnostic is simple: take the exact same image, host it as a normal file, and reference it with a regular URL in the failing client. If the hosted version renders and the data URI doesn't, you have a client-support problem, not an encoding problem — and the fix is to stop inlining for that channel. This is also where the size tradeoff bites: Base64 inflates every image by about a third and the inlined copy can't be cached separately from the page, so large images should stay as files regardless. Our Base64 guide's section on when a data URI actually pays off walks through that decision with numbers.
Picking the right image-to-Base64 converter
If you are going to inline images regularly, the converter you use matters more than it looks. The best image-to-Base64 converters run entirely in your browser (your image never uploads anywhere), show you the encoded size before you commit so you can judge the ~33% inflation, and hand you the output in the exact format you need — a ready-to-paste data URI, a CSS url() rule, or a plain encoded string. Compare a few free Base64 encoding tools on those three criteria and keep the one that shows its work.
Frequently asked questions
Why is my Base64 image showing as a broken icon?
In most cases the declared MIME type doesn't match the actual file (a JPEG declared as PNG), the data URI syntax is broken (missing ;base64, or the comma), or the string was damaged in transit — stripped padding, a URL-safe alphabet in a standard decoder, lowercased characters, or truncation. Work through the six fixes above in order; the symptom table at the top tells you where to start.
How can I tell what image format a Base64 string holds?
Read the first few characters: iVBORw0KGgo means PNG, /9j/ means JPEG, R0lGOD means GIF, and UklGR means WebP. These prefixes are the file's magic bytes surviving the encoding, and they are the fastest way to catch a MIME-type mismatch.
Does whitespace break a Base64 data URI?
It can. The encoding itself ignores no whitespace — decoders vary, and inside a CSS url() or an HTML attribute, line breaks pasted from an email-style encoder (76-character wrapping) may break parsing. Strip all whitespace from the string before embedding.
Can a database corrupt a Base64 string?
Yes, in two ways: truncation, when the column is too short for the string, and case corruption, when a case-insensitive collation or a normalizing function changes letter case. Store Base64 in a binary-safe or case-sensitive text column sized for the payload.
What is the best free image-to-Base64 converter?
The best ones convert entirely in your browser with no upload, display the encoded size so you can weigh the ~33% inflation before inlining, and output a ready-to-paste data URI, CSS rule, or <img> tag. Judge any free converter on those three points rather than on its homepage claims.
Should large images be converted to Base64?
Usually not. The encoding adds roughly a third to the file size, and an inlined image can't be cached independently of the page containing it. Data URIs pay off for small, frequently reused assets like icons; photographs and large graphics should stay as separate files. The decision is covered in depth in our Base64 encoding guide.
Comments
No comments yet. Be the first to share your thoughts below.