Apache configuration

.htaccess Guide: Redirects, Rewrites, HTTPS Rules and Examples

The .htaccess file is one of the most useful and most dangerous files on an Apache website. It can redirect old URLs, force HTTPS, create clean URLs, block access and add simple security headers. It can also break the entire site with one bad rewrite rule, because apparently Apache enjoys drama.

This guide explains practical .htaccess rules with examples, expected outputs, testing commands and FAQs. If you want to generate rules interactively, try the .htaccess Rule Builder.

Before you edit .htaccess: always make a backup first. On cPanel or most Linux hosting accounts, you can usually do this from the command line with cp .htaccess .htaccess.bak.$(date +%F-%H%M).

What is .htaccess?

.htaccess is a per-directory Apache configuration file. It lets you apply rules to a website without editing the main Apache virtual host configuration. On shared hosting, reseller hosting and many cPanel servers, it is commonly used for redirects, rewrite rules, access control and cache or header tweaks.

Common uses

Redirecting old URLs, forcing HTTPS, removing file extensions, blocking access, setting error pages and adding headers.

Common risk

A bad rewrite can cause redirect loops, 403 errors, 404 errors or a full 500 Internal Server Error.

Before editing .htaccess

Before adding new rules, check that you are editing the right file and that you can recover if something goes wrong.

cd /home/example/public_html
cp .htaccess .htaccess.bak.$(date +%F-%H%M)
ls -la .htaccess*

Example output:

-rw-r--r-- 1 example example 2198 May 15 14:20 .htaccess
-rw-r--r-- 1 example example 2198 May 15 14:22 .htaccess.bak.2026-05-15-1422

After changing rules, test with curl -I. This shows the HTTP status and redirect target without loading the whole page.

curl -I https://example.com/old-page

301 redirect one old URL to a new URL

Use a 301 redirect when a page has permanently moved. This is useful for SEO because it points users and search engines to the preferred new URL.

RewriteEngine On

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

Test it:

curl -I https://example.com/old-page

Expected output:

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

Redirect an old .html URL to a clean URL

RewriteEngine On

RewriteCond %{THE_REQUEST} \s/+(.+?)\.html[\s?] [NC]
RewriteRule ^(.+?)\.html$ /$1 [R=301,L]

This redirects /about.html to /about only when the browser directly requests the .html version.

Force HTTPS

If your SSL certificate is installed and working, you can redirect HTTP requests to HTTPS.

RewriteEngine On

RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Test it:

curl -I http://example.com/

Expected output:

HTTP/1.1 301 Moved Permanently
Location: https://example.com/
Tip: make sure HTTPS works before forcing it. If the certificate is broken, forcing HTTPS can make the site look completely down.

Force www or non-www

You should choose one preferred host version. For example, use either example.com or www.example.com, not both.

Force non-www

RewriteEngine On

RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^ https://example.com%{REQUEST_URI} [R=301,L]

Force www

RewriteEngine On

RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^ https://www.example.com%{REQUEST_URI} [R=301,L]

Test it:

curl -I https://www.example.com/blog

Expected output for non-www:

HTTP/2 301
location: https://example.com/blog

Serve clean URLs from PHP or HTML files

Clean URLs are easier to read and share. Instead of showing /blog.php, you can serve the same file from /blog.

RewriteEngine On

RewriteRule ^blog/?$ blog.php [L,QSA]
RewriteRule ^quizzes/?$ quizzes.php [L,QSA]
RewriteRule ^cheat-sheets/?$ cheat-sheets.php [L,QSA]

Test it:

curl -I https://example.com/blog

Expected output:

HTTP/2 200
content-type: text/html; charset=UTF-8

Fallback for real .html files

If you have files like grep-quiz.html but want /grep-quiz to work, use a careful fallback rule.

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.+?)/?$ $1.html [L]
Order matters: specific rules should usually appear above generic fallback rules. Otherwise the generic rule may catch the request first.

Access control examples

Disable directory listing

This stops Apache from showing a list of files when a directory has no index file.

Options -Indexes

Block one IP address

<RequireAll>
    Require all granted
    Require not ip 203.0.113.10
</RequireAll>

Allow only one IP address

Require ip 203.0.113.10
Be careful: allow-only rules can lock you out of a web path. Keep SSH, FTP or file manager access available before testing.

Simple security headers

Some headers can be added from .htaccess if Apache has mod_headers enabled.

<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>

Test it:

curl -I https://example.com/

Expected output:

x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
referrer-policy: strict-origin-when-cross-origin

Troubleshooting .htaccess errors

If a rule breaks the site, check the HTTP status and Apache error log.

curl -I https://example.com/
tail -50 /usr/local/apache/logs/error_log

500 Internal Server Error

A 500 often means a syntax error, unsupported directive or invalid regular expression.

HTTP/2 500
content-type: text/html; charset=iso-8859-1

403 Forbidden

A 403 can be caused by access rules, directory listing being disabled, ModSecurity, file permissions or Apache trying to serve a directory instead of a rewritten file.

HTTP/2 403
content-type: text/html; charset=iso-8859-1

Too many redirects

This usually means two rules are fighting each other, such as forcing www and non-www at the same time.

curl -I -L https://example.com/old-page

For more command-line troubleshooting practice, see the Linux Troubleshooting Hub, the grep Command Builder and the dig Command Builder.

Useful .htaccess workflow

  1. Back up the current file.
  2. Add one rule at a time.
  3. Test with curl -I.
  4. Check for redirect loops.
  5. Check Apache logs if you see 403 or 500 errors.
  6. Only use 301 redirects when the move is permanent.
  7. Keep specific rules above generic fallback rules.

You can also use the .htaccess Rule Builder to generate common snippets and then adapt them carefully.

FAQ

.htaccess FAQ

Where is the .htaccess file located?

It is usually in the website document root, such as public_html/.htaccess. Some applications also use additional .htaccess files in subdirectories.

Why does .htaccess cause a 500 error?

A 500 error often means Apache found an invalid directive, bad syntax, unsupported module or a rewrite rule it cannot process. Check the Apache error log for the exact reason.

Should redirects go at the top or bottom?

Specific redirects should usually go near the top, before generic rewrite or fallback rules. Rule order matters because Apache processes them from top to bottom.

What is the difference between RewriteRule and Redirect?

Redirect is simpler and useful for basic redirects. RewriteRule is more flexible and can use conditions, patterns and flags.

What does [R=301,L] mean?

R=301 means send a permanent redirect. L means stop processing rules when this rule matches.

What does [L,QSA] mean?

L means stop processing rules. QSA means query string append, which keeps existing query parameters when rewriting.

Can .htaccess improve SEO?

Yes, mostly by fixing redirects, avoiding duplicate URL versions, forcing the preferred HTTPS and host version, and making sure old URLs point to the correct new pages.

Can I use .htaccess on Nginx?

No. .htaccess is an Apache feature. Nginx uses server block configuration instead.

$ practise_next --topic linux

Practise this next

Turn the guide into practice with a related quiz, builder, cheat sheet or learning path.