Skip to contentSkip to footer

If you want to be kept up to date with new articles, CSS resources and tools, join our newsletter.

Broken links, or "dead links", on your website are links that go to a URL that doesn't work. Sometimes this is because the site you're linking to has gone offline or has a server error, sometimes it's because there is a spelling mistake in your link. Detecting these is difficult: you don't click on each url on each page every time you make a change, since that simply would take too much time.

Waiting for your visitors to tell you about broken links is also not a great strategy. Sending them to a URL that doesn't work and then waiting for them to tell you is not a great user experience, and very few visitors will take the effort to notify you. Additionally, a page that has broken links is an indicator for search engines that the content is probably outdated or low quality.

With Polypane, you can check for broken links automatically and detect not just broken links but also unneeded redirects. Before we show you how to check for broken links, first a short primer:

Roughly there are two types of broken links, those with a 4xx status code and those with a 5xx status code.

A 400 status code means you made an error.

A 500 status code means the server made an error.

For example, a "404 not found" means that while the server got and understood your requests, the thing you tried to find was not there. A "500 internal server error" means there was an error in the code of the server that it couldn't recover from.

Those two are the most important, but if you're checking for broken links there are a few others you might encounter in the wild. While this isn't an exhaustive list, they're the ones you'll see most often.

4xx errors, a.k.a. "You messed up"

  • 400 Bad Request There was something wrong with the request, like an error in the request syntax.
  • 401 Unauthorized/403 Forbidden Both can be used to indicate a user does not have the rights to access this link, for example because they're not logged in yet.
  • 404 Not Found as mentioned, this means the URL doesn't exist.
  • 405 Method not Allowed Some URLS can only be accessed with a GET or a POST, but you used a different method.
  • 410 Gone Like a 404, but explicity communicates that there was a resource and it's now been removed.
  • 429 Too Many Requests Some servers might rate limit how often you can open a URL to prevent abuse, they can use this status code.
  • 451 Unavailable for Legal Reasons When a URL is not available because of some legal demand. "Fun" fact: the error code is a reference to the novel Fahrenheit 451.

5xx errors, a.k.a. "We messed up"

  • 500 Internal Server Error As mentioned, the server crashed while trying to respond.
  • 501 Not Implemented Usually used to indicate something will eventually be implemented.
  • 502 Bad Gateway When the server is used as a proxy or gateway, but it got a bad response from the server it was proxying too. For example when you run Nginx as a proxy for a Django, Rails or Express.js server, and that server is down.
  • 503 Service Unavailable Usually sent when the server is over capacity (too many requests, not enough memory, etc.)

There's (much) more error codes than just these (like 418 I'm a teapot, look it up), but they're the ones you see most often "in the wild".

3xx status codes: "Look elsewhere"

When you start testing for broken links you'll soon find URLs returning a code in the 3xx range. Those are used to indicate a resource has moved, either temporarily or permanently. While not a big issue (the URLs still work) these are nice to fix, as you don't know if the redirects will be available forever, and there is a (tiny) performance cost because your browser needs to send a second request to the correct URL.

  • 301 Moved Permanently Used to indicate that the resource has moved to this new location forever. Due to the way the spec was written, a 301 can switch from a POST to a GET.
  • 302 Found Used to indicate that the resource is now moved elsewhere. While this one is still in widespread use, you should really use either 303 or 307.
  • 303 See Other Replaces 302 specifically in the situations where you can GET the resource elsewhere.
  • 304 Not Modified If the resource hasn't changed, your browser can safely get it from the Cache for a faster turnaround.
  • 307 Temporary redirect Same as 302 Found but more explicit in its intent. You can not change the HTTP Method (so a POST stays a POST).
  • 308 Permanent redirect Same as 301 Moved Permanently but more explicit in its intent. You can not change the HTTP Method (so a POST stays a POST).

Some of these are a little vague and seem to overlap, because some details do not really have a material effect on how your browser behaves.

In practice, you'll see 301 and 302 the most, though I assume that will slowly switch over to 307 and 308.

With that little primer out of the way, lets discover how to find and fix broken links in Polypane.

When you open a page in Polypane, the Outline panel parses it to find all the links on the page. To head to the Outline panel, first open the side panel (with ctrl/cmd shift +p, or by clicking the side panel button in the header), going to "Info" and then to the "Outline" tab. By default, Polypane shows the list of headers, but click the dropdown to switch to "links". Make sure "Show issues" is checked.

Outline panel overview

The links are shown in order with their accessible text content and the URL they go to, this is a great overview to check if all your links have names that make sense (and that they're not all just "Read more").

At the same time, Polypane is checking each URL to detect which status code is returned.

When it's done, it will prefix the status to each URL:

  • White text on a red background is a big issue, like a broken link.
  • Red text is a minor issue, like a redirect or server issue.
  • A checkmark means everything is okay (we got a 200 status code).
  • A question mark means we couldn't verify a url because it was blocked or returned a 429 status code.

Fixing big issues

Obviously, fixing broken links (those with a 404) are highest priority:

Example of the broken links

Find out why a url is now offline and where it was moved too (old urls not properly redirecting happens more often than you think), find a suitable alternative or remove the link from your page altogether.

Fixing minor issues

Server issues are big problems but usually not something you can directly do something about (unless it happens on your server!) If the server error comes from a third party website, be kind and let them know which URLs are broken (or point them to Polypane. ;)

It shouldn't be a high priority to fix 301 or 302 (or 307/308) but usually it's an easy fix. A really common one is the link not ending in a /, but the server automatically adding one to all URLs.

For example, the "articles" link in the main navigation on Smashing Magazine is missing that /:

Example of an unneeded redirect

The actual URL is /articles/, with the / at the end. When they add that / in the HTML, the redirect is solved.

Not all redirects can be solved however, as some might be contextual. The links to our dashboard for example might redirect you to log in, and otherwise to the main account overview.

There are two other issues that the Outline panel will highlight: not using HTTPS and missing a rel="noopener" link.

Not using HTTPS

Using HTTPS makes the web more secure and more private, but it's an easy mistake to link to the HTTP version of a URL since it usually forwards to HTTPS anyway.

It's such an easy mistake, the offical website of the White House made it right in the middle of their homepage (this has since been fixed):

Screenshot of the whitehouse.gov website with the link to Twitter circledThat same link with a 'no-https' badge in the Outline panel

Any URL that does not use HTTPS will have a "non-HTTPS" badge visible. For example, the link to Latinotype in the SmashingMagazine footer is using HTTP, despite both sites supporting HTTPS:

Example of the 'no HTTPS' badge

Using target="_blank" without rel="noopener"

When you add target="_blank" to open it in in a new tab, you are actually giving the page you opened access to your window object, which is a security risk. You can prevent this by adding rel="noopener" to the same link.

Firefox since version 79 and Chrome since 88 have added this to URLs by default, but users using older browser like Edge Legacy or Internet Explorer are still at risk, so Polypane warns you about this issue too.

Example of the missing rel warning

We show a warning for URL that uses target="_blank" but does not have a rel="noopener" or rel="noreferrer attribute.

Try it for yourself

Polypane is available with a 14 day free trial, enough time to check all the pages on your site. Start a trial now.

Build your next project with Polypane

  • Use all features on all plans
  • On Mac, Window and Linux
  • 14-day free trial – no credit card needed
Try for free
Polypane screenshot