Skip to main content

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>
warning

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:

  1. Fetch the Image: Use the fetch() API to request the image data from the URL.
  2. Get a Blob: Convert the response into a Blob, which is a file-like object representing the raw image data.
  3. Create an Object URL: Generate a temporary, local URL for the Blob using URL.createObjectURL().
  4. Simulate a Click: Create a temporary <a> element in memory, set its href to the object URL, add the download attribute, and programmatically click it to initiate the download.
  5. 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-Origin header, the fetch call 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 the download attribute is the simplest and most direct solution.
  • For cross-origin images (on a different server), you must use the JavaScript fetch method. This approach is more powerful but requires the remote server to have the correct CORS policy in place.