Skip to main content
ToolMaple

Image to Base64 Converter

Convert an image to Base64 or a data URL you can paste into HTML or CSS.

Last updated:

Drag images here, or choose files

Up to 50 images at a time, 5 MB per file (Base64 is a poor fit for large images)

No image selected yet

What a data URL is

A data URL carries a whole file inside the URL string itself, so the browser never makes a separate request to fetch it. The format comes from IETF RFC 2397, published in 1998, and its shape is:

data:[mediatype][;base64],<data>

For an image that reads data:image/png;base64,iVBORw0KGgo.... Anywhere a URL is accepted you can use one instead: HTML’s <img src>, CSS’s background-image: url(), Markdown’s ![](...). The browser sees the data: scheme, decodes the payload and draws the image without a network round trip.

People who do this by hand tend to get caught by two things. First, the command line base64 prints only the payload; the data:image/png;base64, prefix is yours to add, and declaring the wrong media type, calling a JPEG a PNG, makes some browsers refuse to render it. Second, GNU coreutils base64 wraps its output at 76 columns unless you pass -w 0, and a data URL cannot contain line breaks, so the image silently fails. What this page produces is a single line with the prefix already attached, ready to paste.

When to inline, and when to keep a separate file

Inlining is convenient, not free. Base64 makes the payload about 33% larger, and once the string lives inside an HTML or CSS file it is downloaded again with every copy of that file, because the browser can no longer cache the image on its own.

  • Inline it: icons under about 2 KB, images in HTML email, a Markdown document that has to travel as one file, an offline page, mock data in tests.
  • Keep the file: anything over roughly 10 KB, anything reused across several pages so caching pays off, and anything you expect to update on its own schedule.
  • The usual threshold: bundlers have settled on a few kilobytes. Vite inlines assets below 4 KB by default through build.assetsInlineLimit, and webpack 5 asset modules use a comparable default of about 8 KB. Under the line it is inlined, over it a file is emitted.

Situations where inlining earns its cost:

  • HTML email: avoids the external image that a mail client blocks behind a "display images" prompt, with the caveats further down this page.
  • A single file report: a .md or .html you hand someone directly, with no folder of assets to lose and no link to rot.
  • Small icons and logos in CSS: one fewer request, and the icon can never be missing while the stylesheet is present.
  • Fixtures and mock data: an image inside a JSON fixture keeps an integration test from depending on a file path.
  • Offline pages: one HTML file that renders completely with no network at all.

Why the encoded string is bigger than the file

Base64 maps every 3 bytes onto 4 printable ASCII characters, so growth of about 33% is built into the encoding, not a shortcoming of any particular tool. Add roughly 22 characters for the data:image/png;base64, prefix and a very small icon can look alarming as a percentage, while the absolute difference is a few hundred bytes and rarely worth worrying about.

Convert one image and pick the form you need

  1. Drag the image onto the dashed box, or use the file picker. The limit is 5 MB per file, because Base64 was never a good answer for large images.
  2. The row that appears shows the original size next to the encoded length, so the cost of inlining is visible before you commit to it.
  3. Click the row to load it into the preview below. The five tabs are Data URL, Raw Base64, HTML, CSS and Markdown.
  4. Use Data URL when the string goes straight into <img src> or url(). Use Raw Base64 when something else adds the prefix or decodes the payload, such as an API field or a backend decoder.
  5. The HTML, CSS and Markdown tabs are complete snippets with the syntax already assembled, so they can be pasted as they are.
  6. Use the copy button rather than selecting the text by hand. These strings run to tens of thousands of characters and a drag selection that misses the tail produces an image that will not decode.

Convert a batch and get a contact sheet with it

  1. Drop in several files at once; 50 or fewer is a comfortable batch. Files over 5 MB and anything that is not an image are skipped, and a message tells you how many were dropped and why.
  2. A counter shows how many of the batch are done. Everything runs in your browser, so the speed depends on this machine and not on your connection.
  3. Click any row to switch the preview. Remove a file with the ✕ on its row, or press Clear to start the batch again.
  4. For a single file as plain text, use the download button on its row to save a .base64.txt.
  5. Download all as ZIP packs the batch: one .base64.txt per image, duplicate names numbered automatically, plus an output.html.
  6. Open that output.html in a browser and every image renders at once with its original filename underneath. That is the quickest acceptance check there is: if the picture appears, the string is complete.

Pasting into HTML, CSS and Markdown

The data URL this page produces goes into the three places you would expect:

  • HTML: <img src="data:..." />
  • CSS: background-image: url("data:...");
  • Markdown: ![alt](data:...)

All three snippets are valid as copied, but the alt attribute is empty. Fill it in with what the image actually shows. It is what a screen reader announces and what a sighted visitor sees when the image fails to render.

  • Desktop: press the copy button and wait for the confirmation. After pasting, check that the value is still one unbroken line; an editor that hard wraps on save will break it.
  • iPhone, iPad and Android: use the copy button too. Do not long press and drag the selection handles; selecting tens of thousands of characters by hand on a phone almost never captures the whole string.
  • When the string is too long to carry around: save it with the download button as .base64.txt, or take the whole ZIP, and open it in an editor when you are ready to paste.
  • Going the other way: to encode or decode plain text rather than a file, use the Base64 text encoder.

Where data URLs work, and where they do not

  • Browsers: RFC 2397 sets no length limit, but every engine imposes one of its own, the published figures differ, and they have changed between versions. Past the limit the whole string is ignored and nothing renders.
  • Sites with a Content Security Policy: if img-src does not list data:, an inlined image is blocked and the console names the directive responsible. Allow it deliberately on a site you control.
  • Email: support for data: images across mail clients is inconsistent, so one message can look different in two inboxes. The approach that behaves predictably is still an attachment referenced by Content-ID. Gmail additionally clips a message past about 102 KB, which a Base64 image reaches fast.
  • Markdown on someone else’s platform: a number of hosts strip data: image sources when they sanitize user content, so the image comes out blank. Your own .md files and offline HTML are unaffected. Test with one small image before committing a document full of them.
  • Version control: a large data URL in source is a single line of tens of thousands of characters, and no reviewer can read that diff. Keeping images over a few kilobytes as files is kinder to collaborators.

The encoding itself also differs by runtime, which matters when you reproduce this conversion in a script:

// Node.js: read the bytes, then encode
const b64 = fs.readFileSync('logo.png').toString('base64')
const dataUrl = 'data:image/png;base64,' + b64

# Python
import base64
b64 = base64.b64encode(open('logo.png','rb').read()).decode()

# Shell (GNU coreutils; -w 0 keeps it on one line)
base64 -w 0 logo.png

In the browser, btoa() only accepts a string of code points below 256, so passing it text read as UTF-8 throws. For a file, read it with FileReader.readAsDataURL(), which is what this page does and which returns the prefix already attached.

Limits, and where your image goes

  • Base64 is encoding, not encryption: there is no key and anyone can reverse it. Keep private screenshots, identity documents and contracts out of documents you publish.
  • It slows down first paint: an inlined image downloads with the HTML or CSS that contains it, cannot be lazy loaded and cannot be cached separately, so a large one is added straight onto the critical path.
  • Nothing is compressed or resized: this is a change of representation only. Shrink the image first if you want a shorter string.
  • Write the alt text: the HTML and Markdown snippets ship with an empty alt, and shipping them as they are means an image with no text alternative.

Nowhere. FileReader reads the file into your tab’s memory, hands back a Base64 string and is finished; closing the tab releases both. There is not a single network request in the process, which is also why converting a large image depends only on your own hardware.

Frequently asked questions

Does my image get uploaded anywhere?

No. The file is read by FileReader inside the page, which is a browser API that works on the local file you picked. There is no upload step and no server that receives images. You can watch the network panel while you convert and see that nothing is sent. Close the tab and both the file and the string are gone from memory.

Which output should I copy: Data URL or Raw Base64?

Copy the Data URL when the string goes straight into markup: an img src, a CSS url(), a Markdown image. It already carries the data:image/png;base64, prefix that tells the browser how to decode it. Copy Raw Base64 when something on the other side adds the prefix for you or decodes the payload itself, such as an API field, a JSON fixture or a server that calls its own base64 decoder.

Why is the Base64 string bigger than the image file?

Base64 turns every 3 bytes into 4 printable characters, so the payload grows by roughly a third. RFC 4648 defines that mapping. Add about 22 characters for the data:image/png;base64, prefix and a tiny icon can look dramatically larger in percentage terms, though the absolute difference is still only a few hundred bytes.

Is there a maximum length for a data URL?

RFC 2397 does not define one, but browsers do, and the published figures differ by browser and change between versions. Rather than chase a number, treat a few hundred kilobytes as the point where a data URL stops being a good idea. This page caps single files at 5 MB, which is a guard against filling a tab with a string nobody wants to paste, not a browser limit.

Should I convert an SVG to Base64?

Usually not. SVG is already text, so you can URL encode it and inline it as data:image/svg+xml,... which stays smaller and stays readable in a diff. Base64 earns its keep for binary formats such as PNG, JPEG, GIF and WebP. If you do inline SVG in CSS, remember to escape the # in any hex color, because an unescaped # starts a fragment.

Does this compress or resize the image?

No. This is a change of representation only: the same bytes come out, written as text. If the file is too heavy, shrink it first and convert afterwards, which is the order that gives the shortest string. Open the image compressor

Can I convert a whole folder at once?

Yes. Drop in several files together; up to 50 files of 5 MB or less each is a comfortable batch. Click any row to switch the preview below it to that image, with all five forms available. Download all as ZIP writes one .base64.txt per image, numbering duplicate names, and adds an output.html you can open in a browser to see every image render at once, which is the fastest way to confirm each string is complete.

Why does my inlined image not show in an email?

Support for data: images in email clients is inconsistent, and the same message can render differently in two inboxes. Gmail also clips a message once it grows past about 102 KB, hiding the rest behind a "View entire message" link, and a Base64 image fills that budget quickly. The traditional approach that behaves predictably is to attach the image and reference it by Content-ID, or to host it and link to it.

My inlined image is blocked on my own site. What is wrong?

Check your Content Security Policy. If the img-src directive does not list data:, the browser refuses to render an inlined image and says which directive blocked it in the console. Adding data: to img-src fixes it, but do it deliberately: the directive exists partly to limit what can be smuggled into a page as an inline resource.

Is Base64 a form of encryption?

No. It is an encoding with no key, and anyone can reverse it. A data URL sitting in HTML, CSS or Markdown means the whole image is published inside that document, so anyone who can read the source can recover the picture. Keep private screenshots, identity documents and contracts out of inlined images. The conversion here is local, but where you paste the string afterwards is the document owner’s business, not the browser’s.

Sources

More tools

The shortest data URL starts with the smallest file, so run a photo through the image compressor before encoding it, or switch a PNG screenshot to WebP with the image converter first. For text rather than files, the Base64 encoder and decoder handles both directions.

Related tools

Privacy: images are read and encoded locally by the browser’s FileReader. Nothing is uploaded, nothing is stored, and this site has no backend that receives images. Close the tab and the file and the string it produced both leave memory. Where you paste the string afterwards is up to that document.