Google Search Console has a report called Page Indexing. It lists the pages on your site Google decided not to index, grouped by reason. One of those groups is called Duplicate without user-selected canonical, and it probably has more URLs in it than you expected.
The name sounds like an accusation. It is not one.
Here is the whole thing in plain English. A canonical is Google’s word for the one URL it treats as the real version of a page. You have two or more URLs that Google thinks are the same page. You never told it which one counts. So it picked one, indexed that, and filed the rest under this label.
That happens more easily than it sounds. These are three URLs, and to Google they are one page:
https://example.com/shoes
https://example.com/shoes?sort=price
https://example.com/shoes?utm_source=newsletter
Google indexes one of them and files the other two under this status. Nobody did anything wrong.
Most advice tells you to add a canonical tag to every URL in that list. That advice is wrong more often than it is right, and the rest of this post is why. Your job is not to empty the list. Your job is to find out which URL Google picked, and decide whether it picked well.
- It is a status, not an error. Google found duplicate URLs, none declared a preference, so it picked one and indexed that.
- The page is not penalized. Signals from the duplicates consolidate onto the URL Google chose.
- The only question that matters is which URL it picked. Inspect the URL and compare Google’s canonical against yours. One at a time in Search Console, or handed to your agent with ContextBolt SEO.
- A canonical tag is a hint, not a directive. Google can ignore it, which moves you to a different status rather than fixing anything.
- Fix it only when Google chose badly, like a parameter URL or a print version. Otherwise leave it alone.
Where you are seeing this
If you landed here from a search and have not found the report yet, this is where it lives.
- Open Google Search Console and pick your site.
- Click Indexing, then Pages: That is the Page Indexing report.
- Scroll to “Why pages aren’t indexed”: It is a table of reasons, each with a count.
- Find this row and click it: You get a list of example URLs in that group.
One warning about that list, because it catches people out. The count on the row and the number of URLs you can actually see are not the same thing. More on why that matters, and what to do about it, further down.
What the status actually means
Google’s own wording is short. The page “is a duplicate of another page, although it doesn’t indicate a preferred canonical page,” and Google “has chosen the other page as the canonical for this page.”
Three things follow from that sentence, and all three get lost in the panic.
Google crawled the page. It is not blocked, not broken, not skipped. Googlebot fetched it, read it, and compared it against something else on your site. That already puts it ahead of the two statuses people confuse it with, where the page was either never fetched or was fetched and judged not worth an index slot.
The page’s value did not evaporate. Canonicalization consolidates. Links pointing at the duplicate, and the relevance of its content, roll into the URL Google chose. You have not lost the page from search. You have merged it.
Nobody declared a preference. That is the “user-selected” half of the name, and it is the only part of the status describing something you did rather than something Google did. You never told it which URL was the real one.
So the status is Google reporting a decision it made on your behalf, in a situation where you never expressed an opinion. Read it that way and the report stops looking like a list of defects.
Why did Google pick a different URL?
Google names the signals it uses when nobody declares a canonical, and the list is shorter than most SEO writing implies. Its canonicalization documentation ranks them roughly like this.
- Redirects: a strong signal that the redirect target should become canonical.
- The rel=canonical annotation: also a strong signal, and still only a signal.
- Sitemap inclusion: a weak signal in favor of URLs you submitted.
- HTTPS: Google prefers the secure version of an otherwise identical page.
- hreflang clusters: URLs inside a cluster are preferred over ones outside it.
Notice what is missing. Internal link counts are not on that list. Neither is URL depth, nor which page you think is more important, nor how long the page has existed. People reason from all three and then find Google’s choice inexplicable.
The line worth carrying is Google’s own framing that none of these are required, and that most sites do fine without declaring a preference at all. That is the opposite of the standard advice, and it comes from the people who run the index.
How do you see which URL Google picked?
This is the whole diagnosis and it takes one call.
The Page Indexing report shows you the bucket. It does not show you, on the summary screen, which URL Google chose for any given duplicate. For that you inspect the URL, and the inspection returns two fields side by side. One is the canonical you declared, if any. The other is the URL Google actually indexed.
When those two disagree, you have your answer. When your declared canonical comes back empty, you have confirmed the “user-selected” half of the status is literally true.
You can do this by hand in Search Console, one URL at a time. If your Search Console is connected to an AI agent, you can ask for it in plain English instead, which starts to matter once the list runs past about five URLs.
Copy this prompt
Pull my Search Console pages report for the last 28 days. Take the 20
pages with the most impressions and inspect each one. List only the
pages where Google's chosen canonical is different from the URL I
asked about, showing both URLs side by side and the coverage state.
That returns a mismatch list rather than a report. Every row on it is a decision waiting for you, and every page not on it is fine.
If your Search Console is not wired up yet, connecting Search Console to your agent takes about twenty seconds and the read-only connection costs nothing.
What causes it? Five common patterns
Almost every case traces back to one of five patterns, and four of them come from the platform rather than from anything you wrote.
| Cause | What it looks like | Worth fixing |
|---|---|---|
| URL parameters | Tracking, sorting and filter strings appended to a real page | Yes |
| Host variants | www and non-www, http and https, trailing slash and not | Yes |
| Thin archive pages | Tag, category and date archives repeating the same excerpts | Sometimes |
| Pagination and print views | A second URL rendering the same article in another shell | Sometimes |
| Genuinely similar pages | Two posts covering nearly the same topic | No, rewrite instead |
The last row is the one people misdiagnose. If Google merged two pages you wrote deliberately, it is telling you something true about those pages. A canonical tag will not make them different. Only editing them will.
Which ones should you fix, and which should you leave?
Here is the uncomfortable version, and it is the reason this post exists.
Most of the URLs in that bucket do not need anything done to them. If Google picked the URL you would have picked, the system worked. Adding markup to make a warning disappear from a report is not SEO. It is tidying.
The cases that genuinely need action share one trait. Google picked a URL you would not have picked, and that URL is now the one people land on.
- Fix it when a parameter URL won: Somebody searching for your product should not arrive at a sorted, filtered version of the listing.
- Fix it when a print or stripped-down shell won: The reader gets your article with none of your navigation and none of your calls to action.
- Fix it when the wrong language or region won, because hreflang is the one place a wrong pick can send the wrong audience entirely.
- Leave it when Google picked the clean URL: That is the outcome you wanted.
- Leave it when the duplicate is machine-generated and worthless, like an internal search results page. Better to stop generating it than to annotate it.
The honest test is whether a real person landing on Google’s chosen URL would be worse off than one landing on yours. If the answer is no, close the tab.
The fix that quietly makes it worse
Adding a canonical tag to every page in the list is the most common response and the least examined one.
Google treats that tag as a strong signal. It does not treat it as a command. So one of two things happens. Either Google agrees with you, in which case you have confirmed a decision it had already made, or Google disagrees, in which case the page moves out of this status and into one called duplicate, Google chose different canonical than user.
Read that second outcome carefully. The page is still not indexed under your preferred URL. You have not fixed anything. You have swapped a status saying “you did not express a preference” for one saying “you expressed a preference and Google declined it”, which is strictly more information about a problem you still have.
There is a sharper failure mode too. A canonical tag pointing at the wrong target is one of the few ways to actively lose a page. Point a unique page at an unrelated one and you have asked Google to stop indexing something it was happily indexing.
The order that works is diagnose, then decide, then annotate. Not annotate and hope.
How is this different from the other duplicate statuses?
Four statuses in the Page Indexing report look similar and describe genuinely different situations. Telling them apart takes ten seconds and saves you fixing the wrong thing.
| Status | What Google did | What it is telling you |
|---|---|---|
| Duplicate without user-selected canonical | Crawled, merged, chose for you | You never declared a preference |
| Duplicate, Google chose different canonical than user | Crawled, merged, overruled you | Your declared canonical lost |
| Alternate page with proper canonical tag | Crawled, merged, agreed with you | Nothing. This one is working |
| Crawled, currently not indexed | Crawled, then declined it | A quality judgment, not a duplicate one |
That third row deserves a mention because people still try to fix it. Google’s guidance on Alternate page with proper canonical tag is that there is nothing you need to do. It is the report confirming your setup is correct, which is a strange thing to find in a list of pages that are not indexed, and it catches people out every time.
Running the check across a whole site
This is the warning from the top, in full, and it is worth knowing before you plan an afternoon around it.
The Page Indexing report caps its examples. Google states the list “is limited to 1,000 items, and isn’t guaranteed to show all URLs in a given status,” even when there are fewer than a thousand. So the bucket count and the URLs you can actually see are two different numbers.
The Search Console API does not close that gap. It exposes search analytics, sitemaps, sites and URL inspection, and the inspection endpoint works on exactly one URL per call. No endpoint hands you every URL sitting in a given index status. The per-URL truth is available and the list is not.
The same wall shows up on every status in this report. It is why discovered, currently not indexed has to be diagnosed URL by URL too, even though its cause sits somewhere else entirely.
That leaves two honest routes. Export what the report will give you, or generate your own URL list from your sitemap and inspect them one by one. Inspection is quota-limited to 2,000 queries per day per property, which is plenty for most sites and a real constraint on large ones.
This is where doing it in an agent stops being a preference and starts being the only sane option. A loop that reads your sitemap, inspects each URL, and reports only the canonical mismatches is a paragraph of instruction rather than a script. It is the same shape as the other SEO loops worth running, where the agent does the looking and you do the deciding. For the wider version, the site audit workflow walks through running checks across every page instead of one at a time.
Where the data comes from
Everything above needs two things. Your own index status, which is free from Google, and somewhere for the readings to pile up so you can tell a new mismatch from one that has sat there for months.
ContextBolt SEO is the tool I build. It puts a read-only Search Console connection and a full SEO toolkit inside the agent you already work in, so an inspection is a sentence rather than a tab and a wait. The Search Console tools are free and never spend your monthly research credits. It is $35 a month with a 7-day free trial, and there is no dashboard to work in, because every lookup lands on a board that fills itself while you work somewhere else.
The reason that shape suits this particular job is that canonical decisions move slowly. You need last month’s reading to know whether today’s is new, and a folder of dated files does that better than any report you have to remember to open.
What I would actually do
Open the bucket. Inspect ten URLs, not all of them. Write down Google’s chosen canonical next to each one.
If Google picked the URL you would have picked in nine cases out of ten, you do not have a canonical problem. You have a report with a frightening label on it, and the correct response is to close it and go do something that moves traffic.
If Google picked badly, look at what the bad picks have in common. It will almost always be one generator, one parameter, one template. Fix the generator and the whole bucket drains at once, which is a far better afternoon than annotating four hundred pages by hand.
The instinct this report triggers is to make the number go to zero. Resist it. A duplicate Google resolved correctly is the system working, and the only version of this status that costs you anything is the one where you never checked which URL it chose.