Special characters in a URL path: what breaks and why
Spaces, percent signs and non-ASCII characters in a path break when copied and pasted. squirrel decodes the path and reports what it finds.
What counts as a problematic character
A URL path is limited by RFC 3986 to a defined set of characters. Anything else has to be percent-encoded, which is why a space becomes %20. Some characters are reserved because they delimit parts of the URL: ? starts the query, # starts the fragment, & and = separate parameters.
Encoding is correct and works. What varies is how the software around it behaves: link parsers that stop at the first unexpected character, systems that encode an already-encoded path a second time, tools that display the raw percent sequence rather than decoding it. Non-ASCII characters in a path are valid, and browsers show them decoded, but whether anything else does depends on the application. Sticking to unreserved characters removes the question.
What squirrel checks
The rule runs on every crawled page over the URL path only, decoded first with decodeURIComponent. It emits up to two checks:
url-special-charswarns when the decoded path contains any of% & = # [ ] { } | \ ^ ~ \< >, or a space, or any character outside printable ASCII. Message:URL path contains problematic characters, with the categories found listed as items:spaces,special characters,non-ASCII characters`. Severity warning, weight 4.url-special-charspasses otherwise. Message:URL path uses clean characters.url-double-slashwarns when the path contains//anywhere after the first character. Message:URL path contains double slashes, with the path as the value.
The space test looks at both the raw path, for a literal %20 or whitespace, and the decoded path. The query string is not examined.
How to fix it
https://example.com/blog/cafe-guide
Generate slugs by transliterating to ASCII, lowercasing, and replacing anything left with a hyphen. Collapse repeated separators so a title with a colon and a space does not produce --.
A site whose audience reads a non-Latin script has a real reason to use those characters in URLs, and browsers display them correctly. Disable the rule rather than transliterating a language into something its readers cannot recognise.
| Rule ID | url/special-chars |
| Category | URL Structure |
| Scope | Per-page |
| Severity | warning |
| Weight | 4/10 |
Enable / disable
Disable this rule
[rules]
disable = ["url/special-chars"]Disable all URL Structure rules
[rules]
disable = ["url/*"]Enable only this rule
[rules]
enable = ["url/special-chars"]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/lowercase: case, the other thing a slug generator should normalise.
- url/hyphens: the separator the generator should be using.
- i18n/lang-attribute: the correct way to declare a page’s language.
- links/invalid-links: links whose href does not parse at all.
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. Each path is listed with the categories of character it contains. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.