Redirecting HTTP to HTTPS
Having HTTPS is only half the job. Visitors still reach the http:// version of your site: when
they type example.com without a scheme, follow an old link or open an old bookmark. If that
version serves the page instead of redirecting, those visitors stay on an unencrypted connection.
Why it matters
A page served over HTTP has none of the protection HTTPS gives: anyone on the network path can read or change it, including any links or forms that would have taken the visitor to the secure site.
A permanent redirect from every http:// URL to its https:// equivalent fixes that for each
visit, and tells search engines that the HTTPS URLs are the ones to index. It also avoids having
two copies of every page.
A redirect alone still leaves the very first request on plain HTTP. HSTS closes that gap for returning visitors, and it requires the redirect to be in place first.
What we check
We request the http:// version of the scanned page and follow up to two redirects.
| Result | When |
|---|---|
| Pass | the request ends on an https:// URL, or a redirect points to https:// |
| Fail | the http:// URL serves a response without redirecting to HTTPS |
| Info | nothing accepts connections on port 80, so nothing is served over HTTP |
| Couldn’t test | the request failed for another reason, such as a timeout |
The “info” case is fine from a security point of view, but visitors who type your domain without
https:// may get a connection error in browsers that try HTTP first. A redirect gives them a
working page.
How to fix
Redirect every HTTP request to the same host and path on HTTPS with a 301 (permanent) status.
308 also works and keeps the request method for non-GET requests.
Nginx
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
$request_uri keeps the path and query string, so http://example.com/a?b=1 goes to
https://example.com/a?b=1.
Apache (in the port 80 virtual host or .htaccess)
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Or, in a dedicated <VirtualHost *:80>:
Redirect permanent / https://example.com/
Cloudflare: SSL/TLS → Edge Certificates → Always Use HTTPS → On. Cloudflare then redirects at the edge before the request reaches your server.
Behind a load balancer or proxy that terminates TLS, your application sees every request as
HTTP. Redirect at the proxy, or have the app check the X-Forwarded-Proto header from your trusted
proxy instead of the connection scheme. Otherwise HTTPS requests get redirected to HTTPS again in a
loop.
Things to watch
- Use a permanent redirect.
302and307are temporary; browsers and search engines keep coming back to the HTTP URL. - Keep the path. Sending every HTTP URL to the HTTPS home page breaks deep links.
- Redirect to the same host first if you plan to preload HSTS:
http://example.com→https://example.com, then any www/non-www redirect. - Do not serve content on port 80 for any other purpose, except ACME HTTP-01 challenges
(
/.well-known/acme-challenge/) if your certificate client needs them. Most clients handle those before the redirect applies.
MDN’s guide to redirections in HTTP explains the redirect status codes and how browsers treat each one.