HTTP 200 Does Not Mean the URL Is Correct

Does your link checker treat a 200 as proof that everything is fine? In practice, a server may forward you to the right page with a 301 even when part of the URL is wrong. To a checker that follows redirects, a wrong URL and a correct one produce exactly the same 200. This article sets out the blind spot and how to detect it, based on measurements taken on 4 August 2026.

About the measurements: the HTTP statuses below were obtained by the author with curl on 4 August 2026. Behaviour can change when a service changes its implementation, so reproduce it yourself before relying on it. The steps are given in the article.

What link checking misses

Auditing an internal link list, the references inside articles, or a pile of bookmarks. When you want to verify mechanically that a URL is alive, most implementations do this:

  1. Send a GET (or HEAD) to the URL
  2. Follow redirects
  3. Record it as alive if the final status is 2xx

This detects whether a URL is broken, but not whether a URL is wrong. Those are different things. The first is the server returning 404; the second is the server helpfully forwarding you to the right place, so a wrong URL still returns 200.

Measured: a wrong username still returns 200

Services that put the author's name in the article URL make this especially likely. Using the slug of a real article on a technical article-sharing service and changing only the username segment of the path, the results were as follows (measured 4 August 2026).

Shape of the requested URLStatusLocation
Correct author name + real slug200(none)
A different real author's name + real slug301The true author's URL (with ?redirected=1)
A username that does not exist + real slug301Same as above
Correct author name + a slug that does not exist404(none)

The conclusion is unambiguous: this service resolves an article by its slug alone, and the username segment of the path carries no authority. Put in a username that does not exist, or a different real person's name, and you are absorbed by a 301 into the true owner's URL. Conversely, if the slug does not exist you get 404 even with the correct username.

To a checker that follows redirects, all of these are "final 200". A link with a mistyped username and a link left over from before the author renamed themselves look exactly as healthy as a correct one.

Why services are built this way: it is not behaviour to blame. It exists so that renaming a user does not kill every existing link. The same idea is everywhere: GitHub username changes, handle changes on social platforms, CMS permalinks keyed on an article ID. Structures where part of the URL is decoration and the real lookup uses a different key are common. The problem is not the behaviour but a checker that does not account for it.

Why it matters

Detection method 1: compare the requested URL with the final URL

The simplest method, and it works on any service. Follow redirects, then check whether the final URL equals the original. With curl, %{url_effective} gives you the final URL.

# Print the final URL alongside the status
curl -sL -o /dev/null \
     -w 'status=%{http_code}\nfinal=%{url_effective}\n' \
     "$URL"

# Observe the 3xx directly, without following it
curl -s -o /dev/null \
     -w 'status=%{http_code}\nlocation=%{redirect_url}\n' \
     "$URL"

Split the verdict like this and the blind spot disappears.

ObservationMeaningTreat as
200, and final URL equals the originalThe URL is correct and aliveOK
200, but final URL differsYou were redirected; the stored URL is stale or wrongNeeds review (update the link to the final URL)
3xx (observed without following)Same as aboveNeeds review
4xx / 5xxBrokenNG

When comparing, remember to ignore tracking query parameters the service adds. In the measurement above, the redirect target carries ?redirected=1. Compare the strings with that included and the link will be flagged as mismatched forever, even after you correct it. Strip the query, or remove known parameters, before comparing.

Detection method 2: verify ownership through a public API

Matching URLs still does not tell you whose article it is. Where a service offers a public API, the reliable check is to fetch the article list for a username and confirm that the slug you care about is in it. The service above has an endpoint that needed no authentication and returned JSON in this shape on 4 August 2026.

# List a user's articles (no authentication; measured 2026-08-04)
curl -s "https://zenn.dev/api/articles?username=<name>&order=latest"

# Response shape (excerpt)
{
  "articles": [
    {
      "slug": "66fc12c8dc1f61",
      "path": "/<name>/articles/66fc12c8dc1f61",
      "published_at": "2026-08-04T09:31:15.165+09:00",
      "article_type": "tech",
      "user": { "username": "<name>" }
    }
  ]
}

That path is the canonical path of the article as that user's work. If a URL in your link list is not among them, you can conclude that the username is wrong, or that ownership of the article has moved. A status code can never tell you that.

Manners when calling a public API: requiring no authentication is not permission to hammer it. Space out your requests, put a contact address in your User-Agent, cache responses to avoid refetching, stop and back off on a 429, and read robots.txt and the terms of service. Monitoring runs continuously, so it becomes a load problem far more easily than a one-off script does.

Generalising: which part of a URL is the real key?

This is not a quirk of one service but a general property of URL design. On many sites a URL combines two kinds of component:

Working out which parts of the URLs you monitor are key and which are decoration reduces both false positives and blind spots. Finding out is easy: deliberately break the part you believe is decoration and see whether you get a 404 or a 301. That is exactly what the measurement above did.

It also helps to look at the kind of redirect. A permanent move (301 or 308) means you should rewrite your stored link; a temporary one (302 or 307) means you should not. For an overview of status codes, see An Introduction to HTTP Status Codes.

Checklist

  1. Does your checker record the final URL, rather than only the status?
  2. Does it compare the original and final URLs, after stripping tracking query parameters?
  3. Does it treat 301 and 308 as needs updating rather than simply OK?
  4. Do you verify that person and category names inside a URL are correct by some means other than the URL?
  5. If your monitoring calls an API, have you settled on an interval, a User-Agent, caching and 429 handling?

How to reproduce the measurements (4 August 2026)

  • Get a real article slug from the public API: curl -s "https://zenn.dev/api/articles?order=latest"
  • Replace the username segment with (1) the correct name, (2) a different real user's name, and (3) a name that does not exist, then run curl -s -o /dev/null -w '%{http_code} %{redirect_url}'
  • Replace the slug with a value that does not exist and repeat the observation
  • Confirm that the <link rel="canonical"> of the redirected page points at the true owner's URL without the query string

All of the above were run by the author. A service's implementation can change, so this is not a permanent specification.

Frequently Asked Questions

If a link checker gets a 200, does that mean the URL is correct?

No. A service may be designed to redirect a partially wrong URL to the correct one with a 301. A checker that follows redirects sees a final status of 200, so a wrong URL looks just as healthy as a correct one.

How can I detect a wrong URL?

Compare the requested URL with the final URL. With curl, -w '%{url_effective}' gives you the final URL. Strip any tracking query parameters the service adds, such as ?redirected=1, before comparing. Observing the 3xx directly without following it also works.

How do I verify that the username inside a URL is correct?

A status code cannot tell you. Where the service offers a public API, fetch the article list for that username and check whether the slug you care about appears in it. If it does not, the username is wrong or ownership has moved.

How do I work out which parts of a URL can be wrong and still redirect?

Deliberately break the part you believe is decoration and see whether you get a 404 or a 301. The part that produces a 404 is the key used to look up the resource; the part that is absorbed by a 301 is human-facing decoration.

← Back to Tech Blog