/ โ† Redirect Fixes / 301 Redirect Not Working
In this guide
  1. Why a 301 redirect seems not to work
  2. How to test a redirect properly
  3. Apache, .htaccess, nginx and Plesk
  4. Cloudflare, cPanel, WordPress and site builders
  5. Working redirect rules
  6. A worked example
  7. The fix, step by step
  8. Edge cases worth knowing
  9. Keeping redirects reliable
  10. Questions and answers

Why a 301 redirect seems not to work

A 301 redirect tells browsers and search engines that a page has moved permanently to a new address. When you add one and the old URL still loads, or you remove one and it keeps redirecting, the cause is nearly always one of three things:

  1. A cache is answering instead of your server. Browsers store 301 responses and reuse them without asking again. Page caches and CDNs can also hold the old response.
  2. Another rule handles the request first. A CMS, plugin, hosting panel or CDN rule catches the URL before your redirect gets the chance, or sends it somewhere else afterwards.
  3. The rule is in the wrong place or the wrong format. An .htaccess rule on an nginx server, a path entered with the domain on a site builder, or a pattern that does not quite match the URL being requested.

The first job is to stop guessing which. The browser is the worst tool for this, because it shows what it remembers. A command-line request shows what the server actually sends now.

๐Ÿ’ก Write the redirect, then test it from the command line before telling anyone it works. curl shows the response the server sends now; a browser may be showing one it stored earlier.

How to test a redirect properly

Request the old URL with curl, which never caches redirects:

curl -sI https://www.example.com/old-page

A working redirect returns something like:

HTTP/2 301
location: https://www.example.com/new-page/
server: nginx

To follow the whole chain and see each step, add -L and filter the output:

curl -sIL https://www.example.com/old-page | grep -iE '^(HTTP/|location:|server:|x-redirect-by:|cf-)'

Read the result against this table:

What curl showsWhat it means
200 on the old URLNo redirect is reaching the request; the rule is not being read or not matching
301 to the wrong addressAnother rule runs first, or the target is written wrongly
302 or 307 instead of 301The rule or tool defaults to temporary; set the type explicitly
301 in curl, but the browser behaves differentlyThe browser is using a cached response; clear it or use a private window
Several 301s in a rowRules are stacked; see redirect chains
Redirects back to itself, or curl stops at 30 redirectsA loop; see redirect loops

The headers often tell you which layer answered. cf-ray means Cloudflare, x-redirect-by: WordPress or a plugin name means the CMS, and the server header shows whether Apache, nginx or LiteSpeed sent it. Test every variant too: http and https, with and without www, and with and without a trailing slash, because a rule often matches only one of them.

Apache, .htaccess, nginx and Plesk

Apache and .htaccess

For .htaccess rules to work at all, three things must be true: the server runs Apache or LiteSpeed, the virtual host allows overrides with AllowOverride All (or at least FileInfo), and for RewriteRule the rewrite module is enabled, with RewriteEngine On in the file. A quick test is to put a deliberate typo at the top of .htaccess: if the site does not return a 500 error, the file is not being read.

Common mistakes in the rule itself:

nginx

nginx does not read .htaccess files at all. If the server header says nginx and Apache is not running behind it, every rule in .htaccess is ignored. Redirects go in the server block, and nginx must be reloaded after each change:

sudo nginx -t && sudo systemctl reload nginx

Plesk

On Plesk with nginx in front of Apache, .htaccess works for most pages, because nginx passes them to Apache. But if Serve static files directly by nginx is switched on under Apache and nginx Settings, requests for files such as .pdf or .jpg never reach Apache, so .htaccess redirects for them do nothing. Put those redirects in the Additional nginx directives box instead. On a Plesk site running nginx only, all redirects must go there. See redirects on Plesk and redirects on Apache.

Cloudflare, cPanel, WordPress and site builders

Cloudflare

Cloudflare Redirect Rules only act on traffic that passes through Cloudflare, so the DNS record for the hostname must be proxied, shown by the orange cloud. A grey-cloud record goes straight to your server and ignores every Cloudflare rule. Rules also run in order, so an earlier rule can catch the request first. Check Single Redirects, Bulk Redirects and any old Page Rules for overlapping matches. Purge the cache for the URL after changing anything. See redirects on Cloudflare.

cPanel

The Redirects tool under Domains writes lines into the .htaccess file of the domain's document root. The usual reasons it fails are choosing the wrong domain from the list, the www option not matching how visitors arrive, and the wildcard box being ticked or left unticked by mistake. Open .htaccess in File Manager afterwards and check the generated RewriteCond and RewriteRule lines sit above the WordPress block.

WordPress

Redirect plugins only run when WordPress loads, so a page cache plugin or server cache can serve the old page without WordPress ever seeing the request. Clear the page cache after adding a redirect. WordPress also redirects old post slugs on its own, which can override or confuse a plugin rule. See redirects in WordPress.

Wix, Squarespace and Webflow

PlatformWhere redirects liveCommon reason it fails
WixThe URL Redirect Manager in the SEO settingsFull domain typed in the old URL box; the site is not on a connected custom domain
SquarespaceURL Mappings in the developer tools settings, written as /old-page -> /new-page 301A live page still uses the old path; missing spaces around the arrow
WebflowThe 301 redirects section in Site settingsSite not published after saving; trailing slash not matching the old URL

On all three, enter the old path without the domain, match the trailing slash exactly as the old URL had it, and check that no live page still sits at the old path.

Working redirect rules

One page on Apache

RewriteEngine On
RewriteRule ^old-page/?$ /new-page/ [R=301,L]

# BEGIN WordPress
...

A whole domain on Apache

RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?old-example\.com$ [NC]
RewriteRule ^(.*)$ https://new-example.com/$1 [R=301,L]

One page on nginx

location = /old-page {
    return 301 /new-page/;
}

A whole domain on nginx

server {
    listen 443 ssl;
    server_name old-example.com www.old-example.com;
    # ssl_certificate lines for the old domain go here
    return 301 https://new-example.com$request_uri;
}

$request_uri keeps the path and query string, so every old page goes to its matching new page. The old domain still needs a valid certificate, or browsers stop with a security warning before they ever see the redirect.

โš ๏ธ Test new rules on one URL with a 302 first if you are unsure. Browsers hold on to 301s, so a mistaken permanent redirect can keep sending your own browser, and your visitors, to the wrong page after you fix it. See 302 versus 301.

A worked example

A business renames its services page from /services-old/ to /services/ and adds this to .htaccess:

# BEGIN WordPress
...
# END WordPress
RewriteRule ^/services-old/$ /services/ [R=301,L]

The old URL still loads. curl returns 200. There are two faults. The rule sits below the WordPress block, so WordPress has already taken the request, and the pattern starts with a slash, so it would not match in .htaccess anyway. Moving the rule above # BEGIN WordPress and changing it to ^services-old/?$ gives a 301 in curl straight away.

The owner's browser, however, now loops between the two pages. Earlier that week he had tested a redirect from /services/ to /services-old/, and the browser cached it. A private window shows the redirect working correctly, and clearing the browser cache fixes his own view.

The fix, step by step

Step 1

Test the old URL with curl

Run curl -sI on the old URL and read the status line and Location header. Then run it again with -L to see every hop. Do this for http and https, with and without www, and with and without a trailing slash. Write down what each variant returns. You now know whether the redirect is missing, pointing somewhere wrong, temporary instead of permanent, or working perfectly and hidden by your browser cache.

Step 2

Rule out the browser cache

If curl shows the correct 301 but your browser does not, the browser is replaying a stored response. Open a private window, or in Chrome DevTools tick Disable cache on the Network panel and reload. Clear the browser cache if your normal window still misbehaves. Confirm by loading the old URL in the private window and seeing it arrive at the new address in a single step.

Step 3

Identify which layer answers the request

Look at the response headers from curl. A cf-ray header means Cloudflare responded, x-redirect-by names WordPress or a plugin, and the server header shows Apache, nginx or LiteSpeed. If the redirect you wrote lives in a different layer from the one answering, that layer is catching the request first. Confirm by checking whether the answering layer has its own rule or cached copy for the URL.

Step 4

Put the rule where the server reads it

If the server header says nginx with no Apache behind it, move the rule from .htaccess into the nginx server block, or the Additional nginx directives box on Plesk. On Apache, check that AllowOverride permits .htaccess and that the rewrite module is enabled. For Cloudflare, make sure the DNS record is proxied. Confirm with a curl request that the layer you chose now returns the 301.

Step 5

Correct the rule's syntax and order

On Apache, place the rule above # BEGIN WordPress, remove any leading slash from the RewriteRule pattern and add /? to match with or without a trailing slash. On nginx, use location = /old-page with return 301. On site builders, enter the path only, without the domain. Set the type to 301 explicitly. Reload the server after editing, then test again with curl to see the new response.

Step 6

Remove competing rules

Search every layer for other rules that match the same URL: redirect plugins, the CMS's own slug redirects, the cPanel Redirects tool, Cloudflare Single and Bulk Redirects and any old Page Rules. Delete duplicates so each redirect exists in one place only, and make sure it points straight at the final address. Retest the full chain with curl -sIL and confirm there is exactly one 301 followed by a 200.

Step 7

Clear server and CDN caches

Purge the page cache in your CMS or caching plugin, any server-level cache such as LiteSpeed or Varnish, and the CDN cache for both the old and new URLs. Cached responses can keep serving the old page or an old redirect for hours after the rule changes. Run curl once more after purging and check that the response headers show a fresh response rather than a cache hit.

Step 8

Publish and retest every variant

On Wix, Squarespace or Webflow, publish the site if the platform needs it before redirects go live. Then run your curl loop over every variant of the old URL and confirm each returns a single 301 to the final page. Update internal links, menus and the sitemap to use the new address. Finally, inspect the old URL in Search Console so Google can see the redirect sooner.

Edge cases worth knowing

Keeping redirects reliable

  1. Keep each redirect in one place only: the server, the CMS or the CDN. Write down which layer you use so the next person does not add a competing rule elsewhere.
  2. Point every redirect at the final URL, so a later change does not create a chain.
  3. Keep a simple list of old and new URLs, and test it with a curl loop after every hosting move, plugin change or redesign.
  4. Update internal links to the new URL rather than relying on the redirect for your own menus and content.

If you later need to undo a permanent redirect, the guide to removing a 301 redirect covers the caches involved. For larger moves, see migration redirects.

Questions and answers

1. Why is my 301 redirect not working?

A 301 that seems not to work is nearly always cached, overruled by another rule, or written in the wrong place or format. Browsers store 301s and replay them, so test with curl or a private window. Then check which layer answers the request, since a plugin, CDN or hosting panel can catch the URL first. Finally, check the rule itself: an .htaccess rule does nothing on nginx, and a pattern with a leading slash never matches in .htaccess.

2. Why does my .htaccess redirect not work?

The most common reasons are that the server runs nginx and never reads .htaccess, that the virtual host has AllowOverride set to None, or that the rule sits below the WordPress block, which takes every request first. In .htaccess, RewriteRule patterns also have no leading slash, so a pattern beginning with a slash never matches. Put a deliberate typo at the top of the file: if the site does not return a 500 error, the file is not being read at all.

3. Why is my Cloudflare redirect rule not working?

Cloudflare redirect rules only run on traffic that passes through Cloudflare, so the DNS record for that hostname must be proxied, shown by the orange cloud. A grey-cloud record goes straight to your server and skips every rule. Also check the rule order, because an earlier rule or an old Page Rule can match the request first, and make sure the hostname and path in the rule match exactly. Purge the cache and test with curl afterwards.

4. How do I clear a cached 301 redirect in my browser?

Clear the browser's cached images and files, or test in a private window, which starts with an empty cache. In Chrome you can also open DevTools, tick Disable cache on the Network panel and reload the page while DevTools stays open. Browsers keep 301 responses because they are meant to be permanent, so a redirect you removed can still seem to work, and a new one can seem missing, until the stored copy is gone.

5. How long does a 301 redirect take to work?

A 301 redirect works as soon as the server sends it, which is immediately after you save the rule and reload the server or publish the site. If it seems slow, a cache is in the way: a page cache, a CDN or your browser is still serving the old response. Search engines are different, because they need to recrawl the old URL before updating results, which can take days or weeks for less visited pages.

6. Why does my redirect work on http but not on https?

The rule is probably only in the configuration that handles http on port 80, or the CDN rule is limited to the http scheme. On nginx, http and https are usually separate server blocks, so a rule in one does not apply to the other. On Apache, an https virtual host may point to a different folder or not allow .htaccess. Add the rule where https requests are handled, then test both variants with curl.

7. Should I use .htaccess, a plugin or Cloudflare for redirects?

Use whichever single layer you can manage reliably, and keep all redirects in that one place. Server rules in .htaccess or nginx are fast and do not depend on the CMS. A WordPress plugin is easier to edit but only runs when WordPress loads. Cloudflare rules run before your server and suit domain-wide moves. Problems start when the same URL is redirected in two or three layers, so choose one and remove copies from the others.

Check what your redirects really return

The redirect checker requests each URL fresh, with no browser cache, and shows every hop with its status code and Location header, so you can see straight away whether your 301 is live, wrong or missing.

Open Redirect Fixes โ†’
๐Ÿ’ฌ Got a problem?
Related Guides: All Redirect Fixes  ·  Redirects on Apache  ·  Redirects on Cloudflare  ·  Redirects on Plesk  ·  How to Remove a 301 Redirect  ·  Learning Hub

About aiwebpageseo

aiwebpageseo.com is a data-driven SEO and AEO (Answer Engine Optimisation) platform providing a free suite of technical SEO tools. Rather than relying on AI-theorised assumptions, the platform analyses live URL performance, delivering objective diagnostics, page speed metrics, CLS debugging, and site crawl data alongside actionable technical tutorials.