Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For an image chosen with a file input, use FileReader.readAsDataURL(). It returns a complete data URL, such as data:image/png;base64,..., that you can assign to an image’s src. For a remote image, fetch it as a Blob first; for image edits such as resizing or cropping, draw it to a canvas and serialize the canvas instead.

Convert a selected image file to a data URL

A browser file input gives JavaScript a File, which is a kind of Blob. Pass that file to FileReader.readAsDataURL(); the reader asynchronously produces the full data URL. The following example is a complete page: choose an image, convert it, and preview the result.

<input id="image-file" type="file" accept="image/*">
<p id="status"></p>
<img id="preview" alt="Selected image preview">
<textarea id="result" rows="6"></textarea>

<script>
function imageFileToDataURL(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.addEventListener("load", () => resolve(reader.result));
    reader.addEventListener("error", () => reject(reader.error));
    reader.readAsDataURL(file);
  });
}

const input = document.querySelector("#image-file");
const preview = document.querySelector("#preview");
const result = document.querySelector("#result");
const status = document.querySelector("#status");

input.addEventListener("change", async () => {
  const file = input.files?.[0];
  if (!file) return;

  status.textContent = "Reading image…";
  result.value = "";
  try {
    const dataURL = await imageFileToDataURL(file);
    preview.src = dataURL;
    result.value = dataURL;
    status.textContent = "Image converted.";
  } catch (error) {
    status.textContent = `Could not read image: ${error.message}`;
  }
});
</script>

The promise resolves to a string, not a raw Base64 payload. The returned value contains the media type and encoding declaration before the comma, followed by the encoded bytes. MDN describes readAsDataURL() as reading the contents of a specified Blob or File.

Validate the selected file when needed

The accept="image/*" attribute helps users choose an image in the file picker, but it is not a security check. If the application accepts only certain formats or sizes, validate those constraints in code too. For example, the following handler rejects files larger than 5 MB and checks the browser-provided media type:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const MAX_BYTES = 5 * 1024 * 1024;
const ALLOWED_TYPES = new Set(["image/png", "image/jpeg", "image/webp"]);

async function handleFile(file) {
  if (!ALLOWED_TYPES.has(file.type)) {
    throw new Error("Choose a PNG, JPEG, or WebP image.");
  }
  if (file.size > MAX_BYTES) {
    throw new Error("The image must be 5 MB or smaller.");
  }
  return imageFileToDataURL(file);
}

Client-side checks improve the interaction but do not replace server-side validation if the file will be uploaded or trusted by a backend. File metadata is supplied by the client and should not be treated as proof of file contents.

Convert an image at a remote URL

For an image URL, fetch the response body as a Blob, then reuse the file conversion function. This works only when the remote server permits the browser to read the response under its Cross-Origin Resource Sharing (CORS) policy.

async function remoteImageToDataURL(url) {
  const response = await fetch(url);
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  return imageFileToDataURL(await response.blob());
}

remoteImageToDataURL("https://example.com/photo.jpg")
  .then(dataURL => {
    document.querySelector("#preview").src = dataURL;
  })
  .catch(error => {
    console.error("Could not convert remote image:", error);
  });

Use an absolute URL when calling this from a page, and handle both network failures and non-success HTTP responses. Checking response.ok matters because fetch() does not reject its promise merely because the server returned an HTTP error status.

Why a remote image may fail despite loading in a tab

A browser can display an image from another origin without granting your script permission to read its bytes. Fetching the image as a Blob requires the server to return suitable CORS permission for your page’s origin. If the server does not permit it, JavaScript cannot bypass that restriction. Use a server you control, configure its CORS response, or route the request through a backend that is authorized to retrieve the image. Do not expose private credentials in browser code to work around access restrictions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use canvas when pixels or output format must change

FileReader preserves the bytes in the file. Use a canvas when you need to resize, crop, compose, or encode the rendered pixels in another supported format. Load the image, draw it to a canvas, then call toDataURL().

function canvasToDataURL(image, type = "image/png", quality) {
  const canvas = document.createElement("canvas");
  canvas.width = image.naturalWidth || image.width;
  canvas.height = image.naturalHeight || image.height;

  const context = canvas.getContext("2d");
  if (!context) throw new Error("Could not create a 2D canvas context.");
  context.drawImage(image, 0, 0);

  return quality === undefined
    ? canvas.toDataURL(type)
    : canvas.toDataURL(type, quality);
}

const image = new Image();
image.onload = () => {
  const dataURL = canvasToDataURL(image, "image/webp", 0.85);
  document.querySelector("#preview").src = dataURL;
};
image.onerror = () => console.error("Image could not be loaded.");
image.src = "./photo.jpg";

The default output type is PNG when no type is specified or the requested type is unsupported. For formats that support lossy encoding, such as JPEG and WebP, the quality argument is a number from 0 to 1. The browser may use a different encoding or quality implementation, so do not treat that number as a guaranteed file size or visual-quality measurement.

Resize before encoding

To reduce dimensions, set the canvas dimensions to the target size and draw the source image into that rectangle. This changes the rendered pixels before serialization:

function resizeImageToDataURL(image, width, height, type = "image/jpeg", quality = 0.85) {
  const canvas = document.createElement("canvas");
  canvas.width = width;
  canvas.height = height;
  const context = canvas.getContext("2d");
  if (!context) throw new Error("Could not create a 2D canvas context.");
  context.drawImage(image, 0, 0, width, height);
  return canvas.toDataURL(type, quality);
}

This example stretches the image to the requested width and height. To preserve the aspect ratio, calculate dimensions that fit the target bounds before calling drawImage(). Cropping instead requires choosing a source rectangle and destination rectangle for drawImage().

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Canvas and cross-origin images

A remote image can appear in an img element yet still taint a canvas when drawn. Once tainted, the canvas cannot be read back with toDataURL(). The remote server must grant appropriate CORS access, and the image must be loaded in a CORS-enabled manner before drawing. If you control the server, configure its CORS policy; otherwise, use an image source that permits this operation or perform the authorized processing on a server.

Choose the right output for the job

Input and need Recommended approach What you get
Selected local file; preserve original file contents FileReader.readAsDataURL(file) Complete data URL string
Remote URL; read image bytes in the browser fetch() to Blob, then FileReader Complete data URL if CORS permits the fetch
Existing image pixels; resize, crop, compose, or encode differently Draw to canvas, then canvas.toDataURL() Serialized canvas pixels in a supported image format
Large image or display-only preview; data URL not required Blob plus URL.createObjectURL() Short-lived object URL without a large Base64 string

Keep the data URL prefix or strip it deliberately

Keep the complete string when a consumer expects a URL, including an image’s src, a CSS url(), or a field that accepts a data URL. The prefix identifies the URL scheme and, in this case, the image media type and Base64 encoding.

Some APIs ask for only the Base64 payload. In that case, remove the declaration through the first comma, rather than assuming every image has the same MIME type:

function dataURLToBase64(dataURL) {
  const comma = dataURL.indexOf(",");
  if (comma === -1) throw new Error("Not a valid data URL.");
  return dataURL.slice(comma + 1);
}

Only strip the prefix when the receiving format explicitly requests raw Base64. Sending the stripped value to an image src removes the information needed to interpret it as a data URL.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Large images, memory, and performance

A data URL holds the encoded image in a JavaScript string. That can use substantially more memory than the original binary image, and creating or copying a long string can be costly. MDN warns that toDataURL() encodes the whole image into an in-memory string and can run into URL-length limits when used as an image source. For large images, prefer a Blob and an object URL when a data URL is not a requirement.

function previewBlob(blob, img) {
  const objectURL = URL.createObjectURL(blob);
  img.src = objectURL;

  // Revoke the URL when this preview is replaced or no longer needed.
  return () => URL.revokeObjectURL(objectURL);
}

For a selected file, the browser already has a Blob, so an object URL can preview it without converting it to Base64. For a canvas, use canvas.toBlob() to create a Blob, then call URL.createObjectURL(blob). Revoke object URLs when finished to release their associated resources. If a downstream system specifically demands a data URL, conversion may be unavoidable; avoid keeping redundant copies in state, logs, or the DOM.

Troubleshooting common conversion failures

  • The result is empty or the preview does not update: Confirm a file was selected and that the code waits for the reader’s load event or promise. Clear stale output before beginning a new read.
  • reader.error is set: The read operation failed or was interrupted. Show a useful error to the user and let them select the file again; do not treat a failed read as a valid data URL.
  • A remote fetch reports a CORS error: The image host has not authorized the browser origin to read the response. Configure CORS on a server you control or use an authorized server-side retrieval path; client JavaScript cannot override the policy.
  • The fetch resolves but conversion should not proceed: Check response.ok before calling response.blob(). A 404 or 500 response is still a completed HTTP response.
  • canvas.toDataURL() throws a security error: The canvas may be tainted by a cross-origin image without appropriate permission. Fix the image’s CORS access before drawing, or use a different permitted source.
  • The encoded image is unexpectedly PNG: toDataURL() falls back to PNG if the requested type is unsupported. Check the actual returned prefix instead of assuming the browser honored the requested format.
  • The data URL is too large or slow to handle: Avoid converting if an object URL or Blob meets the need. If the recipient requires a data URL, consider resizing or encoding a lossy format via canvas where appropriate.
  • The receiver rejects a seemingly valid value: Determine whether it expects a complete data URL or only the Base64 portion, and whether it accepts the reported media type. Do not strip or replace the prefix without confirming its input contract.

Or skip the browser setup

If your goal is a screenshot of a web page rather than converting an image file already on your device, ScreenshotNeo can return a screenshot image from one GET request. It is a screenshot API, not a replacement for FileReader when you need to convert a local file. Its clean-shot steps can accept cookie or consent banners and remove supported consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, with verdict and billing information in response headers. Its MCP server provides screenshot tools for AI agents.

For example, this cURL call saves a screenshot of a page as WebP. See the ScreenshotNeo documentation for API parameters and response details.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for 1,000 free screenshots a month with no card.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.