How to Download an Image with JavaScript
Triggering a file download from a browser is a common requirement, especially for images. The correct method for doing this depends on a critical factor: the origin of the image. Is the image hosted on the same domain as your website, or on a different one?
This guide will teach you the two standard methods for downloading an image. You will learn the simple HTML-only approach for same-origin images and the more powerful JavaScript fetch method required for cross-origin images.
Method 1 (Simple): The download Attribute for Same-Origin Images
For images that are hosted on the same domain as your web page, the simplest solution is a standard anchor (<a>) tag with the download attribute.
The download attribute is a signal to the browser that the link's target should be downloaded rather than navigated to. You can also provide a value to the attribute to suggest a new filename.
For example, we have an image on our server and want to provide a simple download link for it.
<!-- Problem: How to make this link download the image? -->
<a href="/images/house.png">Download Image</a>
The solution is to simply add the download attribute to the <a> tag.
<!-- This will now trigger a download when clicked -->
<a href="/images/house.png" download>Download Image</a>
<!-- You can also suggest a new filename -->
<a href="/images/house.png" download="my-downloaded-house.png">Download as...</a>
Limitation: This method is blocked by browser security policies for cross-origin URLs. If you try to use it with an image from a different domain, the browser will likely just navigate to the image instead of downloading it.
Method 2 (Powerful): Using JavaScript fetch for Cross-Origin Images
To download an image from a different domain (or when you need more control), you must use JavaScript to fetch the image data and trigger the download programmatically.
The logic:
- Fetch the Image: Use the
fetch()API to request the image data from the URL. - Get a Blob: Convert the response into a
Blob, which is a file-like object representing the raw image data. - Create an Object URL: Generate a temporary, local URL for the
BlobusingURL.createObjectURL(). - Simulate a Click: Create a temporary
<a>element in memory, set itshrefto the object URL, add thedownloadattribute, and programmatically click it to initiate the download. - Clean Up: Revoke the object URL to free up browser memory.
A Reusable async Function for Downloads (Best Practice)
The best practice is to encapsulate the fetch logic in a reusable async function. This makes your code clean, readable, and easy to reuse.
Example of the reusable function:
/**
* Downloads an image from a given URL.
* @param {string} imageUrl The URL of the image to download.
* @param {string} [filename] The desired name for the downloaded file.
*/
async function downloadImage(imageUrl, filename = 'downloaded-image.png') {
try {
// 1. Fetch the image
const response = await fetch(imageUrl);
if (!response.ok) {
throw new Error(`Network response was not ok: ${response.statusText}`);
}
// 2. Get the blob
const blob = await response.blob();
// 3. Create an object URL
const objectUrl = URL.createObjectURL(blob);
// 4. Simulate a click to download
const link = document.createElement('a');
link.href = objectUrl;
link.download = filename;
document.body.appendChild(link);
link.click();
// 5. Clean up
document.body.removeChild(link);
URL.revokeObjectURL(objectUrl);
} catch (error) {
console.error('There was an error downloading the image:', error);
}
}
And the solution as a practical example:
<button id="download-btn">Download Cross-Origin Image</button>
const downloadButton = document.getElementById('download-btn');
const imageUrl = 'https://example.com/cors/images'; // Example cross-origin URL, replace with yours
downloadButton.addEventListener('click', () => {
downloadImage(imageUrl, 'my-placeholder.png');
});
A Critical Note on CORS
The JavaScript fetch method is subject to Cross-Origin Resource Sharing (CORS) policies. This is not a magic workaround for downloading any image from the web.
- The server hosting the image must be configured to allow your domain to request it.
- If the server does not send the correct
Access-Control-Allow-Originheader, thefetchcall will fail, and you will see a CORS error in the console. You cannot bypass this from the client-side.
Conclusion: Which Method Should You Use?
The choice depends entirely on where the image is located.
- For same-origin images (on your own server), the
<a>tag with thedownloadattribute is the simplest and most direct solution. - For cross-origin images (on a different server), you must use the JavaScript
fetchmethod. This approach is more powerful but requires the remote server to have the correct CORS policy in place.