Skip to content
Instant · runs in your browser

htaccess Generator

HTTPS, canonical host, redirects, caching and headers - in the right order.

htaccess generator output runs before anything else your Apache server does, on every single request, which is why the order of the blocks matters more than the blocks themselves. A correct HTTPS rule placed after a correct redirect rule produces 2 301s where one would do, and in the wrong combination it produces a loop. This tool assembles the directives an SEO actually touches, in the order that keeps them from fighting, with the <IfModule> guards that keep a missing module from taking the site down.

Both hostnames serving the same page splits your signals across two URLs. Pick one.

Fill this in and a visitor gets sent straight to the right address in one hop instead of two. Without it we still work, just less efficiently.

/page and /page/ are two URLs to a crawler. Pick one and enforce it.

Leave Type blank for a normal permanent move (301). Use 302 if the move is temporary, or 410 if the page is gone for good and you are not replacing it. These run after the HTTPS and www rules above.

The path on your site, starting with a slash. Leave blank to keep the default one.

Order is the whole feature

The generated file always sequences the rewrite block the same way:

  1. Scheme and host canonicalization
  2. Custom redirects
  3. Trailing-slash policy

The reasoning is mechanical. A request for http://www.example.com/old-page that hits your custom redirect first gets sent to http://www.example.com/new-page, which is still on the wrong scheme and the wrong host, so it is canonicalized on the next pass. That is 2 hops instead of one, and every hop bleeds a little link equity and adds a round trip. Reverse 2 rules that both rewrite the host and you get a redirect loop that only shows up on one hostname, which is a miserable afternoon.

Trailing-slash normalization goes last so it tidies whatever the rules above produced rather than the other way round. Custom redirect patterns are written to tolerate an optional trailing slash, so they keep matching once that policy is switched on.

One hop instead of 2

The domain field is optional and it changes the output materially. Leave it blank and HTTPS and host canonicalization are 2 independent rules, so http://www.example.com costs 2 redirects. Fill it in and both collapse into one:

<IfModule mod_rewrite.c>
  RewriteEngine On

  RewriteCond %{HTTPS} off [OR]
  RewriteCond %{HTTP_HOST} !^example\.com$ [NC]
  RewriteRule ^ https://example.com%{REQUEST_URI} [R=301,L]
</IfModule>

One rule, one 301 to the final URL, whichever of the four wrong variants the request arrived on.

One caveat the generator prints as a comment: behind a proxy or CDN, %{HTTPS} reads off on every request because TLS terminated at the edge. Swap that first condition for RewriteCond %{HTTP:X-Forwarded-Proto} !https or the rule redirects forever.

Canonical host and trailing slashes in htaccess rules

The canonical host field takes 3 values: leave alone, force www, force non-www. Which one you pick has no ranking effect. Serving both does, because www.example.com/pricing and example.com/pricing are 2 URLs to a crawler, splitting whatever signals the page has earned.

Trailing slash is the same argument one level down. /pricing and /pricing/ are distinct URLs. Either policy ships with the guard that keeps it safe:

  • Add skips anything that looks like a real file, so /robots.txt is never rewritten to /robots.txt/.
  • Remove skips real directories, because mod_dir issues its own DirectorySlash redirect adding the slash back, and the 2 rules will ping-pong until the browser gives up.

Writing redirect lines with a rule generator

The redirects field takes one rule per line, from | to | status:

/old-pricing        | /pricing        | 301
/2019/legacy-post   | /blog/legacy-post
/discontinued-item  | /shop           | 410

Status is optional and defaults to 301. Accepted values are 301, 302, 303, 307, 308 and 410. Anything else falls back to 301 with a warning, because Apache will not emit an arbitrary code from a RewriteRule here.

Use 301 for a move that is permanent, which is nearly always. 302 and 307 tell search engines to keep the old URL indexed, which is right for a seasonal campaign page and wrong for a site migration. 410 is not a redirect at all: it emits [G,L] and tells crawlers the URL is intentionally gone, which gets it dropped faster than a 404.

The audit catches 4 things before they reach the server:

  • Self-redirects. A rule pointing at its own source loops until the browser stops it. Skipped.
  • Duplicate sources. If /old is the source of 3 rules, only the first ever fires. The other 2 are dead lines someone will one day "fix" by editing the wrong one.
  • Chains. /a → /b where /b → /c costs 2 hops. Point the first rule at /c.
  • Redirecting /. Sending the site root somewhere catches the destination too. That belongs at the vhost or DNS level, not here.

Destinations containing a ? get the QSA flag so the incoming query string survives. Worth knowing: RewriteRule matches the path only, never the query string. To redirect based on a parameter you need a RewriteCond %{QUERY_STRING} in front of it.

Compression, caching, and headers worth setting

Gzip wraps mod_deflate and lists the text types worth compressing: HTML, CSS, JavaScript, JSON, XML, SVG and fonts. Images, video and PDFs are deliberately absent. They are already compressed, so deflating them burns CPU to save nothing.

Browser caching wraps mod_expires with long lifetimes for static assets and zero for HTML. That asymmetry is the point. Cache a fingerprinted CSS file for a year and it never gets refetched; cache HTML for a year and you cannot ship a fix.

Security headers is a checkbox group with 3 entries, all uncontroversial:

  • X-Content-Type-Options: nosniff stops browsers guessing a MIME type you did not send.
  • X-Frame-Options: SAMEORIGIN allows framing from your own origin only.
  • Referrer-Policy: strict-origin-when-cross-origin keeps your outbound referrals attributable without leaking full paths.

Directory listings and a 404 that returns 404

Disable directory listing emits Options -Indexes, which stops Apache generating a browsable file index for any folder without an index file. Those listings expose files nobody ever linked to, and Google indexes them happily.

Custom 404 writes an ErrorDocument 404 line. The path must be site-root-relative, like /404.html. This is the one field where a plausible-looking value breaks things: give it an absolute URL such as https://example.com/404.html and Apache stops serving the error document and issues a 302 to that URL instead. The page then returns 200. That is a soft 404, and it is worse than the default Apache error page because search engines will index it.

Before you overwrite the generated configuration file on the server

Back up the existing file first, somewhere outside the document root. Then confirm 3 things:

  • The server reads the file. .htaccess only applies where the vhost sets AllowOverride All (or at minimum FileInfo). Otherwise it is read and silently ignored, which looks identical to a syntax error you cannot find.
  • The chain is one hop. curl -sIL https://example.com/old-pricing prints every response in the chain. You want exactly one 301 landing on a 200.
  • Nothing upstream intercepts. On nginx none of this applies. Behind a CDN, edge rules may fire before Apache sees the request at all, so a redirect that "does not work" may be working perfectly under a rule you forgot about.

Every block sits inside its <IfModule> guard, so a host missing mod_deflate or mod_expires serves the site normally instead of returning a 500 on every request.

Frequently Asked Questions

Why is my .htaccess being ignored?

Almost always AllowOverride. If the vhost sets it to None, Apache never reads the file. Second most likely: the file is not in the document root, or it was uploaded as htaccess.txt because the browser refused to save a dotfile.

Should I use 301 or 302?

301 for anything permanent, which includes almost every SEO redirect. 302 and 307 keep the old URL in the index and pass no signal to the destination, so they suit temporary campaign or maintenance URLs and nothing else.

Does forcing www help or hurt rankings?

Neither. What hurts is serving both without picking one. Choose whichever you already use in your canonical tags and internal links, and enforce it.

Can I redirect based on a query string?

Not with RewriteRule alone, since it matches the path only. Add RewriteCond %{QUERY_STRING} ^id=42$ above the rule, and remember to append ? to the destination if you want the original query string dropped.

Is 410 better than 404 for a removed page?

For a page you deliberately deleted with nothing to replace it, yes. Both eventually drop out of the index; 410 states the intent explicitly and tends to be processed faster. Use 404 when you genuinely do not know whether the URL should exist.

Server config is a one-time job. Keeping the pages behind those URLs worth crawling is the recurring one, and that is what BlazeHive automates end to end.

Related free tools

All tools →