← All articles 9 min read

Image to Base64: Encode Images in 5 Languages

Base64 encoding converts binary image data into an ASCII string that you can embed directly in HTML, CSS, JSON, or API payloads. The result is a data: URI — a self-contained image reference that eliminates the need for a separate HTTP request.

The most common use cases:

Base64 encoding is straightforward in every major language. The real question is not how to encode — it is when encoding is the right choice versus serving the image as an external file.

Before encoding, compress your source image to the smallest possible size. A 50KB PNG produces a 67KB base64 string; a 5KB PNG produces a 6.7KB string. Pixotter's compression tools run entirely in your browser and typically reduce file sizes by 40-80% with no visible quality loss. Compress first, encode second.


Why Convert Images to Base64?

Base64 inline embedding solves a specific set of problems. Here is when it genuinely helps:

Eliminate HTTP requests for small assets. Every external image is a separate HTTP request — DNS lookup, TCP connection, TLS handshake, response. For a 400-byte favicon or a 1KB UI icon, the request overhead dwarfs the payload. Inlining that icon as a base64 data: URI removes the request entirely.

Email compatibility. Most email clients block external images by default, showing a "click to load images" prompt. Base64-encoded images embedded directly in the HTML body render immediately without user intervention. This matters for logos in transactional emails, signature images, and critical visual elements in marketing emails.

API and data interchange. REST APIs that accept JSON cannot carry binary data natively. Base64 encoding wraps the image bytes in a JSON-safe string. This is standard practice for avatar uploads, document attachments, and image processing APIs — including the multimodal inputs accepted by GPT-4 Vision and Claude.

Single-file documents. HTML exports, saved web pages, SVG documents with embedded raster images, and Markdown-to-PDF pipelines all benefit from self-contained image data. No broken image links when the file moves to a different machine.

CSS sprites replacement. For a small set of icons (under 2KB each), base64 data URIs in CSS eliminate the sprite sheet and its maintenance overhead. The icons load with the stylesheet — no additional request, no image positioning math.


How to Convert an Image to Base64

JavaScript (Browser)

The FileReader API reads a file from an <input> element and returns a base64-encoded data URI:

// FileReader approach — works with file inputs and drag-and-drop
const input = document.querySelector('input[type="file"]');

input.addEventListener('change', (event) => {
  const file = event.target.files[0];
  const reader = new FileReader();

  reader.onload = () => {
    const base64String = reader.result;
    // reader.result is "data:image/png;base64,iVBORw0KGgo..."
    console.log(base64String);
  };

  reader.readAsDataURL(file);
});

To encode an image already rendered on a <canvas>:

// Canvas approach — useful for screenshots or processed images
const canvas = document.querySelector('canvas');
const base64Png = canvas.toDataURL('image/png');
const base64Jpeg = canvas.toDataURL('image/jpeg', 0.85);
// Second argument sets quality (0.0 to 1.0) for lossy formats

toDataURL() returns the full data URI including the data:image/...;base64, prefix. If you need the raw base64 string without the prefix, split on the comma:

const rawBase64 = canvas.toDataURL('image/png').split(',')[1];

Python 3.12

import base64
from pathlib import Path

image_path = Path("icon.png")
image_bytes = image_path.read_bytes()
base64_string = base64.b64encode(image_bytes).decode("utf-8")

# Build a data URI
mime_type = "image/png"
data_uri = f"data:{mime_type};base64,{base64_string}"

print(f"Encoded length: {len(base64_string)} characters")

For a one-liner in a script:

import base64
b64 = base64.b64encode(open("icon.png", "rb").read()).decode("utf-8")

Node.js 22

import { readFileSync } from 'node:fs';

const imageBuffer = readFileSync('icon.png');
const base64String = imageBuffer.toString('base64');

// Build a data URI
const mimeType = 'image/png';
const dataUri = `data:${mimeType};base64,${base64String}`;

console.log(`Encoded length: ${base64String.length} characters`);

Node.js 22 also supports the Buffer.from() round-trip for decoding:

import { writeFileSync } from 'node:fs';

// Decode base64 back to an image file
const decoded = Buffer.from(base64String, 'base64');
writeFileSync('output.png', decoded);

Bash (GNU coreutils)

# Encode — the -w 0 flag disables line wrapping (default wraps at 76 chars)
base64 -w 0 icon.png > icon.b64.txt

# Encode and build a data URI in one line
echo "data:image/png;base64,$(base64 -w 0 icon.png)"

# Decode
base64 -d icon.b64.txt > decoded.png

On macOS, the base64 command uses different flags:

# macOS — use -b 0 instead of -w 0
base64 -b 0 -i icon.png -o icon.b64.txt

PHP 8.3

<?php
$imagePath = 'icon.png';
$imageData = file_get_contents($imagePath);
$base64String = base64_encode($imageData);

// Build a data URI
$mimeType = mime_content_type($imagePath);
$dataUri = "data:{$mimeType};base64,{$base64String}";

echo "Encoded length: " . strlen($base64String) . " characters\n";

CSS Data URIs

Embed a base64-encoded image directly in a stylesheet:

.icon-search {
  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0i...);
  background-size: 16px 16px;
  width: 16px;
  height: 16px;
}

.logo {
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAAN...);
  background-repeat: no-repeat;
  background-size: contain;
}

For SVG specifically, you can skip base64 and use UTF-8 encoding, which is smaller:

.icon-arrow {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14m-7-7 7 7-7 7'/%3E%3C/svg%3E");
}

Size Limits and Performance

Base64 encoding inflates file size by exactly 33%. Every 3 bytes of binary data become 4 bytes of ASCII text. A 10KB image becomes a ~13.3KB base64 string. A 100KB image becomes ~133KB of text embedded in your HTML or CSS.

This overhead compounds in ways that are easy to underestimate:

Parsing cost. The browser must parse the base64 string, decode it to binary, then decode the image format. For external images, the browser streams and decodes in parallel. For inline base64, the entire string must be present before decoding begins.

No caching. An external image at /icons/search.png is cached by the browser after the first load. Subsequent page views serve it from disk cache with zero network cost. A base64 image embedded in HTML is re-downloaded with every page load. Embedded in CSS, it caches with the stylesheet — better, but the CSS file is now larger and takes longer to parse on every page.

HTTP/2 multiplexing. The original argument for base64 was reducing HTTP requests. Under HTTP/1.1, each request required a separate TCP connection (or waited in a queue). Under HTTP/2 (universal since ~2020), hundreds of requests share a single connection with minimal overhead. The request-reduction benefit of base64 is dramatically smaller than it was a decade ago.

Gzip interaction. Base64 text compresses poorly with gzip/brotli compared to binary image data served separately. A 10KB PNG served as a file compresses to ~10KB (PNG is already compressed). The same image as 13.3KB of base64 text in HTML might compress to ~11KB — still larger.

Recommended limits:


Base64 vs External Images

Factor Base64 Inline External Image File
HTTP requests 0 (embedded in document) 1 per image
Total bytes transferred ~33% larger than source Source size (often gzip-compressed)
Browser caching Not cached independently (cached with host document) Cached separately, served from disk on repeat visits
Initial page load Faster for tiny images (<2KB); slower for larger ones Faster for images >5KB due to parallel loading and streaming
Render blocking Image blocks document parse if in HTML; blocks render if in CSS Non-blocking with async/loading="lazy" attributes
CDN delivery No — travels with host document Yes — served from edge nodes closest to user
Best for Icons <2KB, email templates, single-file exports, API payloads Photos, illustrations, anything >5KB, any image shown on multiple pages

The crossover point depends on your stack, but the general rule holds: base64 for tiny, critical, single-use images. External files for everything else.


Compress Before Encoding

Base64 encoding is a transport mechanism, not a compression method. It makes files larger, not smaller. The single most impactful thing you can do before encoding is to compress the source image aggressively.

Consider a workflow for embedding a small logo:

  1. Start with a 48KB PNG logo
  2. Run it through Pixotter's PNG compressor — output: 12KB (75% reduction)
  3. Base64 encode — output: 16KB string
  4. Versus encoding the original: 64KB string

That is a 4x difference in the base64 string length, and it directly impacts your HTML/CSS file size, parse time, and bandwidth.

For icons and small graphics, convert to WebP or SVG before encoding. SVG icons encoded as UTF-8 data URIs (not base64) are often under 500 bytes. A 2KB PNG icon might compress to 800 bytes as WebP, yielding a ~1.1KB base64 string instead of ~2.7KB.

Compression is always step one. Encode step two. Pixotter's tools handle both — compress in your browser, then copy the result for encoding. Your images never leave your device.


Frequently Asked Questions

What is a base64 image?

A base64 image is a text representation of binary image data, encoded using the base64 alphabet (A-Z, a-z, 0-9, +, /). It is typically wrapped in a data URI — data:image/png;base64,iVBORw0KGgo... — that browsers can render directly in <img> tags, CSS background-image properties, and SVG <image> elements without fetching an external file.

Does base64 encoding reduce image file size?

No. Base64 encoding increases size by 33%. Every 3 bytes of binary data become 4 bytes of ASCII text. To reduce image size, compress the image before encoding. The compression reduces the binary data, and the encoding then produces a proportionally shorter string.

What is the maximum size for a base64 image in HTML?

There is no hard limit in the HTML specification. Browsers can handle multi-megabyte data URIs. The practical limits are performance and user experience — a 1MB base64 string in your HTML adds 1MB to every page load, blocks parsing, and cannot be cached independently. Keep base64 images under 5KB (source size) for acceptable performance. For anything larger, serve the image as an external file and let the browser cache it.

How do I convert a base64 string back to an image?

Decode the base64 string to binary bytes and write them to a file. In JavaScript: atob(base64String) or Buffer.from(base64String, 'base64') in Node.js. In Python: base64.b64decode(base64_string). In Bash: echo "$base64_string" | base64 -d > image.png. See our guide on converting base64 back to image files for complete examples in every language.

Can I use base64 images in email HTML?

Yes, and it is often the best approach for critical images like logos. Most email clients block external images by default but render inline base64 images immediately. Limitations: some email clients (notably older Outlook versions) have size caps on embedded images (~30KB per image). Gmail clips HTML emails over 102KB total — keep your combined base64 images well under that threshold.

Is base64 encoding the same as encryption?

No. Base64 is an encoding scheme, not encryption. It transforms binary data into text for transport — anyone can decode it instantly. Base64 provides zero security. If your images contain sensitive data, use actual encryption (AES-256, for example) and transmit over HTTPS. Do not rely on base64 to obscure image contents.


Summary

Base64 encoding is a tool with a narrow optimal range. For small icons (under 2KB), email templates, API payloads, and single-file documents, it eliminates HTTP requests and simplifies deployment. For anything larger, external image files with proper caching and CDN delivery outperform inline encoding on every metric.

The workflow: compress your image to the smallest possible size, convert to an efficient format if needed, then encode. The smaller the input, the shorter the base64 string, and the less impact it has on your page weight.

Pixotter handles the compression and conversion steps in your browser — no upload, no account, no server round-trip. Start with compression, then encode the result using the code examples above.