I suspect the following is actually a bug in the HTML/JS specification rather than WebKit's implementation of it (although I wasn't able to locate which standard applied); if there is a better place to submit this then please let me know. Currently, the <iframe> element raises the onload event regardless of whether loading succeeds or fails. It should raise onload only if loading succeeds, and onerror if it fails. This should work regardless of whether the page being loaded is at the same origin or not, and the network error type or HTTP status code should be accessible, in order to allow JS code to properly distinguish load failures. Of course, if the page being loaded is not at the same origin, then the actual *content* of the successfully loaded page should be inaccessible as usual. As it stands it appears to be completely impossible to determine from the containing page whether or not the iframe loading succeeded or failed. As I want to be able to provide alternate content (either by changing the iframe src or srcDoc or by hiding the iframe and displaying a static div instead), this breaks things for me. (Note that in my case I want to be able to load pages from a different origin and I do not want to access their content, just the success/failure of loading, treating 404 etc as failure. As such the remote site should not need to be CORS-enabled.) Given the prevalence of related questions on stackoverflow.com, I don't think this is an isolated use case, and there don't appear to be any good workarounds. (The only known workaround is to enable CORS and examine the loaded content, and/or to switch to XHR, which are both counterproductive.)
FWIW, in the interim I've worked around this by running an XHR HEAD request first, and setting the iframe src only if that succeeds. This is an unsatisfactory workaround as it requires three server hits instead of just one (as the XHR sends OPTIONS+HEAD, and then the iframe sends GET), and it requires that the target page be CORS-enabled, which should not be required for this scenario. (There's also the possibility that the HEAD succeeds but then the GET fails, if the server happens to die in the interim, but this seems unlikely enough that it can probably be ignored fairly safely.)
This needs a testcase and a test across browsers.