That page is telling you one simple thing: a request went out over HTTP to a host that only accepts HTTPS, so it returned a 403 instead of redirecting.

Why this happens (most common)

  1. Hard-coded http:// URLs in HTML/CSS/JS (scripts, images, beacons, fonts, analytics).
  2. Reverse proxy/ELB misconfig — app is behind TLS, but your app thinks the request is HTTP because X-Forwarded-Proto/“trust proxy” isn’t set, so it refuses it.
  3. Health checks/cron/crawlers hitting http://….
  4. Mixed-content auto-upgrades missing (no CSP upgrade-insecure-requests).

Quick triage

  • In DevTools → Network, see which request returned 403; check Initiator to find the caller.
  • Repo sweep for stray HTTP:
    • macOS/Linux: rg -n "http://(?!localhost)" -g '!node_modules'
    • Windows: git grep -n "http://(?!localhost)"
  • Edge logs: look for 403s and the Host/User-Agent to spot health checks or bots.
  • At the proxy: confirm requests carry X-Forwarded-Proto: https.

Fixes that stick

1) Redirect and forward correctly

Nginx

server { listen 80; server_name _; return 301 https://$host$request_uri; }

# when proxying to app:
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Apache

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

CloudFront/Cloudflare

  • Viewer Protocol Policy: Redirect HTTP to HTTPS
  • Origin Protocol Policy: HTTPS only
  • Enable HSTS (see below).

Kubernetes NGINX Ingress

metadata:
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"

2) Make your app “proxy-aware”

Express

app.enable('trust proxy');
app.use((req,res,next)=> req.secure ? next()
  : res.redirect(301, 'https://' + req.headers.host + req.originalUrl));

Django

SECURE_SSL_REDIRECT = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

Rails

config.force_ssl = true

3) Stop emitting HTTP from the codebase

  • Replace all http:// with https:// (analytics, fonts, images, API calls).
  • Add CSP to auto-upgrade stragglers:
Content-Security-Policy: upgrade-insecure-requests
  • Add a CI guard so this never regresses:
    • Fail build if http:// (non-localhost) appears in web assets.
    • ESLint rule: avoid http URLs in strings (or a custom grep step).

4) Security headers (enforce contract)

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Referrer-Policy: no-referrer-when-downgrade

HSTS ensures browsers won’t even try HTTP next time.

5) Clean up non-browser callers

  • Update health checks and any internal jobs to HTTPS.
  • If a third-party beacon/analytics script was http://, change to https://. (Many gov/analytics endpoints deliberately 403 plain HTTP beacons.)

Bottom line: treat “HTTPS only” as a hard contract. Redirect at the edge, forward proto headers correctly, make the app proxy-aware, purge http:// from the codebase, and lock it with HSTS + CI. If you want, paste the 403 request URL + initiator and I’ll point to the exact culprit.