By SitemapFixer Team
Updated April 2026

Non-Canonical URL: What It Means and How to Fix It

Find non-canonical URLs in your sitemapScan Free

A non-canonical URL is any URL whose rel="canonical" tag points to a different URL. The page is telling search engines, "don't index me — index that other URL instead." Non-canonical URLs are a normal part of any large site: paginated archives, sort and filter variants, mobile alternates, AMP pages, and tracking-parameter URLs all legitimately declare a different canonical. The problem starts when non-canonical URLs end up in your sitemap, get linked internally as if they were the primary version, or — most commonly — show up in Google Search Console under one of four "non-canonical" statuses you weren't expecting.

This guide covers what a non-canonical URL actually is, the four GSC statuses where they appear, when non-canonical URLs are correct, when they signal a real problem, and exactly how to fix each scenario. For broader canonical strategy, see the canonical issues guide.

What a Non-Canonical URL Looks Like

The defining characteristic is simple: the value of href in the canonical link tag does not match the URL of the page itself. Self-referencing canonicals (where the URL points to itself) are canonical URLs. Anything else is non-canonical.

<!-- Canonical URL (self-referencing) -->
<!-- Page URL: https://example.com/shoes -->
<link rel="canonical" href="https://example.com/shoes" />

<!-- Non-canonical URL (points elsewhere) -->
<!-- Page URL: https://example.com/shoes?sort=price -->
<link rel="canonical" href="https://example.com/shoes" />

<!-- Non-canonical URL (mobile alternate) -->
<!-- Page URL: https://m.example.com/shoes -->
<link rel="canonical" href="https://example.com/shoes" />

<!-- Non-canonical URL (paginated archive) -->
<!-- Page URL: https://example.com/blog/page/3 -->
<link rel="canonical" href="https://example.com/blog/page/3" />
<!-- (Self-referencing — modern best practice for paginated content) -->

The last example is interesting: it's a paginated page that self-canonicalizes, which is the modern recommendation. The widely repeated "canonical pagination back to page 1" pattern produces non-canonical URLs that hide everything on page 2+ from Google. We'll get to that.

The Four GSC Non-Canonical Statuses

Google Search Console reports non-canonical URLs across four distinct statuses in Indexing → Pages. Each one means something different and demands a different fix.

1. "Alternate page with proper canonical tag" — The page is non-canonical and Google agrees with the canonical you declared. This is an informational status, not an error. It is the expected status for pagination, parameter variants, and mobile alternates. Do nothing unless the URL is showing up here when it shouldn't (e.g., a primary product page incorrectly canonicalized to a category).

2. "Duplicate, Google chose different canonical than user" — You declared a canonical, but Google overrode it and picked a different URL. Common causes: HTTP canonical on an HTTPS-served page, canonical pointing to a redirect or 404, internal links overwhelmingly pointing to a different URL, or hreflang signals contradicting the canonical. Fix by aligning all signals (canonical + sitemap + internal links + redirects) to point to the same URL.

3. "Duplicate without user-selected canonical" — No canonical tag is present and Google found similar content elsewhere on the site. The page is non-canonical by Google's decision, not yours. Almost always caused by a CMS template that fails to output a canonical tag on certain URL patterns (parameter variants, faceted navigation, search result pages). Fix by adding a self-referencing canonical to the template, or by canonicalizing the variant to the parent page if it shouldn't be indexed independently.

4. "Duplicate, submitted URL not selected as canonical" — You included the URL in your sitemap, but Google decided it's a duplicate of another URL it already indexed. The conflict is direct: your sitemap says "index this," but the canonical signals say "index that other URL." Fix by removing the URL from your sitemap (sitemaps must contain canonicals only) or by changing the canonical to make the submitted URL the canonical version.

When Non-Canonical URLs Are Correct

Before fixing anything, verify the non-canonical URL is actually wrong. Many non-canonical URLs are doing exactly what they should:

Sort, filter, and tracking parameter variants. ?sort=price, ?utm_source=newsletter, ?ref=email, ?color=red — these are not separate pages from a content perspective. They should canonicalize to the parameter-free URL. The exception is filtered views with their own search demand (e.g., a "Nike running shoes" filter that gets significant search volume) — those should self-canonicalize and be in the sitemap.

Mobile alternate URLs. If you serve a separate mobile site at m.example.com, every mobile URL must canonical to its desktop equivalent, paired with a rel="alternate" on the desktop pointing to the mobile URL. Mobile URLs that don't canonicalize to desktop are the bug, not the other way around.

AMP pages. AMP URLs canonical to their non-AMP HTML counterpart. The non-AMP page links to the AMP version with rel="amphtml". This is the prescribed pattern.

Print views and embed views. /article/title?print=1 or /article/title?embed=1 should canonical to the regular article URL. They exist for utility, not for indexing.

Internationalization edge cases. Country-targeted variants of essentially identical content (e.g., /en-us/ and /en-gb/ with the same product copy) sometimes canonicalize one to the other while still using hreflang to swap which version shows in each region. This is contested practice — modern guidance is self-canonical with hreflang — but it exists.

If your non-canonical URL fits one of these patterns and shows under "Alternate page with proper canonical tag," it is working as intended. Move on.

Auditing Non-Canonical URLs With curl + grep

Before relying on a crawler, you can audit non-canonical URLs from any sitemap using nothing but curl, grep, and awk. This is the script I run first on any new audit:

#!/bin/bash
# audit-non-canonical.sh — find non-canonical URLs in a sitemap
SITEMAP="${1:-https://example.com/sitemap.xml}"

# Pull all <loc> entries from the sitemap
URLS=$(curl -s "$SITEMAP" | grep -oE '<loc>[^<]+</loc>' | sed 's/<[^>]*>//g')

echo "URL,Canonical,Status"
for URL in $URLS; do
  HTML=$(curl -sL "$URL")
  CANONICAL=$(echo "$HTML" \
    | grep -oE '<link[^>]+rel="canonical"[^>]*>' \
    | grep -oE 'href="[^"]+"' \
    | head -1 \
    | sed 's/href="//; s/"//')

  if [ -z "$CANONICAL" ]; then
    echo "$URL,,MISSING"
  elif [ "$URL" = "$CANONICAL" ]; then
    echo "$URL,$CANONICAL,SELF"
  else
    echo "$URL,$CANONICAL,NON-CANONICAL"
  fi
done

Run it as ./audit-non-canonical.sh https://example.com/sitemap.xml > report.csv. Every row marked NON-CANONICAL in the output is a URL that shouldn't be in the sitemap. Every row marked MISSING is a page that will likely show up in GSC under "Duplicate without user-selected canonical" if Google finds a similar page elsewhere on the site. Both are fixable patterns.

Removing Non-Canonical URLs From the Sitemap

The single most common cause of GSC's "Duplicate, submitted URL not selected as canonical" warning is a sitemap that includes non-canonical URLs. Sitemaps are a strong indexing signal — they tell Google "these are my important URLs." When that list contains URLs the canonical tags say should not be indexed, you've sent contradictory signals.

The rule is absolute: sitemaps contain self-canonical, indexable URLs that return 200 OK. Nothing else. No 301s, no 404s, no noindex URLs, no URLs whose canonical points elsewhere.

If you generate your sitemap programmatically, filter at generation time. Pseudocode for a Node.js / Next.js sitemap route:

// app/sitemap.ts — only include canonical URLs
import { getAllPages } from '@/lib/cms';

export default async function sitemap() {
  const pages = await getAllPages();

  return pages
    .filter(p => p.statusCode === 200)
    .filter(p => !p.noindex)
    .filter(p => p.canonicalUrl === p.url) // canonical-only filter
    .map(p => ({
      url: p.url,
      lastModified: p.updatedAt,
      changeFrequency: 'weekly',
      priority: 0.7,
    }));
}

For WordPress, Yoast and Rank Math both exclude non-canonical URLs from sitemaps automatically — but only when the canonical is set through the plugin. If a custom theme injects a canonical separately, the plugin doesn't know about it and may include the URL anyway. Check your sitemap output against the audit script above.

For Shopify, the platform's native sitemap.xml already excludes ?variant= URLs, but any app that generates supplementary sitemaps (collection feed apps, multi-language apps) should be audited.

Fixing Each GSC Non-Canonical Status

Fixing "Duplicate, Google chose different canonical than user." This is a signal contradiction problem. Step 1: open the URL in GSC URL Inspection and read the "User-declared canonical" vs "Google-selected canonical" lines. Step 2: visit the Google-selected canonical and check whether the page is HTTPS while your declared canonical is HTTP, whether one resolves to a redirect, or whether one returns 404. Step 3: count how many internal links point to your declared canonical vs the Google-selected one — if the latter has 10x more inbound links, internal linking is overriding your tag. Update internal links, fix any redirect or scheme mismatches, then request indexing for a sample of affected URLs.

Fixing "Duplicate without user-selected canonical." The page is missing a canonical tag. Add one. If the URL is the primary version (e.g., /products/widget), make the canonical self-referencing. If it's a parameter or filter variant that shouldn't be indexed, make it canonical to the parent. The fix lives in your CMS template or framework — for Next.js, set alternates: { canonical: ... } in the page metadata; for WordPress, configure Yoast or Rank Math's "Search appearance" settings; for Shopify, edit theme.liquid to ensure {{ canonical_url }} is rendered.

Fixing "Duplicate, submitted URL not selected as canonical." Decide which URL should win. If the sitemap-submitted URL is correct, change the canonical on the duplicate page to point to it. If the canonical-declared URL is correct, remove the submitted URL from your sitemap. Don't leave the conflict in place hoping Google figures it out — it won't consistently, and the URL will sit in "Discovered, not indexed" limbo for months.

Fixing "Alternate page with proper canonical tag" (when it's wrong). If a primary page is incorrectly listed as an alternate of something else, the canonical on that page is pointing to the wrong URL. Update it to self-reference, then resubmit it via URL Inspection.

Internal Link Audit for Non-Canonical URLs

Internal links are a strong canonicalization signal. If your declared canonical is /shoes but every navigation menu, breadcrumb, and related-products widget links to /shoes/?from=nav, Google will treat the parameter version as more important than your declared canonical and may override it.

The audit: in Screaming Frog or any crawler, export the "Internal Links" report and group by destination URL. Any URL that gets significant internal links but appears in a non-canonical category in GSC is a signal-conflict candidate. Update the source links to point to the canonical version, not the parameter variant.

Common offenders: navigation menus that hard-code tracking parameters, related-product widgets that pass session IDs, breadcrumbs that link to the trailing-slash variant when the canonical is the no-trailing-slash form, and email signatures linking to a redirected legacy URL. None of these individually break canonicalization, but together they push Google toward picking the wrong canonical.

Verifying a Fix With GSC URL Inspection

After deploying any fix, verify it in GSC URL Inspection. Paste the affected URL into the search bar at the top of GSC and read the "Indexing" section. The fields to check:

User-declared canonical — should match what you intended to declare. If this is empty or wrong, your fix didn't deploy correctly (or a cache layer is still serving the old version).

Google-selected canonical — what Google currently considers canonical. Right after a fix, this still reflects the pre-fix state; Google won't update until it recrawls. Click "Test live URL" in the top right to force a fresh fetch and see what Google sees right now.

Indexing allowed? — should be "Yes". If "No," check for stray noindex meta tags or X-Robots-Tag headers.

If the live test confirms the new canonical, click "Request indexing" to nudge Google toward a faster recrawl. Don't request indexing on more than 10–20 URLs per day — bulk requests are throttled and don't produce faster results.

Recovery Time After a Non-Canonical Fix

Timelines depend on crawl frequency for the affected URLs and the type of fix:

Single-URL fixes (changing one page's canonical): 1–7 days for Google to recrawl and update its canonical assignment. The URL appears in the new GSC status within 7–14 days.

Sitemap cleanup (removing non-canonical URLs from sitemap): 5–10 days for the "Duplicate, submitted URL not selected as canonical" count to drop in GSC. Resubmit the sitemap via Sitemaps in GSC after deploying the change.

Template-level fixes (CMS theme change affecting thousands of URLs): 2–6 weeks for full propagation. GSC counts begin moving in week 1 but plateau slowly. Don't panic if half the URLs are still in the old status at week 3 — Google recrawls in priority order, and lower-priority URLs lag.

Cache caveat: if you have Cloudflare, WP Rocket, or any full-page cache between your origin and Googlebot, purge the cache immediately after a canonical fix. Otherwise Googlebot will keep seeing the old HTML for the cache TTL — sometimes days — and the fix will appear stalled.

One sanity check: if a week after a fix, URL Inspection's "Test live URL" still shows the old canonical, the fix isn't actually live in production. Don't blame Google — find the cache or the unreverted deployment.

Common Mistakes That Create Non-Canonical URL Problems

Canonicalizing pagination back to page 1. If /blog/page/2 canonicals to /blog, every article on page 2 becomes invisible to Google. Self-canonicalize each pagination page. The first page does not consolidate signals automatically; ranking flows through internal links to individual articles.

Canonicalizing to a redirect. If your canonical points to a URL that 301s elsewhere, Google has to follow the chain and may decide the final destination is the canonical — overriding your tag. Update the canonical to point directly to the final URL.

Canonicalizing across noindex. If a page is noindex and also has a canonical to another URL, Google interprets the page as withdrawn and the canonical is ignored. Pick one signal: either remove the canonical (if you actually want the page noindexed and out of the index) or remove the noindex (if you want signals to consolidate to the canonical target).

Two canonical tags on one page. When a CMS theme outputs one canonical and an SEO plugin outputs another, Google ignores both. View source on a sample page and count rel="canonical" occurrences. There should be exactly one.

Canonicalizing to a non-200 URL. A canonical pointing to a 404 or 500 is treated as no canonical at all. Always verify the canonical target returns 200.

Related Guides

Find every non-canonical URL on your site
Free analysis in 60 seconds
Analyze My Site Free
Related guides