.htaccess & URL Rewrites

Common .htaccess URL Rewrite Rules

By the Domain India teamPublished 9 min read
Knowledge base article
Contents (10 sections)

This is a copy-and-adapt collection of the .htaccess rewrite rules people ask for most: redirects, clean URLs, trailing slashes, maintenance mode and simple security rules. Every rule is written for Apache 2.4 and is safe against the redirect loops that older snippets on the web often cause. Replace example.com and the paths with your own before you save.

Key takeaways

Put RewriteEngine On once near the top of the .htaccess file in your site's folder (usually public_html), then add rules above any application block such as # BEGIN WordPress. Test every redirect as a temporary 302 first, check it with curl -I and a fresh ?t= value in the URL, and switch to 301 only when it works. On Domain India cPanel, DirectAdmin and Webuzo hosting, mod_rewrite is already on; a php_value line or a typo gives a 500 error, so keep a backup copy of the file.

1. Before you add a rule

  • Back up the file. Copy .htaccess to .htaccess.bak in the File Manager before every edit. If the site shows a 500 error, put the backup back first and fix the rule afterwards.
  • One RewriteEngine On is enough, near the top of the file.
  • Order matters. Rules run from top to bottom. Put redirects above application blocks, and specific rules above general ones.
  • Test with 302, then change to 301. Browsers remember a 301 for a long time, so a mistake keeps hurting visitors even after you fix it.

If you are new to rewrite rules, read how mod_rewrite works on Domain India hosting first. It explains patterns, RewriteCond, RewriteBase and the WordPress and Laravel defaults.

2. Flags you will use

FlagWhat it does
R=301 / R=302Permanent or temporary redirect; the address bar changes
LStop processing further rules in this pass
NCMatch upper and lower case
QSAKeep the visitor's query string when rewriting to a script
QSDDrop the old query string from a redirect
NEDon't encode characters such as # or % in the target
FReturn 403 Forbidden

A rule without R is an internal rewrite: Apache serves a different file, but the visitor's address doesn't change. In .htaccess the pattern is tested without a leading slash, so write ^blog/, not ^/blog/.

3. HTTPS and domain redirects

Force HTTPS once your free SSL certificate is active:

apache
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

To settle on www or non-www as well, don't stack a second rule under this one; that makes a two-step redirect. Use the single combined rule in how to redirect non-www to www. cPanel also has a Force HTTPS switch in Domains; use the switch or the rule, not both.

Move a whole domain to a new one, keeping every path (put this in the old domain's folder):

apache
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?olddomain\.in$ [NC]
RewriteRule ^ https://www.newdomain.in%{REQUEST_URI} [R=301,L]

4. Page, folder and query-string redirects

apache
# One page
RewriteRule ^old-page\.html$ /new-page/ [R=301,L]

# A whole folder, keeping the rest of the path
RewriteRule ^old-folder/(.*)$ /new-folder/$1 [R=301,L]

# A URL with a query string: /product.php?id=123 -> /products/blue-widget/
RewriteCond %{QUERY_STRING} (^|&)id=123(&|$)
RewriteRule ^product\.php$ /products/blue-widget/ [R=301,L,QSD]

Escape dots in patterns with a backslash, because a bare dot means "any character". A plain Redirect 301 /old-page.html /new-page/ line also works, but choose one style per file: Redirect and RewriteRule lines are handled by different modules and don't run in the order you wrote them. For choosing between 301, 302, 404 and 410, see links and redirects explained.

5. Clean URLs and trailing slashes

Hide the .html extension, and send visitors who type the old address to the clean one:

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

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.+?)/?$ $1.html [L]

The first block checks THE_REQUEST, the line the visitor's browser actually sent, so it never fires on the internal rewrite made by the second block. That is what prevents a loop. The same pattern for .php is in the mod_rewrite guide.

Remove index.php or index.html from addresses:

apache
RewriteCond %{THE_REQUEST} \s/+(.*?/)?index\.(php|html)[\s?] [NC]
RewriteRule ^ /%1 [R=301,L,NE]

A simpler rule without THE_REQUEST loops, because Apache itself maps / to index.php internally.

Remove a trailing slash (for addresses that aren't real folders):

apache
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [R=301,L]

Or add one (skipping files such as style.css):

apache
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !/$
RewriteCond %{REQUEST_URI} !\.[a-zA-Z0-9]{1,5}$
RewriteRule ^ %{REQUEST_URI}/ [R=301,L]

Choose one style per site, never both. Pretty URLs for your own script:

apache
# /products/shoes -> product.php?category=shoes
RewriteRule ^products/([a-z0-9-]+)/?$ product.php?category=$1 [L,QSA,NC]

# /2026/03/my-article -> blog.php?year=2026&month=03&slug=my-article
RewriteRule ^([0-9]{4})/([0-9]{2})/([a-z0-9-]+)/?$ blog.php?year=$1&month=$2&slug=$3 [L,QSA,NC]

Don't add these to WordPress, Laravel or another framework: they already send every request through index.php.

6. Maintenance mode

Return a proper "503 Service Unavailable" with your own page, so search engines know the outage is temporary. Replace the example IP address with your own so you can still see the site:

apache
ErrorDocument 503 /maintenance.html
<IfModule mod_headers.c>
    Header always set Retry-After "3600"
</IfModule>

RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^198\.51\.100\.23$
RewriteCond %{REQUEST_URI} !^/maintenance\.html$
RewriteRule ^ - [R=503,L]

This is better than redirecting everything to a maintenance page with a 302, which search engines can treat as a real move. Remove the block as soon as you finish. Open the site yourself to confirm the exemption works: behind Cloudflare or another proxy, the address Apache sees may not be yours.

7. Simple security rules

apache
# Block hidden files such as .git and .env, but keep .well-known for SSL checks
RewriteRule (^|/)\.(?!well-known/) - [F]

# Block named bad bots
RewriteCond %{HTTP_USER_AGENT} (BadBot|EvilScraper) [NC]
RewriteRule ^ - [F,L]

# Stop other sites embedding your images
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?example\.com/ [NC]
RewriteRule \.(jpe?g|png|gif|webp)$ - [F,NC]

Many old snippets block every file starting with a dot. That also blocks /.well-known/, which free SSL certificates use to prove you own the domain, so renewals start failing. Bots can fake their user agent, so treat the bot rule as a nuisance filter, not protection.

To block an IP address, use Apache 2.4 access rules rather than the old Order and Deny from lines:

apache
<RequireAll>
    Require all granted
    Require not ip 192.0.2.100
    Require not ip 198.51.100.0/24
</RequireAll>

8. When a rule doesn't behave

SymptomLikely causeFix
500 error right after savingA typo, curly quotes pasted from a word processor, or a line the server doesn't allowRestore the backup, then read your error log
Too many redirectsThe rule matches its own target, or a second HTTPS rule (or Cloudflare) fights itAdd a condition that excludes the target; use one combined rule
Rule does nothingPattern starts with a slash, the rule sits below the WordPress block, or a subfolder has its own .htaccessRemove the slash, move the rule up, or add RewriteOptions Inherit in the subfolder
Old redirect still happensYour browser remembered a 301, or a cached copy was servedTest in a private window and with curl -I plus a fresh ?t= value
bash
curl -I "https://example.com/old-page.html?t=123"

The Location: line shows where the rule sends visitors. The Apache error log names the exact line it didn't understand; see reviewing error logs in cPanel and DirectAdmin.

9. Rewrite rules on Domain India hosting

  • mod_rewrite is loaded and .htaccess is allowed on our cPanel, DirectAdmin and Webuzo servers. There is nothing to enable.
  • cPanel runs nginx in front of Apache. nginx keeps 200, 301 and 302 responses for up to 120 minutes, and can keep serving a cached copy while Apache returns a 500. Always test with a fresh ?t= value right after saving.
  • php_value and php_flag lines give a 500 error, because PHP doesn't run as an Apache module. Set PHP values in your control panel instead.
  • On DirectAdmin, an Options line may use only Indexes, IncludesNOEXEC, MultiViews, SymLinksIfOwnerMatch, FollowSymLinks or None.
  • Compression is already on at server level, so you don't need mod_deflate rules. Browser caching rules with mod_expires work; see mastering .htaccess.
  • Windows (Plesk) hosting runs IIS, which ignores .htaccess; rules go in web.config.

Every Linux shared plan supports these rules. Domain India list prices on 19 September 2026, excluding 18% GST, start at ₹100 a month for DA Starter and ₹125 a month for cPanel Starter.

Frequently asked questions

Do I need to enable mod_rewrite on Domain India hosting?

No. mod_rewrite is loaded on every Domain India cPanel, DirectAdmin and Webuzo server and .htaccess files are allowed. Add RewriteEngine On and your rules to the .htaccess file in your site's folder.

Why does my site show a 500 error after I added a rewrite rule?

Usually a typo, curly quotes pasted from a word processor, a php_value line, or an Options value the server doesn't allow. Restore your backup copy of .htaccess, then check the error log for the exact line.

Should I use a 301 or a 302 redirect?

Test with a 302, which browsers don't remember for long. When the rule works, change it to 301 for a permanent move, so search engines transfer the old page's ranking to the new address.

Why am I still redirected after I removed a rule?

Browsers remember 301 redirects, and on cPanel a copy may still be served from the cache for a while. Test in a private window and with curl -I and a fresh ?t= value in the address.

My free SSL certificate stopped renewing after I added security rules. Why?

A rule that blocks every path starting with a dot also blocks /.well-known/, which the certificate check uses. Exclude .well-known from the rule, as in the example in this guide.

Do .htaccess rules work on Windows hosting?

No. Domain India Windows hosting runs IIS, which ignores .htaccess. Rewrite rules there go in web.config.

Ready to add your rules? Edit .htaccess with the File Manager, compare cPanel and DirectAdmin hosting, or open a support ticket with your domain and the rule you added if the site breaks.

Stuck on a redirect loop or a 500 error?

Send us your domain and the rule you added, and support will help you find the line that is causing it.

Open a ticket

Was this article helpful?

Your answer helps us decide what to improve next.

Still need help? Open a support ticket and our team will reply.

Prefer an app? Add this site to your home screen.Get the app