How do you cache an image in Javascript

My friends and I are working on a website where we would like to cache certain images in order to display them faster in the future. I have two main questions:

  1. How do you cache an image?
  2. How do you use an image once it has been cached? (and just to verify, if an image is cached on page A, it is possible to call it from the cache to use it on page B, right?)

Also, is it possible to set when the cached version of the image will expire?

It would be much appreciated if an example and/or a link to a page which describes this further was included.

We're fine using either raw Javascript or the jQuery version.

Once an image has been loaded in any way into the browser, it will be in the browser cache and will load much faster the next time it is used whether that use is in the current page or in any other page as long as the image is used before it expires from the browser cache.

So, to precache images, all you have to do is load them into the browser. If you want to precache a bunch of images, it's probably best to do it with javascript as it generally won't hold up the page load when done from javascript. You can do that like this:

function preloadImages(array) {
    if (!preloadImages.list) {
        preloadImages.list = [];
    var list = preloadImages.list;
    for (var i = 0; i < array.length; i++) {
        var img = new Image();
        img.onload = function() {
            var index = list.indexOf(this);
            if (index !== -1) {
                // remove image from the array once it's loaded
                // for memory consumption reasons
                list.splice(index, 1);
        img.src = array[i];

preloadImages(["url1.jpg", "url2.jpg", "url3.jpg"]);

This function can be called as many times as you want and each time, it will just add more images to the precache.

Once images have been preloaded like this via javascript, the browser will have them in its cache and you can just refer to the normal URLs in other places (in your web pages) and the browser will fetch that URL from its cache rather than over the network.

Eventually over time, the browser cache may fill up and toss the oldest things that haven't been used in awhile. So eventually, the images will get flushed out of the cache, but they should stay there for awhile (depending upon how large the cache is and how much other browsing is done). Everytime the images are actually preloaded again or used in a web page, it refreshes their position in the browser cache automatically so they are less likely to get flushed out of the cache.

The browser cache is cross-page so it works for any page loaded into the browser. So you can precache in one place in your site and the browser cache will then work for all the other pages on your site.

When precaching as above, the images are loaded asynchronously so they will not block the loading or display of your page. But, if your page has lots of images of its own, these precache images can compete for bandwidth or connections with the images that are displayed in your page. Normally, this isn't a noticeable issue, but on a slow connection, this precaching could slow down the loading of the main page. If it was OK for preload images to be loaded last, then you could use a version of the function that would wait to start the preloading until after all other page resources were already loaded.

function preloadImages(array, waitForOtherResources, timeout) {
    var loaded = false, list = preloadImages.list, imgs = array.slice(0), t = timeout || 15*1000, timer;
    if (!preloadImages.list) {
        preloadImages.list = [];
    if (!waitForOtherResources || document.readyState === 'complete') {
    } else {
        window.addEventListener("load", function() {
        // in case window.addEventListener doesn't get called (sometimes some resource gets stuck)
        // then preload the images anyway after some timeout time
        timer = setTimeout(loadNow, t);

    function loadNow() {
        if (!loaded) {
            loaded = true;
            for (var i = 0; i < imgs.length; i++) {
                var img = new Image();
                img.onload = img.onerror = img.onabort = function() {
                    var index = list.indexOf(this);
                    if (index !== -1) {
                        // remove image from the array once it's loaded
                        // for memory consumption reasons
                        list.splice(index, 1);
                img.src = imgs[i];

preloadImages(["url1.jpg", "url2.jpg", "url3.jpg"], true);
preloadImages(["url99.jpg", "url98.jpg"], true);

as @Pointy said you don't cache images with javascript, the browser does that. so this may be what you are asking for and may not be... but you can preload images using javascript. By putting all of the images you want to preload into an array and putting all of the images in that array into hidden img elements, you effectively preload (or cache) the images.

var images = [

$(images).each(function() {
var image = $('<img />').attr('src', this);

There are a few things you can look at:

Pre-loading your images
Setting a cache time in an .htaccess file
File size of images and base64 encoding them.



There are a couple different thoughts for base64 encoding, some say that the http requests bog down bandwidth, while others say that the "perceived" loading is better. I'll leave this up in the air.

I have a similar answer for asynchronous preloading images via JS. Loading them dynamically is the same as loading them normally. they will cache.

as for caching, you can't control the browser but you can set it via server. if you need to load a really fresh resource on demand, you can use the cache buster technique to force load a fresh resource.

Even though your question says "using javascript", you can use the prefetch attribute of a link tag to preload any asset. As of this writing (Aug 10, 2016) it isn't supported in Safari, but is pretty much everywhere else:

<link rel="prefetch" href="(url)">

More info on support here:

Note that IE 9,10 aren't listed in the caniuse matrix because Microsoft has discontinued support for them.

So if you were really stuck on using javascript, you could use jquery to dynamically add these elements to your page as well ;-)

I use a similar technique to lazyload images, but can't help but notice that Javascript doesn't access the browser cache on first loading.

My example:

I have a rotating banner on my homepage with 4 images the slider wait 2 seconds, than the javascript loads the next image, waits 2 seconds, etc.

These images have unique urls that change whenever I modify them, so they get caching headers that will cache in the browser for a year.

max-age: 31536000, public

Now when I open Chrome Devtools and make sure de 'Disable cache' option is not active and load the page for the first time (after clearing the cache) all images get fetch and have a 200 status. After a full cycle of all images in the banner the network requests stop and the cached images are used.

Now when I do a regular refresh or go to a subpage and click back, the images that are in the cache seems to be ignored. I would expect to see a grey message "from disk cache" in the Network tab of Chrome devtools. In instead I see the requests pass by every two seconds with a Green status circle instead of gray, I see data being transferred, so it I get the impression the cache is not accessed at all from javascript. It simply fetches the image each time the page gets loaded.

So each request to the homepage triggers 4 requests regardless of the caching policy of the image.

Considering the above together and the new http2 standard most webservers and browsers now support, I think it's better to stop using lazyloading since http2 will load all images nearly simultaneously.

If this is a bug in Chrome Devtools it really surprises my nobody noticed this yet. ;)

If this is true, using lazyloading only increases bandwith usage.

Please correct me if I'm wrong. :)

Yes, the browser caches images for you, automatically.

You can, however, set an image cache to expire. Check out this Stack Overflow questions and answer:

Cache Expiration On Static Images

I always prefer to use the example mentioned in Konva JS: Image Events to load images.

  1. You need to have a list of image URLs as object or array, for example:

    var sources = { lion: '/assets/lion.png', monkey: '/assets/monkey.png' };

  2. Define the Function definition, where it receives list of image URLs and a callback function in its arguments list, so when it finishes loading image you can start excution on your web page:

    function loadImages(sources, callback) {
                var images = {};
                var loadedImages = 0;
                var numImages = 0;
                for (var src in sources) {
                for (var src in sources) {
                    images[src] = new Image();
                    images[src].onload = function () {
                        if (++loadedImages >= numImages) {
                    images[src].src = sources[src];

  1. Lastly, you need to call the function. You can call it for example from jQuery's Document Ready

$(document).ready(function (){ loadImages(sources, buildStage); });

Adding for completeness of the answers: preloading with HTML

<link rel="preload" href="bg-image-wide.png" as="image">

Other preloading features exist, but none are quite as fit for purpose as <link rel="preload">:

  • <link rel="prefetch"> has been supported in browsers for a long time, but it is intended for prefetching resources that will be used in the next navigation/page load (e.g. when you go to the next page). This is fine, but isn't useful for the current page! In addition, browsers will give prefetch resources a lower priority than preload ones — the current page is more important than the next. See Link prefetching FAQ for more details.
  • <link rel="prerender"> renders a specified webpage in the background, speeding up its load if the user navigates to it. Because of the potential to waste users bandwidth, Chrome treats prerender as a NoState prefetch instead.
  • <link rel="subresource"> was supported in Chrome a while ago, and was intended to tackle the same issue as preload, but it had a problem: there was no way to work out a priority for the items (as didn't exist back then), so they all got fetched with fairly low priority.

There are a number of script-based resource loaders out there, but they don't have any power over the browser's fetch prioritization queue, and are subject to much the same performance problems.


Nowdays, there is a new technique suggested by google to cache and improve your image rendering process:

  1. Include the JavaScript Lazysizes file: lazysizes.js
  2. Add the file to the html file you want to use in: <script src="lazysizes.min.js" async></script>
  3. Add the lazyload class to your image: <img data-src="images/flower3.png" class="lazyload" alt="">