An HTTPS redirect loop in WordPress usually appears after TLS starts terminating at a load balancer, reverse proxy, or CDN edge. The browser already requests the secure URL, but /wp-admin/, /wp-login.php/, or the front page keeps redirecting back to the same HTTPS address until the client stops with a too-many-redirects error.

WordPress decides whether a request is secure through is_ssl(), and FORCE_SSL_ADMIN or normal canonical redirects use that result early in the request. If PHP never maps the trusted forwarded scheme to $_SERVER['HTTPS'], and the origin web server still runs a generic HTTP-to-HTTPS redirect, both WordPress and the origin can keep trying to upgrade a request that already arrived at the edge over HTTPS.

A stable fix needs three things to agree with each other: the edge must send one trusted HTTPS header, WordPress must map that header in /wp-config.php/ before core loads, and the origin redirect must skip requests whose forwarded scheme is already https. Only trust headers added by infrastructure under direct control, and note that Amazon CloudFront removes X-Forwarded-Proto before forwarding to a custom origin unless a different origin header or origin-side HTTPS strategy is used.

Steps to fix HTTPS redirect loop in WordPress behind a load balancer:

  1. Confirm that the redirect keeps returning the same public HTTPS URL instead of ending on a normal login or page response.
    $ curl -skIL --max-redirs 5 https://www.example.com/wp-admin/
    HTTP/2 302
    location: https://www.example.com/wp-admin/
    ##### snipped #####
    curl: (47) Maximum (5) redirects followed

    The loop covered here repeats the same https://... target. Redirects that switch between different hostnames or from http:// to https:// only once are a different problem.

  2. Confirm which trusted header the load balancer, reverse proxy, or CDN sends to tell the origin that the viewer already used HTTPS.
    location / {
        proxy_pass http://wordpress-origin;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    Use the exact header name that the edge really sends. X-Forwarded-Proto is common, but some platforms use a fixed custom header or CloudFront-Forwarded-Proto instead.

    Amazon CloudFront removes X-Forwarded-Proto before forwarding to a custom origin. Use CloudFront-Forwarded-Proto through an origin request policy or a fixed custom origin header when the behavior already forces HTTPS.

  3. Open /wp-config.php/ and add the trusted-header mapping above the final require_once ABSPATH . 'wp-settings.php'; line.
    $ sudo vi /var/www/example.com/public_html/wp-config.php
  4. Set WordPress to treat the forwarded HTTPS signal as a secure request before the rest of core loads.
    <?php
    define( 'FORCE_SSL_ADMIN', true );
    
    if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && false !== strpos( $_SERVER['HTTP_X_FORWARDED_PROTO'], 'https' ) ) {
        $_SERVER['HTTPS'] = 'on';
    }

    Replace HTTP_X_FORWARDED_PROTO with the actual trusted header name when the edge uses something different.

    The strpos check covers comma-separated values such as http,https that can appear when multiple proxies append scheme data.

    Keep only one FORCE_SSL_ADMIN definition in the file, and never trust client-supplied forwarded headers on a directly reachable origin.

  5. Edit the existing Apache site redirect so it skips requests whose trusted forwarded scheme is already HTTPS.
    # Apache VirtualHost example
    SetEnvIfNoCase X-Forwarded-Proto "^https$" forwarded_https=on
    
    RewriteEngine On
    RewriteCond %{HTTPS} !=on
    RewriteCond %{ENV:forwarded_https} !=on
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

    Change the redirect rule that already handles the site instead of stacking a second HTTPS redirect somewhere else.

    This verified pattern is best placed in the active VirtualHost or server config for the site rather than a second, disconnected rewrite fragment.

    On Nginx origins, the same rule applies: the HTTPS redirect must key off the trusted forwarded-scheme header instead of the local request scheme alone.

  6. Test the Apache configuration and reload the web server after the redirect change passes validation.
    # Ubuntu or Debian
    $ sudo apache2ctl -t
    Syntax OK
    $ sudo systemctl reload apache2
    
    # Fedora, Red Hat, or CentOS Stream
    $ sudo httpd -t
    Syntax OK
    $ sudo systemctl reload httpd

    If the redirect lives only in .htaccess, save the file and verify carefully; the important part is that the redirect skips requests whose trusted forwarded scheme is already https.

  7. Verify that the HTTPS request now ends on a normal WordPress response instead of returning to the same secure URL again.
    $ curl -skIL --max-redirs 5 https://www.example.com/wp-admin/
    HTTP/2 302
    location: https://www.example.com/wp-login.php?redirect_to=https%3A%2F%2Fwww.example.com%2Fwp-admin%2F&reauth=1
    HTTP/2 200
    
    $ curl -skI https://www.example.com/
    HTTP/2 200

    If the loop disappears but WordPress still emits http:// URLs or the wrong hostname, fix the public site URL and cached content separately.