Pacific Blue Software Logo

Redirect www to non-www with htaccess

How to Redirect www to non-www with htaccess

Most sites answer on two names, example.com and www.example.com, and on both http and https. That is four addresses for every page. Search engines treat them as separate pages with the same content, links and analytics get split between them, and a cookie set on one name may not be sent to the other.

The fix is to choose one address and permanently redirect the other three to it. On Apache that takes a few lines in the .htaccess file in the site's root folder.


www or non-www?

It makes no difference to search ranking. Choose the one you already use on your business cards, in your email signature and in existing links, and keep to it. A bare domain is shorter. A www name is easier to point at a CDN, because a DNS CNAME record is allowed on www but not on the bare domain. This site uses the bare domain.


Redirect www to non-www

RewriteEngine On

RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L,NE]

The condition matches any host name that starts with www. and captures the rest of it as %1. The rule sends the visitor to the same path on that name. Because the domain is captured rather than typed in, the same lines work unchanged on any site and on a staging copy.

The query string is carried across automatically, so www.example.com/page?id=5 goes to example.com/page?id=5.


Redirect non-www to www

RewriteEngine On

RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^(.+)$
RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L,NE]

The first condition skips host names that already start with www. Be careful with this one on a server that also answers on subdomains, because shop.example.com would become www.shop.example.com. On such a server use the fixed form instead:

RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [R=301,L,NE]

Force HTTPS and non-www in One Hop

If you also redirect http to https as a separate rule, a visitor to http://www.example.com is bounced twice: first to https on www, then to the bare domain. Each hop costs a round trip. Combine them so every wrong address goes straight to the right one:

RewriteEngine On

RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L,NE]

Apache reads the first two conditions as either: the request is plain http, or the host starts with www. The third condition always matches; its job is to capture the host name without the www, ready for the rule. The correct address, https://example.com, passes the first two conditions and is left alone.


Where to Put It


Traps

The certificate must cover both names

The browser checks the certificate before Apache sees the request, so a visitor to https://www.example.com gets a security warning, not your redirect, if the certificate only covers example.com. Make sure it lists both names. AutoSSL in cPanel and Let's Encrypt usually include www when its DNS record exists.

Browsers remember a 301

A permanent redirect is cached by the browser, often until the cache is cleared. A mistake in the rule keeps happening to you even after you fix the file. While testing use R=302, and change it to R=301 once it works. Test with curl, which caches nothing.

Redirect loops behind a proxy or CDN

Behind Cloudflare in Flexible mode, or a load balancer that handles HTTPS, Apache receives every request as plain http, so %{HTTPS} off is always true and the site redirects forever. Either set Cloudflare to Full (strict), or test the header the proxy adds instead:

RewriteCond %{HTTP:X-Forwarded-Proto} !https [OR]

The DNS record must exist

Requests for www never reach the server, and so are never redirected, unless www has a DNS record pointing at it. Add an A record for www, or a CNAME to the bare domain.


Testing

Ask for each wrong address with curl and read the Location header:

curl -I http://example.com/page
curl -I http://www.example.com/page
curl -I https://www.example.com/page?id=5

Each one should return a single redirect straight to the final address:

HTTP/1.1 301 Moved Permanently
Location: https://example.com/page

And the final address itself should return 200 with no Location header. Two 301s in a row, or a Location pointing at a .php file, means the rules are in the wrong order.


Tell the Search Engines


Summary

Goal Conditions Rule target
www to non-www %{HTTP_HOST} ^www\.(.+)$ https://%1%{REQUEST_URI}
non-www to www %{HTTP_HOST} !^www\. then ^(.+)$ https://www.%1%{REQUEST_URI}
https and non-www %{HTTPS} off [OR] www, then capture without www https://%1%{REQUEST_URI}

Useful References


One Address for Your Site, in One Redirect


Back to Articles for Developers
Back to Website Articles
Previous: How to Generate HTTP Errors with htaccess
Next: web.config Tips and Tricks for IIS

If you found this useful, then please consider chipping in.
Chip In with PayPal
QR Code to chip in Please chip in if helpful