Fixing Hreflang That Points at 404s or Redirects
Every address listed in a hreflang annotation should answer with a working page straight away. When an alternate returns a 404, a server error or a redirect to somewhere else, Google cannot use that link, and the locale it represents quietly drops out of the cluster.
These faults usually appear after a page is deleted, a slug is renamed, a market is closed or a site is migrated, and nobody updates the annotations. This guide shows how to test every target, how to read each type of failure, what the correct repair is for each, and how to catch new breakages before they ship.
What counts as a broken target
A hreflang target is the address in the href of an alternate link, or in the href
of an xhtml:link entry in a sitemap. For Google to use it, the request for that exact address
should return status 200 with the page itself. Anything else is a problem of some kind:
| Response | What it means for the cluster | Usual repair |
|---|---|---|
| 404 Not Found | The locale page is missing; the annotation is useless | Restore the page, point at the right address, or remove the line everywhere |
| 410 Gone | The page was removed on purpose | Remove the locale from every page in the cluster |
| 301 or 308 permanent redirect | The annotation points at an old address | Replace it with the final address |
| 302 or 307 temporary redirect | Often a geo, language or login redirect | Stop redirecting crawlers, or list the real page |
| 5xx server error | The page may exist but failed when requested | Fix the server fault; retest before editing annotations |
| 200 with an error message | A soft 404: looks fine to a status check, but is empty | Return a real 404 or restore the content |
Redirects deserve a closer look because they seem harmless. A visitor who follows a redirect still
arrives somewhere useful, so the page appears to work. But hreflang is a statement about specific addresses.
If the British page names /de/zubehoer/ and that address redirects to /de/zubehor/,
the German page's own annotations will name the new address, not the old one, so the pair no longer matches.
A redirected target very often creates a return tag error as a side effect.
Where broken targets come from
- Deleted content in one locale only. A seasonal product is removed from the French store but kept elsewhere. The other locales still list the French address, which now returns 404.
- Slug changes after publishing. An editor improves a translated slug. The CMS adds a redirect for visitors, but annotations stored as text, or cached pages, keep the old address.
- Site migrations. Moving from
example.frtoexample.com/fr/, or changing the folder pattern from/fr/to/fr-fr/, turns every old address into a redirect. Annotations generated before the move keep pointing at them. - Markets closed or paused. A country store is switched off and its domain redirected to the main site, but the remaining locales still list it.
- Protocol and host changes. Moving to https, or between
wwwand the bare domain, adds a redirect in front of every hard-coded address. - Geo or language redirects. A server that sends visitors to a country version by IP address or browser language gives crawlers a redirect instead of the page. Because Google mostly crawls from the United States, it may never see the non-US versions.
- Relative addresses. An
hrefsuch as/fr/page/orfr/page/is not a fully qualified address. Google's documentation asks for absolute URLs including the protocol, and relative ones are easy to resolve incorrectly.
Testing every target
The Hreflang Checker probes each target in the clusters it follows and reports the ones that are not reachable, which is the quickest way to see the scale of the problem. For a full-site inventory, extract the targets and request them yourself. The key is to request each address without following redirects, so you see the first response rather than the final destination.
For a single address:
curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" "https://example.com/de/zubehoer/"
For a list of addresses in a file, one per line, a short loop reports everything that is not a plain 200:
while read -r url; do
out=$(curl -s -o /dev/null --max-time 10 -w "%{http_code} %{redirect_url}" "$url")
code=${out%% *}
[ "$code" != "200" ] && echo "$code $url -> ${out#* }"
done < hreflang_targets.txt
If your annotations are in a sitemap, you can build that list from the sitemap itself:
curl -s https://example.com/sitemap.xml \
| grep -o 'xhtml:link[^>]*href="[^"]*"' \
| sed 's/.*href="\([^"]*\)"/\1/' \
| sort -u > hreflang_targets.txt
For sites with a sitemap index, repeat for each child sitemap. For HTML annotations, export the targets
from a crawler instead, because parsing HTML with grep is unreliable.
Spotting soft 404s
A status check will not catch pages that return 200 with "product not found" or an empty template. Two quick signals help: pages whose size is far smaller than others of the same type, and pages whose title contains words such as "not found" or "no longer available" in any of your languages. Check those by hand.
Choosing the right repair
Group the failures by cause before editing anything. The same fix usually applies to hundreds of addresses at once.
Redirected targets
Replace each redirecting address with the address it finally lands on, but only after checking that the final page is the correct equivalent. After a migration, the redirect map you used for the move is the best source: it already pairs every old address with its new one. Apply it to the annotations, not just to the server.
Missing or gone targets
Ask whether an equivalent page should exist. If the product or article was translated and the page was removed by mistake, restore it. If it was moved, use the new address. If the locale no longer has that content, remove the locale from the cluster on every page, not just one, otherwise you trade a broken target for a return tag error. Never replace a missing translation with the locale's home page or a category page; that is not an equivalent.
Temporary redirects
A 302 or 307 on a hreflang target is usually a redirect based on location, language or cookies. Turn it off for the addresses in your clusters and offer a visible country or language switcher instead. If the redirect exists because the target needs a login, that page should not be in a hreflang cluster.
Server errors
Retest 5xx responses a few times. An intermittent fault points at load, timeouts or a bad deployment, and needs fixing on the server; the annotation itself is fine. A permanent error on one locale's template usually means a missing translation string or a broken query for that language.
Address format problems that behave like redirects
Many "redirecting" targets are not old pages at all. They are the right pages written in a slightly different form, and the site redirects to its preferred form. The fix is to standardise the form the annotations use.
| Annotation says | Site serves | Result |
|---|---|---|
http://example.com/fr/ | https://example.com/fr/ | 301 on every target |
https://www.example.com/fr/ | https://example.com/fr/ | 301 on every target |
https://example.com/fr | https://example.com/fr/ | 301 to add the slash |
https://example.com/FR/Contact/ | https://example.com/fr/contact/ | 301 or 404, depending on the server |
/fr/contact/ | https://example.com/fr/contact/ | Not an absolute address |
Build annotations from the same canonical address field the page uses for its own link rel="canonical".
Then the target, the canonical and the page's own self-referencing annotation will always match, and
a change of protocol or host is picked up everywhere at once.
The fix, step by step
Step 1
Extract every hreflang target address
Run the Hreflang Checker on the main page of each locale to see which clusters contain unreachable targets, then build a complete list of targets. Export them from a crawler if your annotations are in the HTML, or pull them from every child sitemap if they are in the sitemap. Remove duplicates so each address is tested once, and keep a note of which pages list each target so you know what to change later.
Step 2
Request each target without following redirects
Request every address and record only the first response: the status code and, for redirects,
the Location it points to. Using curl without the follow option, or a crawler with redirect
following switched off for this report, shows you exactly what Google receives for the annotated address.
Run it from outside your office network with a normal user agent, and recheck anything that returns 403,
429 or 5xx.
Step 3
Sort the failures by status and cause
Group the results into permanent redirects, temporary redirects, 404 and 410 responses, server errors and suspected soft 404s. Within the redirect group, look for patterns such as a missing trailing slash, http instead of https or the wrong host, because those come from one setting rather than many pages. You will usually find that one or two causes explain most of the failures, which tells you where to start.
Step 4
Point redirected targets at the final address
For each permanent redirect, check that the destination is the correct equivalent page, then change the annotation to the destination address. After a migration, apply the same old-to-new redirect map you used on the server. For temporary redirects caused by location or language detection, switch off the redirect for these pages and rely on hreflang plus a visible switcher, so crawlers can reach every version directly.
Step 5
Remove or replace missing and gone targets
For each 404 or 410, decide whether an equivalent page should exist. Restore pages deleted by mistake, correct addresses that were mistyped, and where the locale genuinely has no equivalent, remove that locale from the cluster on every page that lists it. Do not substitute a home page or category page for a missing translation, because that tells Google two unrelated pages are the same content in different languages.
Step 6
Fix the address format at the source
Change the template, plugin or sitemap generator so every target is written as an absolute address in the exact form the site serves: the right protocol, host, letter case and trailing slash. The simplest way is to reuse the canonical address field for each locale version. Purge caches afterwards, rerun the probe and the Hreflang Checker, and confirm that every target now answers 200 on the first request.
Step 7
Test targets before every release
Add the target probe to your deployment process, run against staging or the generated sitemap, and fail the release if any target returns something other than 200. Make hreflang part of every migration, slug change and market closure checklist, and schedule a regular run of the Hreflang Checker to catch pages deleted by editors between releases. Broken targets are cheap to prevent and slow to notice once live.
Hreflang during a site migration
Migrations are the single biggest source of broken targets, because every address in every cluster can change at once. A sequence that avoids a long period of broken annotations:
- Before the move, export the current clusters so you have a record of every group of locale pages.
- Build the redirect map from old to new addresses, including every locale, not just the main language.
- Generate the new annotations from the new addresses, so that on launch day the pages already list their new siblings.
- After launch, probe every target on the new site. Any redirect in the results means an annotation still uses an old address.
- Keep the old addresses redirecting for the long term; they still matter for visitors and links, even though annotations should no longer use them.
If some locales move on a different date from others, update the annotations on the unmoved locales at the same time as each move, so no cluster points at redirects for weeks.
1. Can a hreflang target redirect to the right page?
It should not. Even if the redirect lands on the correct page, hreflang refers to the exact address written in the annotation. The page at the end of the redirect will list its own address, not the old one, so the pair no longer matches and Google may ignore it. Always list the final address that returns a 200 status. Redirects are for visitors and old links, not for hreflang annotations.
2. What should I do when a translated page has been deleted?
First decide whether it should exist. If it was removed by mistake, restore it at the same address. If it moved, update every annotation to the new address. If that locale really no longer has an equivalent page, remove the locale from the cluster on every page that lists it. Removing it from only one page leaves the others pointing at a missing address and creates return tag errors at the same time.
3. Is it fine to point a missing translation at the locale home page?
No. Hreflang says two pages are the same content for different audiences. A home page or category page is not the same content as a product or article, so the annotation is misleading and Google is likely to disregard it. It can also cause the home page to appear for searches it does not answer. If a translation does not exist, leave that locale out of the cluster until the translation is published.
4. Why does the checker show redirects when my pages work fine?
Most often the annotations use a slightly different form of the address from the one the site serves: http instead of https, www instead of the bare domain, a missing trailing slash or different letter case. The site then redirects to its preferred form, which works for visitors but not for hreflang. Build annotations from the same canonical address field the page uses, and the redirects disappear from the report.
5. Do geo-redirects break hreflang?
They can. If a server redirects visitors by IP address or browser language, crawlers may be sent away from the page named in the annotation. Google mostly crawls from the United States, so it may never reach your other country versions directly. Let every locale page load for everyone, show a banner or switcher suggesting a better version, and use hreflang so search results point people to the right page in the first place.
6. How often should I check hreflang targets?
Check after every event that changes addresses: migrations, slug changes, market launches or closures and bulk content deletions. Between those, a regular scheduled run catches pages removed by editors. On large stores where products come and go daily, running the target probe as part of each deployment or nightly job is worthwhile, because a discontinued product in one market can break annotations on every other market's version of that page.
7. Does a temporary server error on a target matter?
A single failed request is unlikely to matter, because Google will try again on later crawls. Repeated or long-lasting errors are different: if a locale page keeps failing, Google cannot confirm the cluster and may drop that page from its index. Retest any 5xx result several times and at different times of day. If the error is persistent, treat it as a server fault to fix, not as a reason to edit the annotations.
The Hreflang Checker follows each cluster of locale pages and validates return tags, language codes, x-default, sitemap consistency, target reachability and canonical alignment.
Open Hreflang Fixes โ