[javascript] jQuery/JavaScript to replace broken images

I have a web page that includes a bunch of images. Sometimes the image isn't available, so a broken image is displayed in the client's browser.

How do I use jQuery to get the set of images, filter it to broken images then replace the src?


--I thought it would be easier to do this with jQuery, but it turned out much easier to just use a pure JavaScript solution, that is, the one provided by Prestaul.

This question is related to javascript jquery html brokenimage

The answer is


Handle the onError event for the image to reassign its source using JavaScript:

function imgError(image) {
    image.onerror = "";
    image.src = "/images/noimage.gif";
    return true;
}
<img src="image.png" onerror="imgError(this);"/>

Or without a JavaScript function:

<img src="image.png" onError="this.onerror=null;this.src='/images/noimage.gif';" />

The following compatibility table lists the browsers that support the error facility:

http://www.quirksmode.org/dom/events/error.html


I use the built in error handler:

$("img").error(function () {
    $(this).unbind("error").attr("src", "broken.gif");
});

Edit: The error() method is deprecated in jquery 1.8 and higher. Instead, you should use .on("error") instead:

$("img").on("error", function () {
    $(this).attr("src", "broken.gif");
});

I use the built in error handler:

$("img").error(function () {
    $(this).unbind("error").attr("src", "broken.gif");
});

Edit: The error() method is deprecated in jquery 1.8 and higher. Instead, you should use .on("error") instead:

$("img").on("error", function () {
    $(this).attr("src", "broken.gif");
});

In case someone like me, tries to attach the error event to a dynamic HTML img tag, I'd like to point out that, there is a catch:

Apparently img error events don't bubble in most browsers, contrary to what the standard says.

So, something like the following will not work:

$(document).on('error', 'img', function () { ... })

Hope this will be helpful to someone else. I wish I had seen this here in this thread. But, I didn't. So, I am adding it


In case someone like me, tries to attach the error event to a dynamic HTML img tag, I'd like to point out that, there is a catch:

Apparently img error events don't bubble in most browsers, contrary to what the standard says.

So, something like the following will not work:

$(document).on('error', 'img', function () { ... })

Hope this will be helpful to someone else. I wish I had seen this here in this thread. But, I didn't. So, I am adding it


Here is a standalone solution:

$(window).load(function() {
  $('img').each(function() {
    if ( !this.complete
    ||   typeof this.naturalWidth == "undefined"
    ||   this.naturalWidth == 0                  ) {
      // image was broken, replace with your new image
      this.src = 'http://www.tranism.com/weblog/images/broken_ipod.gif';
    }
  });
});

Here is a standalone solution:

$(window).load(function() {
  $('img').each(function() {
    if ( !this.complete
    ||   typeof this.naturalWidth == "undefined"
    ||   this.naturalWidth == 0                  ) {
      // image was broken, replace with your new image
      this.src = 'http://www.tranism.com/weblog/images/broken_ipod.gif';
    }
  });
});

Here is a standalone solution:

$(window).load(function() {
  $('img').each(function() {
    if ( !this.complete
    ||   typeof this.naturalWidth == "undefined"
    ||   this.naturalWidth == 0                  ) {
      // image was broken, replace with your new image
      this.src = 'http://www.tranism.com/weblog/images/broken_ipod.gif';
    }
  });
});

Here is a standalone solution:

$(window).load(function() {
  $('img').each(function() {
    if ( !this.complete
    ||   typeof this.naturalWidth == "undefined"
    ||   this.naturalWidth == 0                  ) {
      // image was broken, replace with your new image
      this.src = 'http://www.tranism.com/weblog/images/broken_ipod.gif';
    }
  });
});

I believe this is what you're after: jQuery.Preload

Here's the example code from the demo, you specify the loading and not found images and you're all set:

jQuery('#images img').preload({
  placeholder:'placeholder.jpg',
  notFound:'notfound.jpg'
});

I believe this is what you're after: jQuery.Preload

Here's the example code from the demo, you specify the loading and not found images and you're all set:

jQuery('#images img').preload({
  placeholder:'placeholder.jpg',
  notFound:'notfound.jpg'
});

I believe this is what you're after: jQuery.Preload

Here's the example code from the demo, you specify the loading and not found images and you're all set:

jQuery('#images img').preload({
  placeholder:'placeholder.jpg',
  notFound:'notfound.jpg'
});

I believe this is what you're after: jQuery.Preload

Here's the example code from the demo, you specify the loading and not found images and you're all set:

jQuery('#images img').preload({
  placeholder:'placeholder.jpg',
  notFound:'notfound.jpg'
});

$(window).bind('load', function() {
  $('img').each(function() {
    if( (typeof this.naturalWidth != "undefined" && this.naturalWidth == 0) 
    ||  this.readyState == 'uninitialized'                                  ) {
        $(this).attr('src', 'missing.jpg');
    }
  });
});

Source: http://www.developria.com/2009/03/jquery-quickie---broken-images.html


$(window).bind('load', function() {
  $('img').each(function() {
    if( (typeof this.naturalWidth != "undefined" && this.naturalWidth == 0) 
    ||  this.readyState == 'uninitialized'                                  ) {
        $(this).attr('src', 'missing.jpg');
    }
  });
});

Source: http://www.developria.com/2009/03/jquery-quickie---broken-images.html


While the OP was looking to replace the SRC, I'm sure many people hitting this question may only wish to hide the broken image, in which case this simple solution worked great for me.

Using Inline JavaScript:

_x000D_
_x000D_
<img src="img.jpg" onerror="this.style.display='none';" />
_x000D_
_x000D_
_x000D_

Using External JavaScript:

_x000D_
_x000D_
var images = document.querySelectorAll('img');

for (var i = 0; i < images.length; i++) {
  images[i].onerror = function() {
    this.style.display='none';
  }
}
_x000D_
<img src='img.jpg' />
_x000D_
_x000D_
_x000D_

Using Modern External JavaScript:

_x000D_
_x000D_
document.querySelectorAll('img').forEach((img) => {
  img.onerror = function() {
    this.style.display = 'none';
  }
});
_x000D_
<img src='img.jpg' />
_x000D_
_x000D_
_x000D_

See browser support for NodeList.forEach and arrow functions.


While the OP was looking to replace the SRC, I'm sure many people hitting this question may only wish to hide the broken image, in which case this simple solution worked great for me.

Using Inline JavaScript:

_x000D_
_x000D_
<img src="img.jpg" onerror="this.style.display='none';" />
_x000D_
_x000D_
_x000D_

Using External JavaScript:

_x000D_
_x000D_
var images = document.querySelectorAll('img');

for (var i = 0; i < images.length; i++) {
  images[i].onerror = function() {
    this.style.display='none';
  }
}
_x000D_
<img src='img.jpg' />
_x000D_
_x000D_
_x000D_

Using Modern External JavaScript:

_x000D_
_x000D_
document.querySelectorAll('img').forEach((img) => {
  img.onerror = function() {
    this.style.display = 'none';
  }
});
_x000D_
<img src='img.jpg' />
_x000D_
_x000D_
_x000D_

See browser support for NodeList.forEach and arrow functions.


Here is a quick-and-dirty way to replace all the broken images, and there is no need to change the HTML code ;)

codepen example

    $("img").each(function(){
        var img = $(this);
        var image = new Image();
        image.src = $(img).attr("src");
        var no_image = "https://dummyimage.com/100x100/7080b5/000000&text=No+image";
        if (image.naturalWidth == 0 || image.readyState == 'uninitialized'){
            $(img).unbind("error").attr("src", no_image).css({
                height: $(img).css("height"),
                width: $(img).css("width"),
            });
        }
  });

Here is a quick-and-dirty way to replace all the broken images, and there is no need to change the HTML code ;)

codepen example

    $("img").each(function(){
        var img = $(this);
        var image = new Image();
        image.src = $(img).attr("src");
        var no_image = "https://dummyimage.com/100x100/7080b5/000000&text=No+image";
        if (image.naturalWidth == 0 || image.readyState == 'uninitialized'){
            $(img).unbind("error").attr("src", no_image).css({
                height: $(img).css("height"),
                width: $(img).css("width"),
            });
        }
  });

This is a crappy technique, but it's pretty much guaranteed:

<img onerror="this.parentNode.removeChild(this);">

This is a crappy technique, but it's pretty much guaranteed:

<img onerror="this.parentNode.removeChild(this);">

I couldn't find a script to suit my needs, so I made a recursive function to check for broken images and attempt to reload them every four seconds until they are fixed.

I limited it to 10 attempts as if it's not loaded by then the image might not be present on server and the function would enter an infinite loop. I am still testing though. Feel free to tweak it :)

var retries = 0;
$.imgReload = function() {
    var loaded = 1;

    $("img").each(function() {
        if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {

            var src = $(this).attr("src");
            var date = new Date();
            $(this).attr("src", src + "?v=" + date.getTime()); //slightly change url to prevent loading from cache
            loaded =0;
        }
    });

    retries +=1;
    if (retries < 10) { // If after 10 retries error images are not fixed maybe because they
                        // are not present on server, the recursion will break the loop
        if (loaded == 0) {
            setTimeout('$.imgReload()',4000); // I think 4 seconds is enough to load a small image (<50k) from a slow server
        }
        // All images have been loaded
        else {
            // alert("images loaded");
        }
    }
    // If error images cannot be loaded  after 10 retries
    else {
        // alert("recursion exceeded");
    }
}

jQuery(document).ready(function() {
    setTimeout('$.imgReload()',5000);
});

I couldn't find a script to suit my needs, so I made a recursive function to check for broken images and attempt to reload them every four seconds until they are fixed.

I limited it to 10 attempts as if it's not loaded by then the image might not be present on server and the function would enter an infinite loop. I am still testing though. Feel free to tweak it :)

var retries = 0;
$.imgReload = function() {
    var loaded = 1;

    $("img").each(function() {
        if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {

            var src = $(this).attr("src");
            var date = new Date();
            $(this).attr("src", src + "?v=" + date.getTime()); //slightly change url to prevent loading from cache
            loaded =0;
        }
    });

    retries +=1;
    if (retries < 10) { // If after 10 retries error images are not fixed maybe because they
                        // are not present on server, the recursion will break the loop
        if (loaded == 0) {
            setTimeout('$.imgReload()',4000); // I think 4 seconds is enough to load a small image (<50k) from a slow server
        }
        // All images have been loaded
        else {
            // alert("images loaded");
        }
    }
    // If error images cannot be loaded  after 10 retries
    else {
        // alert("recursion exceeded");
    }
}

jQuery(document).ready(function() {
    setTimeout('$.imgReload()',5000);
});

You can use GitHub's own fetch for this:

Frontend: https://github.com/github/fetch
or for Backend, a Node.js version: https://github.com/bitinn/node-fetch

fetch(url)
  .then(function(res) {
    if (res.status == '200') {
      return image;
    } else {
      return placeholder;
    }
  }

Edit: This method is going to replace XHR and supposedly already has been in Chrome. To anyone reading this in the future, you may not need the aforementioned library included.


You can use GitHub's own fetch for this:

Frontend: https://github.com/github/fetch
or for Backend, a Node.js version: https://github.com/bitinn/node-fetch

fetch(url)
  .then(function(res) {
    if (res.status == '200') {
      return image;
    } else {
      return placeholder;
    }
  }

Edit: This method is going to replace XHR and supposedly already has been in Chrome. To anyone reading this in the future, you may not need the aforementioned library included.


This is JavaScript, should be cross browser compatible, and delivers without the ugly markup onerror="":

var sPathToDefaultImg = 'http://cdn.sstatic.net/stackexchange/img/logos/so/so-icon.png',
    validateImage = function( domImg ) {
        oImg = new Image();
        oImg.onerror = function() {
            domImg.src = sPathToDefaultImg;
        };
        oImg.src = domImg.src;
    },
    aImg = document.getElementsByTagName( 'IMG' ),
    i = aImg.length;

while ( i-- ) {
    validateImage( aImg[i] );
}

CODEPEN:


This is JavaScript, should be cross browser compatible, and delivers without the ugly markup onerror="":

var sPathToDefaultImg = 'http://cdn.sstatic.net/stackexchange/img/logos/so/so-icon.png',
    validateImage = function( domImg ) {
        oImg = new Image();
        oImg.onerror = function() {
            domImg.src = sPathToDefaultImg;
        };
        oImg.src = domImg.src;
    },
    aImg = document.getElementsByTagName( 'IMG' ),
    i = aImg.length;

while ( i-- ) {
    validateImage( aImg[i] );
}

CODEPEN:


I created a fiddle to replace the broken image using "onerror" event. This may help you.

    //the placeholder image url
    var defaultUrl = "url('https://sadasd/image02.png')";

    $('div').each(function(index, item) {
      var currentUrl = $(item).css("background-image").replace(/^url\(['"](.+)['"]\)/, '$1');
      $('<img>', {
        src: currentUrl
      }).on("error", function(e) {
        $this = $(this);
        $this.css({
          "background-image": defaultUrl
        })
        e.target.remove()
      }.bind(this))
    })

I created a fiddle to replace the broken image using "onerror" event. This may help you.

    //the placeholder image url
    var defaultUrl = "url('https://sadasd/image02.png')";

    $('div').each(function(index, item) {
      var currentUrl = $(item).css("background-image").replace(/^url\(['"](.+)['"]\)/, '$1');
      $('<img>', {
        src: currentUrl
      }).on("error", function(e) {
        $this = $(this);
        $this.css({
          "background-image": defaultUrl
        })
        e.target.remove()
      }.bind(this))
    })

Here is an example using the HTML5 Image object wrapped by JQuery. Call the load function for the primary image URL and if that load causes an error, replace the src attribute of the image with a backup URL.

function loadImageUseBackupUrlOnError(imgId, primaryUrl, backupUrl) {
    var $img = $('#' + imgId);
    $(new Image()).load().error(function() {
        $img.attr('src', backupUrl);
    }).attr('src', primaryUrl)
}

<img id="myImage" src="primary-image-url"/>
<script>
    loadImageUseBackupUrlOnError('myImage','primary-image-url','backup-image-url');
</script>

Here is an example using the HTML5 Image object wrapped by JQuery. Call the load function for the primary image URL and if that load causes an error, replace the src attribute of the image with a backup URL.

function loadImageUseBackupUrlOnError(imgId, primaryUrl, backupUrl) {
    var $img = $('#' + imgId);
    $(new Image()).load().error(function() {
        $img.attr('src', backupUrl);
    }).attr('src', primaryUrl)
}

<img id="myImage" src="primary-image-url"/>
<script>
    loadImageUseBackupUrlOnError('myImage','primary-image-url','backup-image-url');
</script>

Pure JS. My task was: if image 'bl-once.png' is empty -> insert the first one (that hasn't 404 status) image from array list (in current dir):

_x000D_
_x000D_
<img src="http://localhost:63342/GetImage/bl-once.png" width="200" onerror="replaceEmptyImage.insertImg(this)">
_x000D_
_x000D_
_x000D_

Maybe it needs to be improved, but:

_x000D_
_x000D_
var srcToInsertArr = ['empty1.png', 'empty2.png', 'needed.png', 'notActual.png']; // try to insert one by one img from this array_x000D_
    var path;_x000D_
    var imgNotFounded = true; // to mark when success_x000D_
_x000D_
    var replaceEmptyImage = {_x000D_
        insertImg: function (elem) {_x000D_
_x000D_
            if (srcToInsertArr.length == 0) { // if there are no more src to try return_x000D_
                return "no-image.png";_x000D_
            }_x000D_
            if(!/undefined/.test(elem.src)) { // remember path_x000D_
                path = elem.src.split("/").slice(0, -1).join("/"); // "http://localhost:63342/GetImage"_x000D_
            }_x000D_
            var url = path + "/" + srcToInsertArr[0];_x000D_
_x000D_
            srcToInsertArr.splice(0, 1); // tried 1 src_x000D_
_x000D_
            _x000D_
                if(imgNotFounded){ // while not success_x000D_
                    replaceEmptyImage.getImg(url, path, elem); // CALL GET IMAGE_x000D_
                }_x000D_
            _x000D_
_x000D_
        },_x000D_
        getImg: function (src, path, elem) { // GET IMAGE_x000D_
_x000D_
            if (src && path && elem) { // src = "http://localhost:63342/GetImage/needed.png"_x000D_
                _x000D_
                var pathArr = src.split("/"); // ["http:", "", "localhost:63342", "GetImage", "needed.png"]_x000D_
                var name = pathArr[pathArr.length - 1]; // "needed.png"_x000D_
_x000D_
                xhr = new XMLHttpRequest();_x000D_
                xhr.open('GET', src, true);_x000D_
                xhr.send();_x000D_
_x000D_
                xhr.onreadystatechange = function () {_x000D_
_x000D_
                    if (xhr.status == 200) {_x000D_
                        elem.src = src; // insert correct src_x000D_
                        imgNotFounded = false; // mark success_x000D_
                    }_x000D_
                    else {_x000D_
                        console.log(name + " doesn't exist!");_x000D_
                        elem.onerror();_x000D_
                    }_x000D_
_x000D_
                }_x000D_
            }_x000D_
        }_x000D_
_x000D_
    };
_x000D_
_x000D_
_x000D_

So, it will insert correct 'needed.png' to my src or 'no-image.png' from current dir.


Pure JS. My task was: if image 'bl-once.png' is empty -> insert the first one (that hasn't 404 status) image from array list (in current dir):

_x000D_
_x000D_
<img src="http://localhost:63342/GetImage/bl-once.png" width="200" onerror="replaceEmptyImage.insertImg(this)">
_x000D_
_x000D_
_x000D_

Maybe it needs to be improved, but:

_x000D_
_x000D_
var srcToInsertArr = ['empty1.png', 'empty2.png', 'needed.png', 'notActual.png']; // try to insert one by one img from this array_x000D_
    var path;_x000D_
    var imgNotFounded = true; // to mark when success_x000D_
_x000D_
    var replaceEmptyImage = {_x000D_
        insertImg: function (elem) {_x000D_
_x000D_
            if (srcToInsertArr.length == 0) { // if there are no more src to try return_x000D_
                return "no-image.png";_x000D_
            }_x000D_
            if(!/undefined/.test(elem.src)) { // remember path_x000D_
                path = elem.src.split("/").slice(0, -1).join("/"); // "http://localhost:63342/GetImage"_x000D_
            }_x000D_
            var url = path + "/" + srcToInsertArr[0];_x000D_
_x000D_
            srcToInsertArr.splice(0, 1); // tried 1 src_x000D_
_x000D_
            _x000D_
                if(imgNotFounded){ // while not success_x000D_
                    replaceEmptyImage.getImg(url, path, elem); // CALL GET IMAGE_x000D_
                }_x000D_
            _x000D_
_x000D_
        },_x000D_
        getImg: function (src, path, elem) { // GET IMAGE_x000D_
_x000D_
            if (src && path && elem) { // src = "http://localhost:63342/GetImage/needed.png"_x000D_
                _x000D_
                var pathArr = src.split("/"); // ["http:", "", "localhost:63342", "GetImage", "needed.png"]_x000D_
                var name = pathArr[pathArr.length - 1]; // "needed.png"_x000D_
_x000D_
                xhr = new XMLHttpRequest();_x000D_
                xhr.open('GET', src, true);_x000D_
                xhr.send();_x000D_
_x000D_
                xhr.onreadystatechange = function () {_x000D_
_x000D_
                    if (xhr.status == 200) {_x000D_
                        elem.src = src; // insert correct src_x000D_
                        imgNotFounded = false; // mark success_x000D_
                    }_x000D_
                    else {_x000D_
                        console.log(name + " doesn't exist!");_x000D_
                        elem.onerror();_x000D_
                    }_x000D_
_x000D_
                }_x000D_
            }_x000D_
        }_x000D_
_x000D_
    };
_x000D_
_x000D_
_x000D_

So, it will insert correct 'needed.png' to my src or 'no-image.png' from current dir.


I found this post while looking at this other SO post. Below is a copy of the answer I gave there.

I know this is an old thread, but React has become popular and, perhaps, someone using React will come here looking for an answer to the same problem.

So, if you are using React, you can do something like the below, which was an answer original provided by Ben Alpert of the React team here

getInitialState: function(event) {
    return {image: "http://example.com/primary_image.jpg"};
},
handleError: function(event) {
    this.setState({image: "http://example.com/failover_image.jpg"});
},
render: function() {
    return (
        <img onError={this.handleError} src={src} />;
    );
}

I found this post while looking at this other SO post. Below is a copy of the answer I gave there.

I know this is an old thread, but React has become popular and, perhaps, someone using React will come here looking for an answer to the same problem.

So, if you are using React, you can do something like the below, which was an answer original provided by Ben Alpert of the React team here

getInitialState: function(event) {
    return {image: "http://example.com/primary_image.jpg"};
},
handleError: function(event) {
    this.setState({image: "http://example.com/failover_image.jpg"});
},
render: function() {
    return (
        <img onError={this.handleError} src={src} />;
    );
}

Better call using

jQuery(window).load(function(){
    $.imgReload();
});

Because using document.ready doesn't necessary imply that images are loaded, only the HTML. Thus, there is no need for a delayed call.


Better call using

jQuery(window).load(function(){
    $.imgReload();
});

Because using document.ready doesn't necessary imply that images are loaded, only the HTML. Thus, there is no need for a delayed call.


This has been frustrating me for years. My CSS fix sets a background image on the img. When a dynamic image src doesn't load to the foreground, a placeholder is visible on the img's bg. This works if your images have a default size (e.g. height, min-height, width and/or min-width).

You'll see the broken image icon but it's an improvement. Tested down to IE9 successfully. iOS Safari and Chrome don't even show a broken icon.

.dynamicContainer img {
  background: url('/images/placeholder.png');
  background-size: contain;
}

Add a little animation to give src time to load without a background flicker. Chrome fades in the background smoothly but desktop Safari doesn't.

.dynamicContainer img {
  background: url('/images/placeholder.png');
  background-size: contain;
  animation: fadein 1s;                     
}

@keyframes fadein {
  0%   { opacity: 0.0; }
  50%  { opacity: 0.5; }
  100% { opacity: 1.0; }
}

This has been frustrating me for years. My CSS fix sets a background image on the img. When a dynamic image src doesn't load to the foreground, a placeholder is visible on the img's bg. This works if your images have a default size (e.g. height, min-height, width and/or min-width).

You'll see the broken image icon but it's an improvement. Tested down to IE9 successfully. iOS Safari and Chrome don't even show a broken icon.

.dynamicContainer img {
  background: url('/images/placeholder.png');
  background-size: contain;
}

Add a little animation to give src time to load without a background flicker. Chrome fades in the background smoothly but desktop Safari doesn't.

.dynamicContainer img {
  background: url('/images/placeholder.png');
  background-size: contain;
  animation: fadein 1s;                     
}

@keyframes fadein {
  0%   { opacity: 0.0; }
  50%  { opacity: 0.5; }
  100% { opacity: 1.0; }
}

CoffeeScript variant:

I made it to fix an issue with Turbolinks that causes the .error() method to get raised in Firefox sometimes even though the image is really there.

$("img").error ->
  e = $(@).get 0
  $(@).hide() if !$.browser.msie && (typeof this.naturalWidth == "undefined" || this.naturalWidth == 0)

CoffeeScript variant:

I made it to fix an issue with Turbolinks that causes the .error() method to get raised in Firefox sometimes even though the image is really there.

$("img").error ->
  e = $(@).get 0
  $(@).hide() if !$.browser.msie && (typeof this.naturalWidth == "undefined" || this.naturalWidth == 0)

(window.jQuery || window.Zepto).fn.fallback = function (fallback) {
  return this.one('error', function () {
    var self = this;
    this.src = (fallback || 'http://lorempixel.com/$width/$height').replace(
      /\$(\w+)/g, function (m, t) { return self[t] || ''; }
    );
  });
};
    

You can pass a placeholder path and acces in it all properties from the failed image object via $*:

$('img').fallback('http://dummyimage.com/$widthx$height&text=$src');

http://jsfiddle.net/ARTsinn/Cu4Zn/


(window.jQuery || window.Zepto).fn.fallback = function (fallback) {
  return this.one('error', function () {
    var self = this;
    this.src = (fallback || 'http://lorempixel.com/$width/$height').replace(
      /\$(\w+)/g, function (m, t) { return self[t] || ''; }
    );
  });
};
    

You can pass a placeholder path and acces in it all properties from the failed image object via $*:

$('img').fallback('http://dummyimage.com/$widthx$height&text=$src');

http://jsfiddle.net/ARTsinn/Cu4Zn/


By using Prestaul's answer, I added some checks and I prefer to use the jQuery way.

<img src="image1.png" onerror="imgError(this,1);"/>
<img src="image2.png" onerror="imgError(this,2);"/>

function imgError(image, type) {
    if (typeof jQuery !== 'undefined') {
       var imgWidth=$(image).attr("width");
       var imgHeight=$(image).attr("height");

        // Type 1 puts a placeholder image
        // Type 2 hides img tag
        if (type == 1) {
            if (typeof imgWidth !== 'undefined' && typeof imgHeight !== 'undefined') {
                $(image).attr("src", "http://lorempixel.com/" + imgWidth + "/" + imgHeight + "/");
            } else {
               $(image).attr("src", "http://lorempixel.com/200/200/");
            }
        } else if (type == 2) {
            $(image).hide();
        }
    }
    return true;
}

By using Prestaul's answer, I added some checks and I prefer to use the jQuery way.

<img src="image1.png" onerror="imgError(this,1);"/>
<img src="image2.png" onerror="imgError(this,2);"/>

function imgError(image, type) {
    if (typeof jQuery !== 'undefined') {
       var imgWidth=$(image).attr("width");
       var imgHeight=$(image).attr("height");

        // Type 1 puts a placeholder image
        // Type 2 hides img tag
        if (type == 1) {
            if (typeof imgWidth !== 'undefined' && typeof imgHeight !== 'undefined') {
                $(image).attr("src", "http://lorempixel.com/" + imgWidth + "/" + imgHeight + "/");
            } else {
               $(image).attr("src", "http://lorempixel.com/200/200/");
            }
        } else if (type == 2) {
            $(image).hide();
        }
    }
    return true;
}

If you have inserted your img with innerHTML, like: $("div").innerHTML = <img src="wrong-uri">, you can load another image if it fails doing, e.g, this:

<script>
    function imgError(img) {
        img.error="";
        img.src="valid-uri";
    }
</script>

<img src="wrong-uri" onerror="javascript:imgError(this)">

Why is javascript: _needed? Because scripts injected into the DOM via script tags in innerHTML are not run at the time they are injected, so you have to be explicit.


If you have inserted your img with innerHTML, like: $("div").innerHTML = <img src="wrong-uri">, you can load another image if it fails doing, e.g, this:

<script>
    function imgError(img) {
        img.error="";
        img.src="valid-uri";
    }
</script>

<img src="wrong-uri" onerror="javascript:imgError(this)">

Why is javascript: _needed? Because scripts injected into the DOM via script tags in innerHTML are not run at the time they are injected, so you have to be explicit.


jQuery 1.8

// If missing.png is missing, it is replaced by replacement.png
$( "img" )
  .error(function() {
    $( this ).attr( "src", "replacement.png" );
  })
  .attr( "src", "missing.png" );

jQuery 3

// If missing.png is missing, it is replaced by replacement.png
$( "img" )
  .on("error", function() {
    $( this ).attr( "src", "replacement.png" );
  })
  .attr( "src", "missing.png" );

reference


I solved my problem with these two simple functions:

function imgExists(imgPath) {
    var http = jQuery.ajax({
                   type:"HEAD",
                   url: imgPath,
                   async: false
               });
    return http.status != 404;
}

function handleImageError() {
    var imgPath;

    $('img').each(function() {
        imgPath = $(this).attr('src');
        if (!imgExists(imgPath)) {
            $(this).attr('src', 'images/noimage.jpg');
        }
    });
}

I solved my problem with these two simple functions:

function imgExists(imgPath) {
    var http = jQuery.ajax({
                   type:"HEAD",
                   url: imgPath,
                   async: false
               });
    return http.status != 404;
}

function handleImageError() {
    var imgPath;

    $('img').each(function() {
        imgPath = $(this).attr('src');
        if (!imgExists(imgPath)) {
            $(this).attr('src', 'images/noimage.jpg');
        }
    });
}

I am not sure if there is a better way, but I can think of a hack to get it - you could Ajax post to the img URL, and parse the response to see if the image actually came back. If it came back as a 404 or something, then swap out the img. Though I expect this to be quite slow.


I am not sure if there is a better way, but I can think of a hack to get it - you could Ajax post to the img URL, and parse the response to see if the image actually came back. If it came back as a 404 or something, then swap out the img. Though I expect this to be quite slow.


I am not sure if there is a better way, but I can think of a hack to get it - you could Ajax post to the img URL, and parse the response to see if the image actually came back. If it came back as a 404 or something, then swap out the img. Though I expect this to be quite slow.


I am not sure if there is a better way, but I can think of a hack to get it - you could Ajax post to the img URL, and parse the response to see if the image actually came back. If it came back as a 404 or something, then swap out the img. Though I expect this to be quite slow.


I think I have a more elegant way with event delegation and event capturing on window's error even when the backup image fail to load.

_x000D_
_x000D_
img {_x000D_
  width: 100px;_x000D_
  height: 100px;_x000D_
}
_x000D_
<script>_x000D_
  window.addEventListener('error', windowErrorCb, {_x000D_
    capture: true_x000D_
  }, true)_x000D_
_x000D_
  function windowErrorCb(event) {_x000D_
    let target = event.target_x000D_
    let isImg = target.tagName.toLowerCase() === 'img'_x000D_
    if (isImg) {_x000D_
      imgErrorCb()_x000D_
      return_x000D_
    }_x000D_
_x000D_
    function imgErrorCb() {_x000D_
      let isImgErrorHandled = target.hasAttribute('data-src-error')_x000D_
      if (!isImgErrorHandled) {_x000D_
        target.setAttribute('data-src-error', 'handled')_x000D_
        target.src = 'backup.png'_x000D_
      } else {_x000D_
        //anything you want to do_x000D_
        console.log(target.alt, 'both origin and backup image fail to load!');_x000D_
      }_x000D_
    }_x000D_
  }_x000D_
</script>_x000D_
<img id="img" src="error1.png" alt="error1">_x000D_
<img id="img" src="error2.png" alt="error2">_x000D_
<img id="img" src="https://i.stack.imgur.com/ZXCE2.jpg" alt="avatar">
_x000D_
_x000D_
_x000D_

The point is :

  1. Put the code in the head and executed as the first inline script. So, it will listen the errors happen after the script.

  2. Use event capturing to catch the errors, especially for those events which don't bubble.

  3. Use event delegation which avoids binding events on each image.

  4. Give the error img element an attribute after giving them a backup.png to avoid disappearance of the backup.png and subsequent infinite loop like below:

img error->backup.png->error->backup.png->error->,,,,,


I think I have a more elegant way with event delegation and event capturing on window's error even when the backup image fail to load.

_x000D_
_x000D_
img {_x000D_
  width: 100px;_x000D_
  height: 100px;_x000D_
}
_x000D_
<script>_x000D_
  window.addEventListener('error', windowErrorCb, {_x000D_
    capture: true_x000D_
  }, true)_x000D_
_x000D_
  function windowErrorCb(event) {_x000D_
    let target = event.target_x000D_
    let isImg = target.tagName.toLowerCase() === 'img'_x000D_
    if (isImg) {_x000D_
      imgErrorCb()_x000D_
      return_x000D_
    }_x000D_
_x000D_
    function imgErrorCb() {_x000D_
      let isImgErrorHandled = target.hasAttribute('data-src-error')_x000D_
      if (!isImgErrorHandled) {_x000D_
        target.setAttribute('data-src-error', 'handled')_x000D_
        target.src = 'backup.png'_x000D_
      } else {_x000D_
        //anything you want to do_x000D_
        console.log(target.alt, 'both origin and backup image fail to load!');_x000D_
      }_x000D_
    }_x000D_
  }_x000D_
</script>_x000D_
<img id="img" src="error1.png" alt="error1">_x000D_
<img id="img" src="error2.png" alt="error2">_x000D_
<img id="img" src="https://i.stack.imgur.com/ZXCE2.jpg" alt="avatar">
_x000D_
_x000D_
_x000D_

The point is :

  1. Put the code in the head and executed as the first inline script. So, it will listen the errors happen after the script.

  2. Use event capturing to catch the errors, especially for those events which don't bubble.

  3. Use event delegation which avoids binding events on each image.

  4. Give the error img element an attribute after giving them a backup.png to avoid disappearance of the backup.png and subsequent infinite loop like below:

img error->backup.png->error->backup.png->error->,,,,,


jQuery 1.8

// If missing.png is missing, it is replaced by replacement.png
$( "img" )
  .error(function() {
    $( this ).attr( "src", "replacement.png" );
  })
  .attr( "src", "missing.png" );

jQuery 3

// If missing.png is missing, it is replaced by replacement.png
$( "img" )
  .on("error", function() {
    $( this ).attr( "src", "replacement.png" );
  })
  .attr( "src", "missing.png" );

reference


Sometimes using the error event is not feasible, e.g. because you're trying to do something on a page that’s already loaded, such as when you’re running code via the console, a bookmarklet, or a script loaded asynchronously. In that case, checking that img.naturalWidth and img.naturalHeight are 0 seems to do the trick.

For example, here's a snippet to reload all broken images from the console:

$$("img").forEach(img => {
  if (!img.naturalWidth && !img.naturalHeight) {
    img.src = img.src;
  }
}

Sometimes using the error event is not feasible, e.g. because you're trying to do something on a page that’s already loaded, such as when you’re running code via the console, a bookmarklet, or a script loaded asynchronously. In that case, checking that img.naturalWidth and img.naturalHeight are 0 seems to do the trick.

For example, here's a snippet to reload all broken images from the console:

$$("img").forEach(img => {
  if (!img.naturalWidth && !img.naturalHeight) {
    img.src = img.src;
  }
}

If the image cannot be loaded (for example, because it is not present at the supplied URL), image URL will be changed into default,

For more about .error()

_x000D_
_x000D_
$('img').on('error', function (e) {_x000D_
  $(this).attr('src', 'broken.png');_x000D_
});
_x000D_
_x000D_
_x000D_


If the image cannot be loaded (for example, because it is not present at the supplied URL), image URL will be changed into default,

For more about .error()

_x000D_
_x000D_
$('img').on('error', function (e) {_x000D_
  $(this).attr('src', 'broken.png');_x000D_
});
_x000D_
_x000D_
_x000D_


I use lazy load and have to do this in order to make it work properly:

lazyload();

var errorURL = "https://example.com/thisimageexist.png";

$(document).ready(function () {
  $('[data-src]').on("error", function () {
    $(this).attr('src', errorURL);
  });
});

I use lazy load and have to do this in order to make it work properly:

lazyload();

var errorURL = "https://example.com/thisimageexist.png";

$(document).ready(function () {
  $('[data-src]').on("error", function () {
    $(this).attr('src', errorURL);
  });
});

I got the same problem. This code works well on my case.

// Replace broken images by a default img
$('img').each(function(){
    if($(this).attr('src') === ''){
      this.src = '/default_feature_image.png';
    }
});

I got the same problem. This code works well on my case.

// Replace broken images by a default img
$('img').each(function(){
    if($(this).attr('src') === ''){
      this.src = '/default_feature_image.png';
    }
});

I found this to work best, if any image fails to load the first time, it is completely removed from the DOM. Executing console.clear() keeps the console window clean, since the 404 errors cannot be omitted with try/catch blocks.

$('img').one('error', function(err) {
    // console.log(JSON.stringify(err, null, 4))
    $(this).remove()
    console.clear()
})

I found this to work best, if any image fails to load the first time, it is completely removed from the DOM. Executing console.clear() keeps the console window clean, since the 404 errors cannot be omitted with try/catch blocks.

$('img').one('error', function(err) {
    // console.log(JSON.stringify(err, null, 4))
    $(this).remove()
    console.clear()
})

Questions with javascript tag:

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax Drag and drop menuitems Is it possible to execute multiple _addItem calls asynchronously using Google Analytics? DevTools failed to load SourceMap: Could not load content for chrome-extension TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined raised when starting react app What does 'x packages are looking for funding' mean when running `npm install`? SyntaxError: Cannot use import statement outside a module SameSite warning Chrome 77 "Uncaught SyntaxError: Cannot use import statement outside a module" when importing ECMAScript 6 Why powershell does not run Angular commands? Typescript: No index signature with a parameter of type 'string' was found on type '{ "A": string; } Uncaught Invariant Violation: Too many re-renders. React limits the number of renders to prevent an infinite loop Push method in React Hooks (useState)? JS file gets a net::ERR_ABORTED 404 (Not Found) React Hooks useState() with Object useState set method not reflecting change immediately Can't perform a React state update on an unmounted component UnhandledPromiseRejectionWarning: This error originated either by throwing inside of an async function without a catch block Can I set state inside a useEffect hook internal/modules/cjs/loader.js:582 throw err How to post query parameters with Axios? How to use componentWillMount() in React Hooks? React Hook Warnings for async function in useEffect: useEffect function must return a cleanup function or nothing FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory in ionic 3 How can I force component to re-render with hooks in React? What is useState() in React? How to call loading function with React useEffect only once Objects are not valid as a React child. If you meant to render a collection of children, use an array instead How to reload current page? Center content vertically on Vuetify Getting all documents from one collection in Firestore ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment How can I add raw data body to an axios request? Sort Array of object by object field in Angular 6 Uncaught SyntaxError: Unexpected end of JSON input at JSON.parse (<anonymous>) Axios Delete request with body and headers? Enable CORS in fetch api Vue.js get selected option on @change Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) Angular 6: How to set response type as text while making http call

Questions with jquery tag:

How to make a variable accessible outside a function? Jquery assiging class to th in a table Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Getting all files in directory with ajax Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) bootstrap 4 file input doesn't show the file name Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource how to remove json object key and value.? How to solve 'Redirect has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header'? Ajax LARAVEL 419 POST error Laravel 5.5 ajax call 419 (unknown status) Only on Firefox "Loading failed for the <script> with source" How to prevent page from reloading after form submit - JQuery Vue component event after render How to use jQuery Plugin with Angular 4? How to disable a ts rule for a specific line? Bootstrap 4 File Input How to force reloading a page when using browser back button? Datatables Select All Checkbox Unable to preventDefault inside passive event listener Getting Error "Form submission canceled because the form is not connected" How to create multiple page app using react Set height of chart in Chart.js console.log(result) returns [object Object]. How do I get result.name? Setting and getting localStorage with jQuery JQuery: if div is visible Using OR operator in a jquery if statement Deprecation warning in Moment.js - Not in a recognized ISO format How to use aria-expanded="true" to change a css property DataTables: Cannot read property style of undefined Disable Chrome strict MIME type checking Consider marking event handler as 'passive' to make the page more responsive Cannot open local file - Chrome: Not allowed to load local resource "Uncaught TypeError: a.indexOf is not a function" error when opening new foundation project what is right way to do API call in react js? why $(window).load() is not working in jQuery? How to use JQuery with ReactJS $(...).datepicker is not a function - JQuery - Bootstrap remove first element from array and return the array minus the first element How to use a jQuery plugin inside Vue Uncaught SyntaxError: Invalid or unexpected token jquery 3.0 url.indexOf error How to redirect page after click on Ok button on sweet alert? Content Security Policy: The page's settings blocked the loading of a resource Uncaught SyntaxError: Failed to execute 'querySelector' on 'Document' Checkbox value true/false vue.js 'document.getElementById' shorthand Removing legend on charts with chart.js v2

Questions with html tag:

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment Angular 6: saving data to local storage Vue.js get selected option on @change Bootstrap 4 multiselect dropdown How to add bootstrap in angular 6 project? Angular 5 Button Submit On Enter Key Press Angular 5, HTML, boolean on checkbox is checked How to render string with html tags in Angular 4+? bootstrap 4 file input doesn't show the file name How can I execute a python script from an html button? Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width Failed to load resource: the server responded with a status of 404 (Not Found) css Change arrow colors in Bootstraps carousel Bootstrap 4 Dropdown Menu not working? CSS Grid Layout not working in IE11 even with prefixes How to prevent page from reloading after form submit - JQuery Centering in CSS Grid Detecting real time window size changes in Angular 4 Angular 4 img src is not found (change) vs (ngModelChange) in angular Bootstrap 4: Multilevel Dropdown Inside Navigation Align the form to the center in Bootstrap 4 How to style a clicked button in CSS How do I change the font color in an html table? Redirecting to a page after submitting form in HTML Load json from local file with http.get() in angular 2 display: flex not working on Internet Explorer Scroll to element on click in Angular 4 How to extract svg as file from web page force css grid container to fill full screen of device How does the "position: sticky;" property work? HTML5 Video autoplay on iPhone Disable button in angular with two conditions? CSS hide scroll bar, but have element scrollable CSS grid wrapping How to load image (and other assets) in Angular an project? Flask - Calling python function on button OnClick event How can I make Bootstrap 4 columns all the same height? Wrapping a react-router Link in an html button

Questions with brokenimage tag:

jQuery/JavaScript to replace broken images