Trailing slashes and uppercase urls in a redirect map

/about, /about/ and /About are three urls to a search engine and often three strings to a redirect engine. what the map needs to contain so every one of them lands in one hop.

by Max Lorenz, Goodaim · updated

three urls, one page
  • /About-Us/case + slash
    /about
  • /about-us/slash
    /about
  • /about-usexact
    /about

SHORT ANSWER

Search engines treat /about, /about/ and /About as different urls, and many redirect engines compare paths as exact strings. A redirect map should therefore hold one row per page, in the form the old site actually used, with rules written to match the other variants too: a regex with /? before the end anchor for the slash, a case-insensitive flag or option for capitals. The targets should be in the exact form the new site serves, or every redirect gains a second hop through the new site’s own slash redirect.

What search engines see

Google’s position on slashes is in its post to slash or not to slash: it treats a url with a trailing slash and one without separately, whether or not the path is a directory. Serving the same content on both is legitimate and common; the cleaner setup is to pick one, use it in internal links and the sitemap, and 301 the other to it, with rel="canonical" as the fallback. The root is the one exception — example.com and example.com/ are equivalent.

On case, Google’s url structure documentation says it treats /APPLE and /apple as distinct urls with their own content. Hosts are case-insensitive; paths are not.

For a relaunch this matters in one direction above all: every variant of an old url that was linked or indexed has to reach the new page. Old campaign links, email footers and backlinks carry capitals and stray slashes far more often than the site’s own navigation ever did.

How the platforms answer

Each platform normalises differently. We requested the same page in its plain, slashed and capitalised form on live sites of each platform on 3 october 2026; this is what came back. It is an observation of those sites, not a documented guarantee — custom domains, apps and server rules can change it, so check your own site the same way.

platformtrailing slashuppercasechecked on (3 october 2026)
Webflow/page/ → 301 to /page/Page → 404three Webflow-hosted sites
WordPress/page → 301 to /page//Page/ → 200, canonical to /page/ (one site: 301 to lowercase)four WordPress sites
Shopify/collections/x/ → 200, canonical to /collections/x/Collections/X → 404 on one store, 301 to the homepage on anothertwo stores on Shopify's own frontend
Squarespace/page/ → 200, canonical to /page/PAGE → 404two Squarespace template sites (slash checked on one)
Wix/page/ → 301 to /page/Page → 301 to /pagewix.com
for p in /about /about/ /About; do
  printf "%-8s " "$p"
  curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" "https://www.example.com$p"
done

Three patterns come out of it. Some platforms redirect the variant to the preferred form (Webflow and Wix strip the slash, WordPress adds it). Some serve both with a canonical pointing at one (Shopify and Squarespace with slashes, WordPress with capitals). And some refuse the variant with a 404 (capitals on Webflow, Squarespace and Shopify). The third pattern is the one that bites in a relaunch: an old WordPress url with a capital letter that worked for years becomes a 404 on Webflow unless a redirect catches it first.

What the redirect map should contain

one row per page — not one per variant. Search Console and analytics exports list /about-us, /about-us/ and /About-Us as separate rows; they are one page, and three rows for it is three chances to disagree.

rules that match the variants — the slash and the case are handled by how the rule matches, not by extra rows — where the redirect engine can do it (next section).

targets in the new site's exact form — if the new site serves /about/ and the redirect points at /about, every visitor goes old url → /about → /about/: a chain on every single row. Write targets the way the new site links to its own pages.

the variants that really were different pages — rare, but they exist: an old server where /Products and /products were separate pages. Then they are two rows, and the rule must stay case-sensitive.

EXAMPLE

a WordPress site moves to Webflow. Its urls end in a slash, and a few old campaign pages were linked as /Sommer-Aktion/. Webflow strips slashes and answers 404 to capitals, so a row for /sommer-aktion alone may not catch either variant. The map keeps one row per page; the check after import requests /sommer-aktion/ and /Sommer-Aktion/ and adds a row for any variant that does not reach the new page in one hop.

Where the variants come from

A list of old urls is usually stitched together from several sources, and each one spells the same page its own way. That is where duplicate rows come from:

the sitemap — lists the form the cms generates — on WordPress with the slash, on Webflow without.

the crawl — follows links as they were written in templates and in the body text, where an editor may have typed /Kontakt or left off the slash years ago.

Search Console and analytics — report the urls Google indexed or visitors requested, including variants from other people’s links, mixed case from print campaigns and /index.html from an old static site.

the backlink report — whatever other sites typed — the variants nobody on your side ever chose.

Merge these on a normalised key before matching — lowercase, slash removed, index.html removed — and keep the original spellings only to test against afterwards. Host-level variants are a different job: http:// versus https:// and www. versus the bare domain are handled by one redirect on the host, not by rows in the map, and that host redirect should land on the final url in the same hop as the path redirect, not before it.

Writing rules that catch every variant

enginetrailing slashcase
Apache RedirectMatch^/about-us/?$(?i)^/about-us/?$
nginx map~^/about-us/?$plain string keys ignore case; regex: ~*
WordPress · Redirectionignore trailing slashes optionignore case option
Webflowtest after importtest after import
Squarespacetest after importcapitalisation has to match, per its help page
Shopifytest after importtest after import

The two server engines are explicit. Apache’s mod_alias matches the url path case-sensitively; /? before $ makes the slash optional and (?i) turns off case for one rule. nginx’s map module matches plain string keys ignoring case, ~ regex keys case-sensitively and ~* regex keys without case. The Redirection plugin has ignore case and ignore trailing slashes as url options, defaulting to whatever its options page sets.

The hosted platforms document much less. Squarespace’s url mappings page asks you to keep the capitalisation of your urls; Webflow and Shopify say nothing either way about slashes or case in redirects. There the reliable answer is the one you measure: import, then request each variant of a handful of old urls and look at the status codes.

What Silentfrog does with them

Silentfrog fetches every url exactly as it was linked, because many servers answer a normalised form with a redirect or a 404, and then compares pages by a normalised key: lowercase, no trailing slash, no index.html, www. or not. So /About-Us/, /about-us and the Search Console row for /about-us/ become one row in the results, matched once.

The redirects file writes paths in that normalised form. What that means per format:

  • apache and nginx rules end in /?$, so both slash forms match. They are case-sensitive as written; if the old site had capitals in its urls, add (?i) after RedirectMatch 301, or change ~ to ~* in the nginx map (csv to .htaccess or nginx).
  • the Redirection plugin: turn on ignore case and ignore trailing slashes before importing.
  • Webflow, Shopify, Squarespace and plain pairs get the lowercase, slash-less path. Test the slashed and capitalised variants of a few old urls after import and add rows for any that do not redirect.
  • targets are written without a trailing slash too. If the new site’s urls end in a slash — a WordPress site, for instance — add it to the targets before importing, or each redirect lands on the slash-less form and takes a second hop.
# add a trailing slash to every target in a from,to csv (header untouched),
# except targets whose last segment has a file extension (.pdf, .jpg, ...)
sed -E '2,$ { \|/[^/,]*\.[A-Za-z0-9]+$|! s#,(/[^,]*[^/,])$#,\1/#; }' redirects.csv > redirects-slash.csv

Settling it on the new site

A relaunch is the cheapest moment to make the new site consistent, because every url changes anyway:

  • pick one slash form and keep it; most hosted platforms decide this for you, so follow theirs;
  • lowercase every slug, including cms items and uploaded files;
  • link internally to exactly that form, and list exactly that form in the sitemap;
  • let the other form redirect to it, or at least carry a canonical to it;
  • write the redirect targets in that same form, so no old url takes two hops.

Then check the result the only way that proves it: request the old url list, variants included, against the live site, and look for anything other than one 301 followed by a 200. Silentfrog builds the map from both crawls with the variants already merged; the first 50 pages are free.

In short

  • /page, /page/ and /Page are three urls to Google; only the root ignores the slash.
  • Platforms differ: some redirect variants, some serve them with a canonical, some answer 404.
  • One row per page in the map; the variants are matched by the rule, not by extra rows.
  • Apache: /?$ and (?i). nginx: /?$ and ~*. Redirection: ignore case and ignore trailing slashes.
  • Targets in the new site's exact form, or every redirect becomes a chain.
  • On hosted platforms, test the variants after import rather than assuming.