Uppercase in a URL: the duplicate content it creates
Most servers treat /Page and /page as two URLs serving the same content. squirrel flags every crawled path containing a capital letter.
What URL case sensitivity is
The path portion of a URL is case-sensitive in the URI specification, and most origin servers treat it that way. /Products and /products are two different resources as far as the protocol is concerned.
When both answer with the same page, you have two URLs for one document. Links split between them, and a search engine has to pick one, which is a choice you would rather make yourself. The host is a separate matter: hostnames are case-insensitive, so EXAMPLE.com and example.com are the same origin.
What squirrel checks
The rule runs on every crawled page over the URL path only. It emits a single check named url-lowercase:
- Warn when the path contains any character in the range A to Z. Message:
URL contains uppercase characters, with the path as the value and its lowercased form as the expected value. Severity warning, weight 4. - Pass otherwise. Message:
URL is lowercase.
The query string and the hostname are not examined. Percent-encoded sequences in the path, which are uppercase hexadecimal by convention, are read as they appear and can trigger the warning.
How to fix it
// compute the lowercase destination, then redirect to it
if (path !== path.toLowerCase()) {
return Response.redirect(new URL(path.toLowerCase(), origin), 301);
}Emit lowercase URLs from the CMS or the router, and redirect the mixed-case forms permanently rather than serving both. The redirect has to build the lowercase target itself. A plain nginx rewrite that captures and re-emits the path preserves its case and redirects /Products to /Products, which is a loop. Set a self-referencing canonical on the lowercase version so any remaining links consolidate.
Do not lowercase the query string with the same rule. Parameter values are often case-sensitive, and tokens or signatures break when they are folded.
| Rule ID | url/lowercase |
| Category | URL Structure |
| Scope | Per-page |
| Severity | warning |
| Weight | 4/10 |
Enable / disable
Disable this rule
[rules]
disable = ["url/lowercase"]Disable all URL Structure rules
[rules]
disable = ["url/*"]Enable only this rule
[rules]
enable = ["url/lowercase"]enable replaces the default ["*"], so this is the only rule selected. Leave disable out: a rule that matches any disable pattern is skipped even when enable names it. Only an enabled setting under a rule’s own [rule_options] table overrides both lists.
Related rules
- url/slug-convention: whether the site mixes case rather than applying one rule.
- url/hyphens: the other per-path convention check.
- crawl/canonical-chain: the canonical tag that consolidates the variants.
- url/trailing-slash: the other way one page becomes two URLs.
URL Structure findings ship in every audit next to the SEO, performance and agent experience rules. See Fix SEO issues with AI for how an agent works through a report.
References
Check your site
Run squirrel audit https://example.com and open the URL Structure section of the report. Every path containing a capital letter is listed with its lowercase form. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.