/en/tool/hreflang-checker/ works crawls the server
Enter the URL of any language version — the tool will find the others from its markup and crawl them automatically. For each page, it checks the response code, canonical, noindex, and robots.txt restrictions; parses link tags and the Link header; compares language codes against authoritative ISO lists; and shows which links are confirmed from both sides and which are not. If the markup is in a sitemap, enter the sitemap URL: we’ll parse it along with its xhtml:link tags and process sitemap indexes in chunks.
Enter one URL. The tool will find the other versions and visit each one.
Rows are set pages, and columns are language codes. Each cell shows whether a link exists and whether the other page links back.
One row for each issue with a page or an individual link. For redirects, you can expand the full chain.
| Page | Language code | Links to | What's wrong | Response |
|---|
Enter the address of any language version and click “Check set.” The tool will get the other versions from its markup—from link tags and the Link header, which is not visible in the page source at all.
Read the matrix by rows. A row is a page and everything it declares about the set. A cross means the link leads somewhere invalid: the response is not 200, there is a redirect, noindex is present, or the language code does not exist.
Understand the arrows. An arrow means a one-way connection: A names B as its pair, but B says nothing about A. No one confirms this connection, so the search engine may ignore it.
Check the response column in the notes table. For links returning 301, click “chain” to see every step with its codes and the final address. hreflang should point to that address.
Download the CSV and send it to the developer. It contains the page, language code, address, response code, reciprocity, and note—one row for each link in the set.
If the markup is in a sitemap, open the “Sitemap or list” tab and provide its address. The server parses the sitemap as XML, so xhtml:link tags are not lost. We follow sitemap indexes piece by piece. The checks are the same as for pages, while response codes are requested with a separate button so requests are not used silently.
If the site is password-protected or inside a closed network, our server cannot access it. Use the “Pasted code” tab instead. The checks are the same; you provide the data yourself.
The input data is the same as the default field values: you can calculate it mentally and confirm that the tool is telling the truth.
For the Russian version's address, the tool fetches the page and finds three links. It then follows them and fetches the other two versions—you do not need to enter them manually.
For each version, it checks the response code, canonical, meta robots, the X-Robots-Tag header, and the robots.txt restriction. All three return 200 and are accessible.
Each version links to itself: ru for the Russian version, en for the English version, and de for the German version. In the matrix, these are the diamonds on the diagonal.
The Russian and English versions name the German version as their pair, while the German version lists only itself and the English version. In the German version's row, the ru column contains a dot; in the Russian version's row, the de column contains an arrow.
There is one one-way connection: https:\/\/example.com\/de\/ does not link back to https:\/\/example.com\/. There is also a note that x-default is not set on any version, so the search engine has no fallback.
The address you entered and the addresses of the versions found in its markup. Our server opens the pages and sitemaps—the browser cannot access a different domain because of the same-origin policy. Nothing we check is saved, either in a database or in a file. The limit is three hundred requests per hour from one address. It applies to all site tools, and the remaining quota is shown below the results.
Each version requires a separate request, and twenty is enough for almost any set. You can raise the limit to fifty or lower it. If there are more versions, provide the sitemap address: it arrives in one request and brings in the markup for all listed addresses at once.
The server fetches the sitemap and parses it as XML. This matters: parsing it as HTML removes the namespace, and with it all xhtml:link tags—the sitemap's entire language markup. We decompress .gz files. If the address points to a sitemap index, we follow its parts, using one request for each. The checks are then the same as for pages: language codes against ISO lists, reciprocity, x-default, and the matrix. We request response codes, canonical, and noindex for the addresses themselves only when you click the button. Those requests target each address, and using them silently would be unfair.
Usually, yes, and we report it on a separate line: the total number of addresses in the sitemap and how many of them have xhtml:link. Only addresses with markup go into the matrix—there is nothing to compare for the others. If the page really has no language versions, everything is fine. If it does have them but no tags, its set has not been declared.
All three. The server retrieves link tags from the head, and the Link header is parsed from the response. It is not present in the page source, and it is the one people forget most often. The sitemap is read from its address or from the text you paste. If one page uses two methods at once, the tool reports it: the search engine will see both sets, but you should use only one.
Because canonical takes precedence over hreflang. If the English version declares the Russian address as canonical, the search engine removes the English version from the index along with all its language-version markup. The set may look perfect and still not work. Each version must be canonical to itself.
Yes. A set describes the entire group of versions, and each version belongs to its own set. If a page lists its neighbors but not itself, the set is considered incomplete.
The version for users whose language does not match any of the listed ones. It is usually a language selector page or the site's main version. The tag is optional, but without it the search engine has no fallback. A set must not contain two different x-default values.
By the lists, not by the format. The language is checked against ISO 639-1, the script against ISO 15924, the country against ISO 3166-1 alpha-2, and the numeric region against UN M.49. Therefore, en-UK fails because the country code is GB; en-EU fails because the European Union is not a country; en_US fails because the separator is a hyphen; and US alone fails because it is a country code, not a language code.
Addresses used to be compared character by character, so https:\/\/example.com\/ and https:\/\/example.com were treated as different pages. Before comparison, the address is now normalized: protocol, www, trailing slash, domain case, default port, and percent encoding in the path. If the only difference is one of these, the connection counts, while the note remains on a separate line.
A version connection must be confirmed from both sides. If A names B as its pair but B says nothing about A, any unrelated site could claim to be your language version. That is why the search engine may ignore a one-way connection.
Switch the user-agent. By default, we identify ourselves as Googlebot because its response is what matters for hreflang. Some sites block this user-agent because the request does not come from Google's IP addresses. Select “Computer, Chrome” and check again.
Writes the title and description and instantly shows how they appear in search results.
Open
Shows the full path from the URL to the final page and the response codes.
Open