How to Set Up htaccess 301 Redirects on Apache

A step-by-step guide to htaccess 301 redirects using mod_alias and mod_rewrite, plus how Google treats permanent redirects during a site move.

SEOAgent team · · 11 min read

A site owner moving pages around on Apache has exactly one file to edit for a permanent redirect: .htaccess. Htaccess 301 redirects tell both visitors and Google that a URL has moved for good, and the syntax lives in two different Apache modules depending on how simple or complicated the move is. Get the directive, the status code or the rule order wrong, and a redirect that looks fine in a browser can still leave Google showing the wrong URL for months.

Htaccess 301 redirects are permanent redirect rules placed in the .htaccess file at a site's document root. mod_alias handles the simple case with Redirect permanent "/old" "/new"; mod_rewrite handles pattern-based cases with RewriteRule "^/old$" "/new" [R=301,L]. Apache returns an HTTP 301 status, and Google's indexing pipeline treats that as a signal to make the new URL canonical.

Prerequisites

  • Access to the .htaccess file in your site's document root, through FTP/SFTP, your host's file manager, or SSH.
  • Confirmation that the site runs on Apache. .htaccess rules only work there; NGINX uses its own location and rewrite syntax in a server block instead.
  • A list mapping each old URL to its new destination. Google's guidance on moving a site points to your sitemap, your server logs, or the "Links to your site" report in Search Console as good places to find the old URLs worth prioritizing.
  • If this is a full site move (a new domain, HTTP to HTTPS, or restructured paths), both the old and new site verified as separate properties in Search Console, including every HTTP, HTTPS, www and non-www variant.

Step 1: Decide between mod_alias and mod_rewrite

Apache ships two modules that can write a redirect into .htaccess, and its documentation is direct about which one to reach for first. mod_alias is built for simple URL manipulation: one old path going to one new path. mod_rewrite exists for the harder cases, redirects that depend on a pattern, a query string, a header or a condition. Apache's "When not to use mod_rewrite" page treats mod_rewrite as a last resort, warning that using it when a simpler directive would do produces configuration that's harder to read and harder to maintain. For most one-to-one page moves, that means mod_alias's Redirect directive is the right starting point, not RewriteRule.

Step 2: Writing htaccess 301 redirects with mod_alias

Redirect is the mod_alias directive for this, and unlike Alias, Apache documents it as working directly inside .htaccess, alongside server config, virtual host and directory contexts. Add this line to send one URL permanently to another:

Redirect permanent "/old" "https://example.com/new"

The syntax is Redirect [status] [URL-path] URL. Leave the status off and Apache defaults to a 302, a temporary redirect, so you have to type permanent to get a 301. The old URL-path must start with a slash and is case-sensitive; the new URL can be a full address on another host or a path on the same site.

Redirect also carries forward anything after the matched path. Apache's own example: a rule redirecting /service to http://foo2.example.com/service will carry a request for /service/foo.pl?q=23&a=42 through to http://foo2.example.com/service/foo.pl?q=23&a=42 automatically, GET parameters included, though POST data is discarded.

The status keyword accepts more than permanent and temp. seeother returns a 303, for a resource that's been replaced; gone returns a 410 for a resource that's been permanently removed, and when you use gone, leave the destination URL out entirely. For a temporary move, use:

Redirect temp "/two-old" "https://example.com/two-new"

Google's guidance explains why the distinction matters: a 301 is a signal to the indexing pipeline that the new URL should become canonical, while a 302 leaves the old URL in Google's search results, which is what you want if the change isn't permanent.

Step 3: Write pattern-based redirects with mod_rewrite

When a redirect depends on a pattern rather than one fixed path, RewriteRule takes over. Google's own documentation pairs a permanent example with its temporary counterpart in the same block:

RewriteEngine on
# redirect the service page to a new page with a permanent redirect
RewriteRule   "^/service$"  "/about/service"  [R=301]
# redirect the service page to a new page with a temporary redirect
RewriteRule   "^/service$"  "/about/service"  [R]

Every mod_rewrite block in .htaccess needs RewriteEngine on as its first line; without it, the RewriteRule lines that follow do nothing. [R=301] makes the redirect permanent; [R] alone defaults to temporary, the same way an unflagged Redirect directive defaults to a 302. Add [L] whenever a .htaccess file has more than one rule in play, so Apache stops checking once that rule matches instead of testing every rule after it.

Step 4: Force HTTPS site-wide

Redirecting an entire site from HTTP to HTTPS is one of the most common reasons to reach for mod_rewrite in .htaccess. Apache's documentation is upfront that the better fix, when you have access to the main server configuration, is a Redirect directive in a dedicated HTTP virtual host rather than mod_rewrite at all. Without that access, mod_rewrite becomes the right tool for the job:

RewriteEngine On
RewriteCond "%{HTTPS}" !=on
RewriteRule "^(.*)" "https://%{SERVER_NAME}$1" [R=301,L]

%{HTTPS} reads on when the connection already uses SSL/TLS, and is empty or off otherwise, so this condition only fires for plain HTTP requests. R=301 is what tells search engines the HTTPS version is now canonical.

Behind a load balancer or reverse proxy

If SSL ends at a load balancer or reverse proxy in front of Apache, mod_ssl never handles the encrypted connection, so %{HTTPS} always reports off, even for visitors who arrived over HTTPS. Check the header your proxy sets instead, usually X-Forwarded-Proto:

RewriteEngine On
RewriteCond "%{HTTP:X-Forwarded-Proto}" =http [NC]
RewriteRule "^(.*)" "https://%{SERVER_NAME}$1" [R=301,L]

Only trust that header if you control the upstream proxy and it overwrites the header on every request. A client connecting straight to Apache can otherwise forge X-Forwarded-Proto itself.

Keep certificate renewals working

Forcing HTTPS site-wide can lock out Let's Encrypt and other ACME clients, which need plain HTTP access to /.well-known/acme-challenge/ to complete domain validation. Place an exception before the redirect rule:

RewriteEngine On
RewriteRule "^/\.well-known/acme-challenge/" - [L]
RewriteCond "%{HTTPS}" !=on
RewriteRule "^(.*)" "https://%{SERVER_NAME}$1" [R=301,L]

The dash substitution tells Apache not to rewrite that request at all, and [L] stops processing there, so ACME challenge requests are served over plain HTTP while everything else still redirects to HTTPS.

Step 5: Redirect www to non-www (or the reverse)

Picking one canonical hostname and redirecting every other variant to it keeps Google from treating www.example.com and example.com as two different sites, and avoids cookie-scope issues between them. Apache's documentation recommends doing this with a Redirect directive in a dedicated virtual host when you have that access, or an <If> block in Apache 2.4 and later. Restricted to .htaccess, the mod_rewrite version looks like this:

RewriteCond "%{HTTP_HOST}" "!^www\.example\.com" [NC]
RewriteCond "%{HTTP_HOST}" "!^$"
RewriteRule "^/?(.*)" "http://www.example.com/$1" [L,R,NE]

To strip a www. prefix instead, swap the condition:

RewriteCond "%{HTTP_HOST}" "^www\.(.+)$" [NC]
RewriteRule "^(.*)" "http://%1/$1" [L,R,NE]

Apache's own example uses a bare R flag here, which defaults to temporary, the same way an unflagged Redirect directive does. Change it to [L,R=301,NE] on both rules if you want Google to treat the result as a permanent, canonical destination.

Step 6: Keep your rule order straight

Two ordering rules affect .htaccess once you have more than one redirect in play. Within mod_alias itself, Redirect directives are processed before Alias directives, and when more than one Redirect or RedirectMatch could match the same request, Apache applies them in the order they appear in the file, with the first match winning, so list the more specific path above the more general one. Across modules, the order flips depending on context: in server or virtual-host configuration, mod_rewrite runs first, but in per-directory context, which is what a .htaccess file is, mod_alias runs first. Mixing Redirect and RewriteRule in the same .htaccess file without accounting for that order is a common reason a rule seems to be ignored.

Step 7: Expect some fluctuation, and watch it in Search Console

Once the redirects are live, don't expect search results to update overnight. Google's guidance on moving a site says ranking fluctuation during this period is normal: for medium-sized sites, it can take a few weeks or more for Google to gradually show the new URLs instead of the old ones, and longer for larger sites, while Googlebot recrawls and reindexes everything. Submitting a sitemap with the new URLs can speed up discovery. The one thing you don't need to worry about is link equity: 301s and other permanent redirects don't cause a loss in PageRank.

Even after things settle, the old URL can keep surfacing now and then. Google calls this an alternate name: once a redirect is permanent, Google treats the new URL as canonical but keeps a record of the old one, and a search query that hints a user might trust the old address better can still bring it up. This is normal, and it fades on its own as people get used to the new URL.

Verify both the old and new sites as separate properties in Search Console, and check the Index Status and Sitemaps reports on each to see how the move is progressing. SEOAgent's rank tracking keeps a position chart over time for the pages you redirected, which makes that fluctuation easier to read than scanning reports one by one.

Common mistakes

  • Forgetting the permanent keyword or the =301 flag. Without it, Apache ships a 302 by default, and Google keeps the old URL in search results instead of switching to the new one.
  • Putting an Alias directive in .htaccess expecting it to redirect something. Apache restricts Alias to server and virtual-host configuration; it has no effect in a .htaccess file, which is exactly where this guide's rules live. Use Redirect instead.
  • Leaving internal links pointed at the old URLs. Google's site-move guidance calls out updating internal links on the new site as its own step, separate from setting up the redirect. SEOAgent's site audit crawls a site and flags broken internal links and orphan pages, which catches anything still pointing at a pre-redirect URL.
  • Reaching for mod_rewrite on a simple one-to-one move, when Apache's own guidance already says Redirect or RedirectMatch is the better choice for exactly that case.
  • Trusting %{HTTPS} behind a reverse proxy or load balancer, where it always reports off even on an HTTPS connection, because mod_ssl never handles the connection directly in that setup.
  • Chaining too many redirects together. Googlebot follows up to 10 hops, but Google recommends redirecting straight to the final destination whenever possible, and keeping any unavoidable chain to no more than 3 and fewer than 5 hops, since each extra hop adds latency and not every browser handles long chains well.

What's new (as of 2026-10-26)

Apache's "When not to use mod_rewrite" page now states the mod_alias-first guidance more directly than most older tutorials do: use Redirect or RedirectMatch for a simple URL-to-URL move, and save mod_rewrite for redirects that depend on a pattern or a condition. Google's redirects documentation, last updated 14 April 2026, still organizes the whole topic around the same two outcomes covered in this guide: a permanent redirect moves the ranking signal to the new URL, and a temporary one leaves it on the old one.

For how these same redirects affect crawl budget, link equity and the rest of a site's SEO beyond the .htaccess file itself, see our guide to 301 redirects and SEO.

Key takeaways

  • An .htaccess redirect only becomes a 301 when you say so explicitly, with Redirect permanent in mod_alias or [R=301] in mod_rewrite; otherwise Apache defaults to a 302.
  • Redirect works inside .htaccess; Alias does not. Apache restricts Alias to server and virtual-host configuration.
  • Google's own guidance confirms that 301s and other permanent redirects don't cause a loss in PageRank, though rankings can fluctuate for a few weeks or more on medium-sized sites while Google recrawls and reindexes.
  • Inside .htaccess, mod_alias directives run before mod_rewrite directives, the opposite order from server and virtual-host configuration, which can make a rule look ignored if you mix the two without accounting for it.
  • Redirect chains should go straight to the final URL. Google follows up to 10 hops but recommends staying at no more than 3 to 5.

FAQ

Will htaccess 301 redirects hurt my search rankings?

No, not permanently. Google's own guidance on moving a site states that 301s and other permanent redirects don't cause a loss in PageRank. Expect temporary ranking fluctuation while Google recrawls and reindexes the new URLs, which for medium-sized sites can take a few weeks or more, and longer for larger ones; submitting a sitemap for the new URLs helps Google discover them faster.

What's the difference between a 301 and a 302 redirect in .htaccess?

A 301, or 308, tells Google the move is permanent, and the indexing pipeline uses it as a signal to show the new URL in search results going forward. A 302, or 303 or 307, tells Google the move is temporary, so the old URL keeps appearing in search results and the new page is only indexed if other signals support it. In mod_alias, the Redirect directive defaults to a 302 unless you add the word permanent.

Should I use mod_alias or mod_rewrite for my redirects?

Apache's own documentation recommends mod_alias's Redirect or RedirectMatch directives for a simple redirect from one URL to another, and reserves mod_rewrite for redirects that depend on a pattern, a query string or a condition. Using mod_rewrite for a case that Redirect could handle tends to produce configuration that's harder to read and maintain later.

How many redirects can I chain together in .htaccess?

Googlebot will follow up to 10 hops in a redirect chain, but Google recommends redirecting straight to the final destination whenever that's possible. If a chain can't be avoided, keep it short, ideally no more than 3 and fewer than 5 hops, since each extra hop adds latency and not every browser or crawler handles long chains well.

Can .htaccess redirects handle a full domain move?

Yes. Google's guidance on moving a site recommends mapping every old URL to its new destination and setting up server-side permanent redirects between them, which on Apache usually means .htaccess rules. For small or medium-sized sites, Google recommends moving all the URLs at once rather than in sections; larger sites can move section by section to make problems easier to catch and fix.

More from the blog

See which searches your site can win

Add your domain and the first research run lists them. That first run uses no credits.