In a browser, use fetch() to download the image, turn the response into a Blob, then pass that blob to FileReader.readAsDataURL(). The result is a complete data URL such as data:image/jpeg;base64,...—not just the Base64 characters. This preserves the downloaded image bytes; it does not redraw or re-encode the image.
Convert an image URL to a data URL in the browser
This function returns a full data URL, which you can use as an image source or pass to an API that accepts data URLs. It checks the HTTP response before attempting to read the image, so an HTTP error is reported rather than silently treated as an image.
async function imageUrlToDataUrl(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Image request failed: ${response.status} ${response.statusText}`);
}
const blob = await response.blob();
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.addEventListener("load", () => resolve(reader.result), { once: true });
reader.addEventListener("error", () => reject(reader.error), { once: true });
reader.readAsDataURL(blob);
});
}
const dataUrl = await imageUrlToDataUrl("https://example.com/photo.jpg");
document.querySelector("img").src = dataUrl;
The final two lines assume the page contains an <img> element. If you only need the string, keep the dataUrl result and omit the assignment. The function uses browser APIs: fetch, Blob, and FileReader. It is not a universal Node.js implementation.
Why use a Blob between fetch and FileReader?
fetch(url) obtains the resource as an HTTP response. response.blob() reads its body as a blob, and readAsDataURL() converts that blob into a data URL. This approach converts the response bytes rather than drawing pixels onto a canvas. The browser supplies the data URL’s media type from the blob; do not hard-code image/png when the source might be JPEG, WebP, or another supported image format.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errors#1 Best Overall
Return only the Base64 payload when required
Some APIs expect raw Base64 characters rather than the complete data URL. Remove everything through the first comma only when the receiving system explicitly asks for raw Base64.
function dataUrlToBase64(dataUrl) {
return dataUrl.slice(dataUrl.indexOf(",") + 1);
}
const base64 = dataUrlToBase64(dataUrl);
Keep the prefix for consumers that accept data URLs, including an image’s src. It identifies the content as a particular media type and says that the remaining content is Base64-encoded. If you strip it, you are responsible for supplying any media-type information separately if the receiving API requires it. Do not assume the URL is always a PNG: the correct type depends on the response.
Rank #2
Check CORS when the image is on another origin
A browser can display a remote image in an <img> element without allowing your JavaScript to read its bytes. For fetch() to make a cross-origin response available to script, the image server must permit the requesting origin through its CORS response headers. Being able to open the image URL or see it on a page does not establish that permission.
CORS is decided by the server, not by a client-side option that can override the server’s policy. If the fetch fails because the image host does not grant access, the practical fixes are to use an image endpoint you control that permits the requesting origin, or to perform the operation in an environment authorized to retrieve the resource. A public CORS proxy is not a general fix: it introduces a third party and does not grant permission from the image owner.
Canvas does not bypass cross-origin restrictions
Another option is loading an image into an Image, drawing it to a canvas, then exporting the canvas. For a remote image, set crossOrigin before assigning src, and the remote host must still provide suitable CORS approval. Otherwise, drawing foreign-origin pixels taints the canvas; an attempt to export it, such as with toDataURL(), fails with a SecurityError.
Use canvas when you need a rendered or transformed image
Canvas is useful when the image is already loaded in the page or when you want the exported output to reflect drawing or other canvas operations. Unlike the fetch-and-Blob method, this is a rendering path, and the resulting representation may differ from the original file. This example exports a PNG data URL by default:
Rank #4
function imageElementToDataUrl(img, type = "image/png", quality) {
const canvas = document.createElement("canvas");
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
const context = canvas.getContext("2d");
if (!context) throw new Error("Could not create a 2D canvas context");
context.drawImage(img, 0, 0);
return canvas.toDataURL(type, quality);
}
Pass an image element that has loaded successfully. Its natural dimensions are used for the canvas, and the optional type and quality arguments control the export request where supported. toDataURL() returns a data URL. If the requested type is omitted or unsupported, it defaults to PNG. Canvas export creates output from the rendered pixels; use fetch plus Blob and FileReader when the goal is to preserve the downloaded bytes instead.
For large canvas output, MDN generally recommends toBlob() together with URL.createObjectURL() rather than toDataURL(), because toDataURL() encodes the whole image into an in-memory string. The appropriate choice depends on what the next step needs: a string data URL, a blob, or a rendered image.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Best Value
Choose the right conversion path
| Need | Use | Important consideration |
|---|---|---|
| Keep the source image bytes and create a browser data URL | fetch() → Blob → FileReader.readAsDataURL() |
Cross-origin fetch requires the image server to allow access; the result includes the data URL prefix. |
| Get only the Base64 characters | Convert to a data URL, then remove the prefix and comma | Do this only if the consumer requires raw Base64 rather than a data URL. |
| Convert a file selected by the user | Pass the selected File to FileReader.readAsDataURL() |
A File is a kind of Blob; remove the prefix only if needed. |
| Export an image already loaded or transformed in the page | Draw to canvas and export | Remote pixels require CORS approval, and large output is better handled as a Blob. |
| Run outside a browser | Use an implementation documented for that runtime | The browser-focused method here does not establish a Node.js recipe. |
Convert a local file input instead of a URL
If the user has selected a file in your page, you already have a File object. Since FileReader accepts a file as a blob, you can skip the network fetch and call readAsDataURL(file) using the same Promise pattern:
function fileToDataUrl(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.addEventListener("load", () => resolve(reader.result), { once: true });
reader.addEventListener("error", () => reject(reader.error), { once: true });
reader.readAsDataURL(file);
});
}
const input = document.querySelector('input[type="file"]');
const dataUrl = await fileToDataUrl(input.files[0]);
Use this only after a file has been selected; an empty file input has no first file. The result is still a complete data URL, with the file’s media type rather than a type you should guess.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Troubleshoot common failures
- The browser reports a CORS error. The remote image host has not allowed your page’s origin to read the response. Configure the image server to grant the required CORS access or retrieve an authorized copy from a server you control. Changing JavaScript cannot grant that permission.
- The function reports an HTTP status error. The response was not successful, for example because the URL is unavailable or access was denied. Check the URL and the reported status and status text; do not pass an error response body on as though it were an image.
- The URL works in an image tag but fetch fails. Displaying an image does not prove that script may read its bytes. Check whether the host permits your origin with CORS headers.
- Canvas export throws
SecurityError. The canvas is tainted by foreign-origin pixels. SetcrossOriginbefore the image’ssrcand confirm the image host grants the necessary CORS access; otherwise use an image source you are permitted to read. - The receiving API rejects the string. Confirm whether it expects a complete data URL or raw Base64. Do not remove the prefix if it expects a data URL, and do not hard-code a MIME type that does not match the image.
- The image looks different after conversion. The fetch-and-Blob route preserves the fetched bytes. Canvas exports rendered pixels and can produce a different representation; choose the method based on whether you need original bytes or a rendered result.
Memory and performance considerations
A data URL is a string containing the image representation, so avoid creating one when the next step can consume a Blob directly. In particular, canvas toDataURL() encodes the whole image into an in-memory string; MDN recommends generally preferring toBlob() with URL.createObjectURL() for large canvas output. No universal maximum image size or numeric conversion overhead is established here, so test with the image sizes and target browsers relevant to your application rather than relying on a made-up cutoff.
For an image URL, the time and reliability of the operation depend on successfully retrieving the resource as well as reading it. The function above makes one fetch, checks its HTTP result, then reads the body. If your downstream operation accepts a blob, keeping the blob avoids converting it to a large string unnecessarily. If it specifically requires Base64, convert only at that boundary.
Recommended Free Tools
Or skip the browser setup
ScreenshotNeo is a website screenshot API, not a general URL-to-Base64 converter. If your actual goal is to capture a webpage as an image rather than encode an existing image URL, its API returns an image or PDF directly. See the ScreenshotNeo API documentation for request options.
Quick Recap
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The saved response is an image file, not a Base64 string; you would still need an appropriate conversion step if a downstream system specifically requires Base64. ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server provides screenshot tools for AI agents, and the Free plan includes 1,000 screenshots per month with no card required; paid plans start at $5 for 3,000 screenshots. Every feature is available on every plan. If webpage capture fits your task, sign up free for 1,000 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.

