My Tool Studio
SEO Tools·4 min read

How Htaccess Redirects Work: Apache 301s Explained

Knowing how htaccess redirects work is the difference between a clean site migration and a weekend of 500 errors. The .htaccess file is Apache's per-directory config: the server reads it on every request, top to bottom, and the matching rules decide where each visitor ends up. That makes it powerful and unforgiving in equal measure, since a single stray character applies to every URL you serve. This guide walks through the directives the .htaccess Generator writes, a worked rule you can read token by token, the 301 versus 302 decision, and how to test before anything reaches production.

.htaccess Generatormytoolstudio.com › tools<title>…</title><meta name="description">SEO ready

The migration weekend where the htaccess file earns its keep

One file, every old URL.

Picture a company moving from shop.example-store.com to example-store.com/shop after a rebrand. Hundreds of product URLs have backlinks, bookmarks, and Google rankings attached. If those old addresses start returning 404s on Monday, years of accumulated authority evaporate and revenue follows it down. The fix lives in one Apache config file: a set of 301 rules that catch each old path and forward it, permanently, to its new home.

The same file handles the quieter migrations too. Switching to HTTPS, settling the www question, and killing trailing slash duplicates are all redirects at the host level, and they all belong in .htaccess on Apache servers. Most shared hosting runs Apache, which is why this one file shows up in nearly every migration checklist ever written.

How htaccess redirects work inside Apache

Two modules, two directive styles.

Apache offers two ways to redirect. The simple one is mod_alias: a line like Redirect 301 /old-page /new-page matches a path prefix and sends the browser elsewhere, no conditions, no patterns. It's readable and hard to break, which is why the .htaccess Generator uses it for your custom one-to-one moves.

The heavier tool is mod_rewrite. A RewriteRule applies a regular expression to the requested path, and RewriteCond lines above it add conditions on things like the hostname or whether HTTPS is on. Rules execute in file order, and the L flag stops processing once a rule fires. That ordering matters more than people expect: put a broad catch-all rule above a specific one and the specific rule never runs.

A worked htaccess rule, read token by token

The HTTPS rule, decoded.

Here's the exact pair the generator writes when you tick Force HTTPS. Line one: RewriteCond %{HTTPS} !=on. Line two: RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]. The condition reads the HTTPS server variable and passes only when it isn't on, meaning the request arrived unencrypted.

The rule itself uses ^ as its pattern, which matches every path, because the condition already did the filtering. The target rebuilds the address: https:// plus %{HTTP_HOST}, the domain the visitor asked for, plus %{REQUEST_URI}, the path and query string. The flags finish the job: R=301 makes it a permanent redirect and L stops further rules from touching this request. So a request for http://example.com/pricing?plan=pro answers with 301 and a Location header of https://example.com/pricing?plan=pro. Add a custom line like Redirect 301 /old-pricing /pricing and that legacy path gets its own permanent forward with no regex involved.

301 vs 302 in htaccess: one number, two promises

Permanent or temporary, choose deliberately.

The difference between 301 vs 302 in htaccess is a single character in the flag, but the consequences diverge for months. R=301 tells browsers and crawlers the move is permanent: caches store it, Google transfers ranking signals to the target, and the old URL drops out of the index over time. R=302 promises the move is temporary, so search engines keep the original URL indexed and wait for it to come back.

Use 301 for migrations, rebrands, and merged pages. Reserve 302 for genuinely short-lived situations, a checkout under maintenance or a seasonal landing page. The expensive mistake is shipping 302s during a migration because a plugin defaulted to them; signals stall on dead URLs while the new ones start from nothing.

Htaccess mistakes that take whole sites down

Learned the hard way, repeatedly.

Because Apache parses .htaccess on every request, errors hit instantly and globally. These are the classics:

  • A syntax typo, even one misspelled directive, returns 500 for the entire site, not just the broken rule.
  • Redirect loops: an HTTPS rule and a www rule that each rewrite the other's output until the browser gives up with too many redirects.
  • Forgetting the L flag, so a request keeps matching later rules and lands somewhere nobody intended.
  • Dropping query strings by writing an explicit target without preserving %{REQUEST_URI} or the QSA flag, which silently strips tracking parameters.
  • Editing the live file over FTP with no backup, so there's nothing to roll back when the phone starts ringing.

Testing rewrite rules safely before they touch production

Three habits, zero downtime.

Testing rewrite rules safely starts with never composing them on the live server. Build the file in the .htaccess Generator, then stage it: a subdomain, a local Apache in Docker, or your host's staging copy all work. Curl is your verifier; curl -I http://example.com/old-page shows the status line and Location header without a browser cache muddying the result.

Two more habits pay off. First, change one thing at a time, because two new rules that interact are exponentially harder to debug than one. Second, keep the previous .htaccess as .htaccess.bak beside the new one, so rollback is a rename instead of an archaeology project.

Where the .htaccess Generator hands off to other tools

Generate here, verify elsewhere.

The .htaccess Generator writes the rules; proving they behave is a separate job. After deploying, run key old URLs through the Redirect Chain Checker to confirm each one reaches its destination in a single hop, and use the HTTP Status Checker to verify the code returned is the 301 you intended rather than a 302 something else injected.

If your duplicate problem is about which version of a live page should rank rather than about forwarding dead ones, that's a job for the Canonical Tag Generator instead; a canonical hint keeps both URLs reachable while a redirect removes one from circulation.

Try it now

Open .htaccess Generator

The tool is one click away. No sign up, no upload, no payment.

Open .htaccess Generator