The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →A data URL is already a usable image URL. To display it, assign the complete string to an HTMLImageElement‘s src property and wait for the image to load (or decode) before reading its dimensions or drawing it. Convert it to a Blob or use a canvas only when another API needs binary bytes, pixel access, resizing, or a different output format.
The direct answer: load the data URL with Image.src
Use the browser’s built-in Image constructor. The promise below resolves only after the browser has loaded the image, so naturalWidth, naturalHeight, and canvas drawing are ready to use.
function loadImage(dataUrl) {
return new Promise((resolve, reject) => {
const image = new Image();
image.onload = () => resolve(image);
image.onerror = () => reject(new Error('Could not load image data URL'));
image.src = dataUrl;
});
}
const image = await loadImage(dataUrl);
document.body.append(image);
console.log(image.naturalWidth, image.naturalHeight);
If you need an explicit decode step, call await image.decode() after the load promise resolves. Decoding before inserting the element can prevent a visible decode pause, but it does not replace validation of the source string.
Understand the data URL format before debugging it
A data URL has this general form:
data:[<media-type>][;base64],<data>
The comma separates metadata from the payload. A media type such as image/png, image/jpeg, image/webp, or image/svg+xml tells the browser what it is receiving. The ;base64 marker means the payload is Base64-decoded. Without that marker, the payload is URL-encoded text. If the media type is omitted, the data URL defaults to text/plain;charset=US-ASCII, which is not an image type.
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
Inspect the header and payload
function inspectDataUrl(dataUrl) {
if (typeof dataUrl !== 'string' || !dataUrl.startsWith('data:')) {
throw new TypeError('Expected a data URL');
}
const comma = dataUrl.indexOf(',');
if (comma === -1) throw new Error('Data URL has no comma separator');
const metadata = dataUrl.slice(5, comma);
const payload = dataUrl.slice(comma + 1);
const base64 = /;base64(?:;|$)/i.test(metadata);
const mediaType = metadata.split(';')[0] || 'text/plain;charset=US-ASCII';
return { mediaType, base64, payload };
}
console.log(inspectDataUrl(dataUrl));
For an image, a missing or incorrect media type is a common reason that assigning src produces a broken image. The payload must also use the encoding advertised by the header: Base64 after ;base64, or URL-encoded data otherwise.
Convert a data URL to a Blob and object URL
Displaying an image does not require a Blob. Use this route when an API expects binary data, when you want a temporary URL for a generated file, or when you want to avoid carrying a very long data URL through your application.
async function dataUrlToObjectUrl(dataUrl) {
const response = await fetch(dataUrl);
if (!response.ok) {
throw new Error(`Data URL could not be read (${response.status})`);
}
const blob = await response.blob();
return {
blob,
objectUrl: URL.createObjectURL(blob)
};
}
const { blob, objectUrl } = await dataUrlToObjectUrl(dataUrl);
const image = new Image();
image.onload = () => {
document.body.append(image);
// Keep objectUrl alive while the image is displayed or used.
};
image.onerror = () => {
URL.revokeObjectURL(objectUrl);
console.error('Object URL could not be displayed');
};
image.src = objectUrl;
// Later, after the image and any links or interactions using it are finished:
// URL.revokeObjectURL(objectUrl);
URL.createObjectURL() creates a temporary Blob URL. Revoke it when nothing needs it anymore, but do not revoke it immediately after assigning src if the image still has to render, be opened, or be saved. Revoking too early can turn a valid image into a blank or failed resource.
Read the bytes without displaying them
The same Blob can be uploaded or inspected with standard Blob APIs:
Rank #2
const response = await fetch(dataUrl);
const blob = await response.blob();
console.log(blob.type, blob.size);
const arrayBuffer = await blob.arrayBuffer();
// Send arrayBuffer or blob to an API that accepts binary image data.
Use a canvas only for pixels, resizing, or re-encoding
Canvas is the right tool when the requirement is more than display: crop an image, inspect pixels, resize it, draw annotations, or export another format. Wait until the image has loaded, then set the canvas dimensions from the image’s natural dimensions before calling drawImage.
async function imageToPngBlob(dataUrl) {
const image = await loadImage(dataUrl);
const canvas = document.createElement('canvas');
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
const context = canvas.getContext('2d');
if (!context) throw new Error('2D canvas is unavailable');
context.drawImage(image, 0, 0);
const blob = await new Promise((resolve) => {
canvas.toBlob(resolve, 'image/png');
});
if (!blob) throw new Error('Image export failed');
return blob;
}
const pngBlob = await imageToPngBlob(dataUrl);
const pngUrl = URL.createObjectURL(pngBlob);
const output = new Image();
output.src = pngUrl;
output.onload = () => {
document.body.append(output);
// Revoke pngUrl when output is no longer needed.
};
Resize while drawing
Set the destination canvas size to the desired dimensions and pass those dimensions to drawImage. The browser performs the resampling during the draw:
async function resizeDataUrl(dataUrl, width, height, type = 'image/webp', quality = 0.85) {
const image = await loadImage(dataUrl);
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const context = canvas.getContext('2d');
if (!context) throw new Error('2D canvas is unavailable');
context.drawImage(image, 0, 0, width, height);
return new Promise((resolve, reject) => {
canvas.toBlob((blob) => {
if (blob) resolve(blob);
else reject(new Error('The browser could not encode this format'));
}, type, quality);
});
}
const resizedBlob = await resizeDataUrl(dataUrl, 800, 600);
const resizedUrl = URL.createObjectURL(resizedBlob);
Prefer canvas.toBlob() plus an object URL for large results. canvas.toDataURL() constructs the entire encoded image as an in-memory string and can run into memory pressure or browser URL-length limits. Use toDataURL() when the caller specifically needs a serialized data URL and the image is small enough.
const image = await loadImage(dataUrl);
const canvas = document.createElement('canvas');
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
canvas.getContext('2d').drawImage(image, 0, 0);
const newDataUrl = canvas.toDataURL('image/png');
If the requested output type is unsupported, canvas export can fall back to PNG. Check the returned Blob’s type when the exact format matters.
Canvas security: why display can work while export fails
An image may render successfully yet make a canvas unreadable. If you draw cross-origin content and the remote server has not granted cross-origin access with CORS, the canvas becomes tainted. Pixel reads such as getImageData() and exports such as toBlob() or toDataURL() can then throw a SecurityError.
The server hosting a remote image must permit the requesting origin for the canvas to remain origin-clean. Setting crossOrigin on an image does not create permission by itself; the response still needs the appropriate CORS headers. A data URL is an inline resource, but modern browsers treat data URLs as unique opaque origins, so do not assume that every origin relationship is inherited from the document that created the string. Test the exact source and operation you need.
Choose the smallest API that solves the problem
| Goal | Use | What to remember |
|---|---|---|
| Show the image | image.src = dataUrl |
Wait for load or decode() before using dimensions. |
| Give another API binary data | fetch(dataUrl).then(r => r.blob()) |
Create an object URL if a temporary URL is useful; revoke it after use. |
| Read or alter pixels | Canvas and getImageData() |
Cross-origin images require CORS or export can fail. |
| Resize or change format | Canvas and toBlob() |
Prefer Blob output for large images; verify the resulting MIME type. |
| Produce a data URL string | Canvas and toDataURL() |
It stores the complete encoded result in memory and may be unsuitable for large images. |
Troubleshooting common failures
The image icon appears instead of the picture
- Check that the string starts with
data:and contains a comma. - Confirm the media type is an image type such as
image/pngorimage/jpeg. - If the header includes
;base64, verify that the payload is actually Base64. Otherwise URL-decode the non-Base64 payload. - Do not omit the media type for an image: the default is text, not an image.
naturalWidth is zero
Read dimensions only after the load event or after a successful decode. Reading immediately after setting src races the network-free but asynchronous image decoder.
fetch(dataUrl) or Blob creation fails
Inspect the comma-separated header and payload with inspectDataUrl(). A malformed percent escape, invalid Base64, or an incorrect data URL prefix must be fixed at the source; wrapping the string in another URL does not repair it.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallRank #4
The Blob URL works briefly and then breaks
Look for URL.revokeObjectURL() running in an onload handler or immediately after assignment. Keep the URL alive for as long as the image, download link, or other consumer needs it, then revoke it during cleanup.
Canvas throws SecurityError
The canvas is tainted by content that lacks the required CORS permission. Use a source that sends permission for your origin, or keep the image as a display-only resource and do not attempt pixel readback or export.
The page becomes slow with large images
Large data URLs duplicate image data in JavaScript strings and decoded image memory. Avoid converting repeatedly, prefer a Blob and object URL for binary workflows, and use toBlob() instead of creating another giant data URL unless serialization is required.
Server-side JavaScript: decoding bytes in Node.js
Node.js does not provide the browser’s Image element or canvas by default. If a server only needs the bytes, this dependency-free function separates the header and decodes a Base64 or URL-encoded payload. Rendering, resizing, and pixel operations still require an image-processing library or a browser runtime.
Best Value
function dataUrlToBuffer(dataUrl) {
if (typeof dataUrl !== 'string' || !dataUrl.startsWith('data:')) {
throw new TypeError('Expected a data URL');
}
const comma = dataUrl.indexOf(',');
if (comma === -1) throw new Error('Data URL has no comma separator');
const metadata = dataUrl.slice(5, comma);
const payload = dataUrl.slice(comma + 1);
if (/;base64(?:;|$)/i.test(metadata)) {
return Buffer.from(payload, 'base64');
}
return Buffer.from(decodeURIComponent(payload), 'utf8');
}
const bytes = dataUrlToBuffer(dataUrl);
console.log(bytes.length);
Use the browser approach when the output must be an on-page image. Use the Node function when an endpoint needs to store or forward the decoded bytes and does not need to render them.
Or skip the browser setup
If the image you need is a webpage screenshot rather than an existing data URL, ScreenshotNeo can return the image directly from one GET request. It handles the browser capture for you and supports PNG, JPEG, WebP, and PDF output. Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
JavaScript with fetch:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the complete option list and response details in the ScreenshotNeo documentation. The free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
Frequently Asked Questions
Does converting a data URL to a Blob change the image quality?
No. Fetching the data URL and exposing its body as a Blob does not re-encode the image. Quality changes only when you decode and export through a transformation such as canvas with a different format, size, or quality setting.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsCan I revoke the original data URL like an object URL?
No. URL.revokeObjectURL() applies to URLs created with URL.createObjectURL(). A data URL is an inline string; release references to that string when it is no longer needed.
Quick Recap
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.

