example.com and www.example.com are different hostnames. If both serve the same site, search engines may treat them as duplicates, cookies and analytics split, and links point both ways. Pick one canonical version, and 301-redirect the other to it, keeping the path and query string.

Which should you choose?

Either works for SEO. Common reasons to pick one:

  • Non-www (example.com): shorter, modern look.
  • www (www.example.com): lets you scope cookies to www only, and CNAME it to a CDN. Some DNS providers can’t CNAME the bare domain.

What matters is consistency: the redirect, internal links, canonical tags, sitemaps, and the app’s base URL all use the same host.

Nginx: non-www as canonical

# redirect HTTP (both hosts) → https://example.com
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}

# redirect HTTPS www → non-www
server {
    listen 443 ssl;
    http2 on;
    server_name www.example.com;
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    return 301 https://example.com$request_uri;
}

# the real site
server {
    listen 443 ssl;
    http2 on;
    server_name example.com;
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    root /var/www/example.com;
    # …
}

For www as canonical, swap the names. Use return 301 (fast and clear) rather than rewrite or if blocks. See Nginx HTTP to HTTPS redirect.

The certificate must cover both names, or visitors to https://www.example.com see a certificate error before the redirect happens:

sudo certbot --nginx -d example.com -d www.example.com

See Let’s Encrypt with Certbot.

Apache

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    Redirect permanent / https://example.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName www.example.com
    SSLEngine on
    # SSLCertificateFile …
    Redirect permanent / https://example.com/
</VirtualHost>

Or with mod_rewrite in .htaccess:

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

See Apache .htaccess guide.

Cloudflare

If the site is behind Cloudflare, you can redirect at the edge with a Redirect Rule: when the hostname equals www.example.com, dynamically redirect to concat("https://example.com", http.request.uri.path), with the query string preserved, as a 301. The www DNS record must exist and be proxied (orange cloud). See using Cloudflare with a VPS.

Update the application

  • WordPress: set the Site Address and WordPress Address to the canonical URL. Mismatches cause redirect loops. See change the WordPress site URL and WordPress too many redirects.
  • Frameworks: set the base or app URL (Laravel APP_URL, Django ALLOWED_HOSTS and canonical links).
  • Search Console: add both properties, or a Domain property, and submit the sitemap with canonical URLs.

Test

curl -sI http://www.example.com/blog/?a=1 | grep -iE '^(HTTP|location)'
curl -sI https://www.example.com/blog/?a=1 | grep -iE '^(HTTP|location)'
curl -sI http://example.com/ | grep -iE '^(HTTP|location)'

Each should be a single 301 to https://example.com/…, with the path and query intact. Avoid chains (http://www → https://www → https://non-www) where possible.

301 vs 302

Use 301 (permanent) for canonical-host redirects, so search engines transfer signals. 302 means temporary. Avoid it for this. Browsers cache 301s aggressively, so test with curl rather than your browser while experimenting.

Quick reference

Task How
Nginx Separate server block → return 301 https://example.com$request_uri;
Apache Redirect permanent or mod_rewrite
Certificate Must include both names
Cloudflare Redirect Rule (301, keep query)
Test curl -sI for each variant

Related: Nginx multiple domains with SSL and WordPress redirects.

  • Nginx
  • SEO
  • Redirects